2012-04-24 15 views
15

Quiero calcular un punto en una línea dada que es perpendicular desde un punto dado.Perpendicular en un segmento de línea desde un punto dado

Tengo un segmento de línea AB y un segmento de línea exterior en el punto C. Quiero calcular un punto D en AB de manera que el CD sea perpendicular a AB.

Find point D

tengo que encontrar el punto D.

Es bastante similar a this, pero quiero tener en cuenta a la coordenada Z también, ya que no aparece correctamente en el espacio 3D.

+0

En ausencia de un * pregunta, esto sería mejor en [math.se] (donde es casi seguro que ya duplica la programación *) – AakashM

+1

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

+1

sería bueno para especificar qué idioma desea que esta en. – ThomasW

Respuesta

14

Prueba: El punto D está en una línea perpendicular a AB CD, y por supuesto D pertenece a AB. Escriba el producto Punto de los dos vectores CD.AB = 0, y exprese el hecho de que D pertenece a AB como D = A + t (B-A).

terminamos con 3 ecuaciones:

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

subtitute las primeras dos ecuaciones en la tercera uno da:

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

Distribuir a despejar t da:

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

que da:

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

deshacerse de los signos negativos:

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

Una vez que tenga t, se puede averiguar las coordenadas de D a partir de las dos primeras ecuaciones.

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

Esto ignora el componente Z de la pregunta original. – Stephen

0

ya que no está afirmando que el lenguaje que está usando, te voy a dar una respuesta genérica:

Sólo tienen un bucle pasando por todos los puntos en el segmento AB, "dibujar un segmento" a C de ellos, obtenga la distancia de C a D y de A a D, y aplique el teorema de pithagoras. Si AD^2 + CD^2 = AC^2, entonces ha encontrado su punto.

Además, puede optimizar su código comenzando el ciclo por el lado más corto (considerando los lados AD y BD), ya que encontrará ese punto más temprano.

4

Hay una sencilla solución de forma cerrada para esto (que no requiere de bucles o aproximaciones) utilizando el producto escalar de vectores.

Imagina tus puntos como vectores donde el punto A está en el origen (0,0) y todos los otros puntos se referencian desde él (puedes transformar fácilmente tus puntos a este marco de referencia restando el punto A de cada punto).

En este punto de referencia D es simplemente el vector projection del punto C en el vector B que se expresa como:

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

El vector de resultado se puede transformar de vuelta al sistema de coordenadas original agregando el punto A hasta eso.

3

Un punto en la línea AB puede parametrizarse por:

M (x) = A + x * (B-A), para x real.

¿Quieres D = M (x) tal que DC y AB son ortogonales:

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

Eso es: punto (BA, CAx * (BA)) = 0, o un punto (BA, CA) = x * punto (BA, BA), dando:

x = punto (BA, CA)/dot (BA, BA) que se define a menos que 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

sería agradable ver una pequeña explicación de lo que hiciste –

+0

Hola. Tengo el punto a, b y d y quiero calcular las coordenadas xey del punto c. ¿Puedo usar tu función? Si no, por favor dígame las modificaciones. –

+0

@MeanCoder El punto c tiene innumerables posibilidades si solo conoce el punto a, b, d. – cuixiping

1

Aquí he convertido el código de respuesta de "cuixiping" al código de 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

no vi esta respuesta ofrecida, pero Ron Warholic tenido una gran sugerencia con la proyección del vector. ACD es simplemente un triángulo rectángulo.

  1. crear el vector AC es decir (Cx - Ax, Cy - Ay)
  2. crear el vector AB es decir (Bx - Ax, By - Ay)
  3. producto escalar de AC y AB es igual a la coseno del ángulo entre los vectores. es decir, cos (theta) = ACx * ABx + ACy * ABy.
  4. longitud de un vector es sqrt (x * x + y * y)
  5. Longitud de AD = cos (theta) * longitud (AC)
  6. Normalizar AB es decir (ABX/longitud (AB), aby/longitud (AB))
  7. D = a + NAB * longitud (AD)
0

Aquí es una implementación de Python basado en la respuesta de Corey Ogburn de this thread.
Proyecta el punto q sobre el segmento lineal definido por p1 y p2 resultante en el punto r.
Se devolverá un valor nulo si r queda fuera del segmento de línea:

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 
Cuestiones relacionadas