2008-09-25 11 views
36

Tengo una línea que dibujo en una ventana y dejo que el usuario la arrastre. Entonces, mi línea está definida por dos puntos: (x1, y1) y (x2, y2). Pero ahora me gustaría dibujar "límites" al final de mi línea, es decir, líneas perpendiculares cortas en cada uno de mis puntos finales. Las tapas deben tener N píxeles de longitud.¿Cómo se puede encontrar un punto a una distancia perpendicular dada de una línea?

Por lo tanto, para dibujar mi línea "cap" en el punto final (x1, y1), necesito encontrar dos puntos que formen una línea perpendicular y donde cada uno de sus puntos esté a N/2 píxeles del punto (x1 , y1).

Entonces, ¿cómo se calcula un punto (x3, y3) dado que necesita estar a una distancia perpendicular N/2 de distancia del punto final (x1, y1) de una línea conocida, es decir, la línea definida por (x1 , y1) y (x2, y2)?

+0

Para una solución resuelta detallada, [consulte aquí] (http://stackoverflow.com/a/17195324/183120). – legends2k

Respuesta

72

Necesita calcular un vector unitario que sea perpendicular al segmento de línea. Evite calcular la pendiente porque eso puede llevar a dividir entre cero errores.

dx = x1-x2 
dy = y1-y2 
dist = sqrt(dx*dx + dy*dy) 
dx /= dist 
dy /= dist 
x3 = x1 + (N/2)*dy 
y3 = y1 - (N/2)*dx 
x4 = x1 - (N/2)*dy 
y4 = y1 + (N/2)*dx 
+1

Sigo pensando que debe haber una manera de evitar esa desagradable raíz cuadrada allí, posiblemente usando Breshenham's Line, pero no puedo pensar en eso. –

+2

Creo que tienes un error de signo en tus cálculos o en los puntos 3 y 4. Usa (+ - - +) o (- + + -) en las últimas cuatro líneas, ¿no? – dmckee

+6

¡Gracias, esto funciona genial! – AZDean

5

Sólo evaluar el versor ortogonal y se multiplica por N/2

vx = x2-x1 
vy = y2-y1 
len = sqrt(vx*vx + vy*vy) 
ux = -vy/len 
uy = vx/len 

x3 = x1 + N/2 * ux 
Y3 = y1 + N/2 * uy 

x4 = x1 - N/2 * ux 
Y4 = y1 - N/2 * uy 
1

Si se quiere evitar una raíz cuadrada, haga lo siguiente:

in: line_length, cap_length, rotation, position of line centre 

define points: 
    tl (-line_length/2, cap_length) 
    tr (line_length/2, cap_length) 
    bl (-line_length/2, -cap_length) 
    br (line_length/2, -cap_length) 

rotate the four points by 'rotation' 
offset four points by 'position' 

drawline (midpoint tl,bl to midpoint tr,br) 
drawline (tl to bl) 
drawline (tr to br) 
3

Puesto que los vectores de 2 a 1 y 1 a 3 son perpendiculares, su producto escalar es 0.

Esto te deja con dos incógnitas: x de 1 a 3 (x1 3), y y de 1 a 3 (y13)

Usa el teorema de Pitágoras para obtener otra ecuación para esas incógnitas.

Resolver para cada desconocido por sustitución ...

Esto requiere elevar al cuadrado y unsquaring, por lo que se pierde la señal asociada con sus ecuaciones.

Para determinar el signo, considere:

while x21 is negative, y13 will be positive 
while x21 is positive, y13 will be negative 
while y21 is positive, x13 will be positive 
while y21 is negative, x13 will be negative 

Conocido: Punto 1: x1, y1

Conocido: la etapa 2: x2, y2

x21 = x1 - x2 
y21 = y1 - y2 

Conocido: distancia | 1 -> 3 | : Teorema de Pitágoras

x13^2 + y13^2 = |1->3|^2 
x13^2 + y13^2 = (N/2)^2 

conocidos:: N/2

ecuación un ángulo 2-1-3: ángulo recto

vectores 2-> 1 y 1-> 3 son perpendiculares

2-> 1 dot 1-> 3 es 0

ecuación b: producto escalar = 0

x21*x13 + y21*y13 = 2->1 dot 1->3 
x21*x13 + y21*y13 = 0 

relación b/w x13 y Y13:

x21*x13 = -y21*y13 
x13 = -(y21/x21)y13 

x13 = -phi*y13 

ecuación a: resuelto para y13 con relación

plug x13 into a 
phi^2*y13^2 + y13^2 = |1->3|^2 

    factor out y13 
y13^2 * (phi^2 + 1) = 

    plug in phi 
y13^2 * (y21^2/x21^2 + 1) = 

    multiply both sides by x21^2 
y13^2 * (y21^2 + x21^2) = |1->3|^2 * x21^2 

    plug in Pythagorean theorem of 2->1 
y13^2 * |2->1|^2 = |1->3|^2 * x21^2 

    take square root of both sides 
y13 * |2->1| = |1->3| * x21 

    divide both sides by the length of 1->2 
y13 = (|1->3|/|2->1|) *x21 

    lets call the ratio of 1->3 to 2->1 lengths psi 
y13 = psi * x21 

    check the signs 
    when x21 is negative, y13 will be positive 
    when x21 is positive, y13 will be negative 

y13 = -psi * x21 

ecuación a: resuelto para x13 con relación

plug y13 into a 
x13^2 + x13^2/phi^2 = |1->3|^2 

    factor out x13 
x13^2 * (1 + 1/phi^2) = 

    plug in phi 
x13^2 * (1 + x21^2/y21^2) = 

    multiply both sides by y21^2 
x13^2 * (y21^2 + x21^2) = |1->3|^2 * y21^2 

    plug in Pythagorean theorem of 2->1 
x13^2 * |2->1|^2 = |1->3|^2 * y21^2 

    take square root of both sides 
x13 * |2->1| = |1->3| * y21 

    divide both sides by the length of 2->1 
x13 = (|1->3|/|2->1|) *y21 

    lets call the ratio of |1->3| to |2->1| psi 
x13 = psi * y21 

    check the signs 
    when y21 is negative, x13 will be negative 
    when y21 is positive, x13 will be negative 

x13 = psi * y21 

para condensar

x21 = x1 - x2 
y21 = y1 - y2 

|2->1| = sqrt(x21^2 + y^21^2) 
|1->3| = N/2 

psi = |1->3|/|2->1| 

y13 = -psi * x21 
x13 = psi * y21 

Normalmente no haría esto, pero lo resolví en el trabajo y pensé que si lo explicaba a fondo me ayudaría a solidificar mi conocimiento.

Cuestiones relacionadas