2012-04-24 19 views
15

Voglio calcolare un punto su una linea data che è perpendicolare da un punto specificato.Perpendicolare su un segmento di linea da un determinato punto

Ho un segmento di linea AB e un punto C al di fuori del segmento di linea. Voglio calcolare un punto D su AB tale che il CD sia perpendicolare a AB.

Find point D

devo trovare il punto D.

E 'molto simile al this, ma voglio prendere in considerazione per coordinare anche Z in quanto non viene visualizzato correttamente nello spazio 3D.

+0

In assenza di una programmazione * * domanda, questo sarebbe meglio su [math.se] (dove è quasi certamente già duplicato) – AakashM

+1

http://stackoverflow.com/questions/1811549/perpendicular-on-a-line-from-a-given-point – jdbertron

+1

Sarebbe bello specificare in quale lingua si desidera. – ThomasW

risposta

14

Prova: punto D è su un CD linea perpendicolare ad AB, e naturalmente D appartiene AB. Annotare il prodotto Punto dei due vettori CD.AB = 0 ed esprimere il fatto che D appartiene ad AB come D = A + t (B-A).

si finisce con 3 equazioni:

Dx=Ax+t(Bx-Ax) 
Dy=Ay+t(By-Ay) 
(Dx-Cx)(Bx-Ax)+(Dy-Cy)(By-Ay)=0 

Subtitute le prime due equazioni nella terza dà:

(Ax+t(Bx-Ax)-Cx)(Bx-Ax)+(Ay+t(By-Ay)-Cy)(By-Ay)=0 

Distribuzione risolvere per t dà:

(Ax-Cx)(Bx-Ax)+t(Bx-Ax)(Bx-Ax)+(Ay-Cy)(By-Ay)+t(By-Ay)(By-Ay)=0 

che fornisce:

t= -[(Ax-Cx)(Bx-Ax)+(Ay-Cy)(By-Ay)]/[(Bx-Ax)^2+(By-Ay)^2] 

sbarazzarsi dei segni negativi:

t=[(Cx-Ax)(Bx-Ax)+(Cy-Ay)(By-Ay)]/[(Bx-Ax)^2+(By-Ay)^2] 

Una volta che avete t, si può capire le coordinate per D dalle prime due equazioni.

Dx=Ax+t(Bx-Ax) 
Dy=Ay+t(By-Ay) 
+2

Ignora il componente Z della domanda originale. – Stephen

0

Dal momento che non stai affermando quale lingua si sta utilizzando, ti darò una risposta generica:

solo per un ciclo che passa per tutti i punti nel segmento AB, "disegnare un segmento" a C da loro, ottieni la distanza da C a D e da A a D, e applica il teorema di Pitagora. Se AD^2 + CD^2 = AC^2, hai trovato il tuo punto.

Inoltre, è possibile ottimizzare il codice avviando il ciclo dal lato più corto (considerando i lati AD e BD), poiché questo punto verrà individuato in precedenza.

4

C'è una semplice soluzione in forma chiusa per questo (che non richiede cicli o approssimazioni) utilizzando il prodotto scalare.

Immaginate i vostri punti come vettori in cui il punto A è all'origine (0,0) e tutti gli altri punti sono referenziati da esso (potete facilmente trasformare i vostri punti in questo fotogramma di riferimento sottraendo il punto A da ogni punto).

In questo sistema di riferimento punto D è semplicemente il vector projection del punto C sul vettore B espressa come:

// Per wikipedia this is more efficient than the standard (A . Bhat) * Bhat 
Vector projection = Vector.DotProduct(A, B)/Vector.DotProduct(B, B) * B 

Il vettore risultato può essere trasformato nuovamente al sistema di coordinate originale aggiungendo punto A al esso.

3

Un punto sulla linea AB può essere parametrizzata:

M (x) = A + x * (B-A), per x reale.

Volete D = M (x) tale che DC e AB sono ortogonali:

punto (B-A, C-M (x)) = 0.

Cioè: punto (BA, CAx * (BA)) = 0, o un punto (BA, CA) = x * punto (BA, BA), dando:

x = punto (BA, CA)/punto (BA, BA) che è definito a meno che A = B.

14
function getSpPoint(A,B,C){ 
    var x1=A.x, y1=A.y, x2=B.x, y2=B.y, x3=C.x, y3=C.y; 
    var px = x2-x1, py = y2-y1, dAB = px*px + py*py; 
    var u = ((x3 - x1) * px + (y3 - y1) * py)/dAB; 
    var x = x1 + u * px, y = y1 + u * py; 
    return {x:x, y:y}; //this is D 
} 

question

+4

Sarebbe bello vedere un piccola spiegazione di quello che hai fatto. –

+0

Ciao. Ho punto A, BeD e voglio calcolare le coordinate X e Y del punto c. Posso usare la tua funzione? Se no, per favore dimmi le modifiche. –

+0

@MeanCoder point c ha innumerevoli possibilità se solo conosce il punto a, b, d. – cuixiping

1

Qui ho convertito il codice di risposta da "cuixiping" al codice MATLAB.

function Pr=getSpPoint(Line,Point) 
% getSpPoint(): find Perpendicular on a line segment from a given point 
x1=Line(1,1); 
y1=Line(1,2); 
x2=Line(2,1); 
y2=Line(2,1); 
x3=Point(1,1); 
y3=Point(1,2); 

px = x2-x1; 
py = y2-y1; 
dAB = px*px + py*py; 

u = ((x3 - x1) * px + (y3 - y1) * py)/dAB; 
x = x1 + u * px; 
y = y1 + u * py; 

Pr=[x,y]; 

end 
0

Non ho visto questa risposta offerta, ma Ron Warholic ha avuto un grande suggerimento con la proiezione vettoriale. ACD è semplicemente un triangolo rettangolo.

  1. Creare il vettore AC ie (Cx - Ax, Cy - Ay)
  2. Creare il vettore AB ie (Bx - Ax, By - Ay)
  3. prodotto scalare di AC e AB è uguale alla coseno dell'angolo tra i vettori. cioè cos (theta) = ACx * ABx + ACy * ABy.
  4. Lunghezza di un vettore è sqrt (x * x + y * y)
  5. Lunghezza AD = cos (theta) * lunghezza (AC)
  6. Normalizzazione AB cioè (ABx/lunghezza (AB), Aby/lunghezza (AB))
  7. D = a + NAB * lunghezza (AD)
0

Ecco un'implementazione pitone base alla risposta di Corey Ogburn da this thread.
Si prevede che il punto q sul segmento di linea definita da p1 e p2 conseguente punto r.
Si tornerà null se r cade al di fuori del segmento di linea:

def is_point_on_line(p1, p2, q): 

    if (p1[0] == p2[0]) and (p1[1] == p2[1]): 
     p1[0] -= 0.00001 

    U = ((q[0] - p1[0]) * (p2[0] - p1[0])) + ((q[1] - p1[1]) * (p2[1] - p1[1])) 
    Udenom = math.pow(p2[0] - p1[0], 2) + math.pow(p2[1] - p1[1], 2) 
    U /= Udenom 

    r = [0, 0] 
    r[0] = p1[0] + (U * (p2[0] - p1[0])) 
    r[1] = p1[1] + (U * (p2[1] - p1[1])) 

    minx = min(p1[0], p2[0]) 
    maxx = max(p1[0], p2[0]) 
    miny = min(p1[1], p2[1]) 
    maxy = max(p1[1], p2[1]) 

    is_valid = (minx <= r[0] <= maxx) and (miny <= r[1] <= maxy) 

    if is_valid: 
     return r 
    else: 
     return None 
Problemi correlati