2008-09-25 29 views
36

Ho una linea che disegno in una finestra e lascio che l'utente la trascini. Quindi, la mia linea è definita da due punti: (x1, y1) e (x2, y2). Ma ora mi piacerebbe disegnare "cappucci" alla fine della mia linea, cioè linee corte perpendicolari in ciascuno dei miei punti finali. I tappi dovrebbero essere lunghi N pixel.Come si trova un punto a una determinata distanza perpendicolare da una linea?

Quindi, per disegnare la mia linea "cap" sul punto finale (x1, y1), ho bisogno di trovare due punti che formano una linea perpendicolare e dove ognuno dei suoi punti è N/2 pixel di distanza dal punto (x1 , y1).

Così come si calcola un punto (x3, y3) dato che deve essere a una distanza perpendicolare N/2 lontano dal punto finale (x1, y1) di una linea nota, cioè la linea definita da (x1 , y1) e (x2, y2)?

+0

Per una soluzione dettagliata, [vedere qui] (http://stackoverflow.com/a/17195324/183120). – legends2k

risposta

72

È necessario calcolare un vettore unitario perpendicolare al segmento di linea. Evitare di calcolare la pendenza perché ciò può portare a dividere per zero gli errori.

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

Continuo a pensare che ci debba essere un modo per evitare quel brutto sqrt lì dentro, possibilmente usando la Linea di Breshenham, ma non riesco a pensarlo fuori mano. –

+2

Penso che tu abbia un errore di segno nei tuoi calcoli o nei punti 3 e 4. Usa (+ - - +) o (- + + -) nelle ultime quattro righe, no? – dmckee

+6

Grazie, funziona benissimo! – AZDean

5

Basta valutare il versore ortogonale e moltiplicare per 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

Se si vuole evitare uno sqrt, effettuare le seguenti operazioni:

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

Dal momento che i vettori da 2 a 1 e 1 a 3 sono perpendicolari, il loro prodotto di punti è 0.

Questo ti lascia con due incognite: x da 1 a 3 (x1 3) e y da 1 a 3 (y13)

Utilizzare il teorema di Pitagora per ottenere un'altra equazione per quelle sconosciute.

Risolvere per ogni sconosciuto per sostituzione ...

Ciò richiede la squadratura e unsquaring, così si perde il segno associato con le equazioni.

Per determinare il segno, prendere in considerazione:

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 

noto: Punto 1: x1, y1

noto: Punto 2: x2, y2

x21 = x1 - x2 
y21 = y1 - y2 

noto: a distanza | 1 -> 3 | : N/2

equazione a: teorema di Pitagora

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

noti: angolo 2-1-3: angolo retto

vettori 2-> 1 e 1-> 3 sono perpendicolari

2-> 1 dot 1-> 3 è 0

equazione b: prodotto scalare = 0

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

rapporto b/w x13 e y13:

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

x13 = -phi*y13 

equazione a: risolto per y13 con rapporto

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 

equazione a: risolto per x13 con rapporto

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 

di condensare

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 non lo farei, ma l'ho risolto al lavoro e ho pensato che spiegarlo accuratamente mi avrebbe aiutato a consolidare le mie conoscenze.

Problemi correlati