2012-04-24 5 views
15

Я хочу вычислить точку на данной линии, перпендикулярную к данной точке.Перпендикуляр на отрезке линии от заданной точки

У меня есть отрезок линии AB и имеет сегмент внешней линии точки C. Я хочу рассчитать точку D на AB так, что CD перпендикулярен AB.

Find point D

Я должен найти точку D.

Это очень похоже на this, но я хочу, чтобы рассмотреть Z координату и как это не правильно отображаться в 3D-пространстве.

+0

В отсутствие * программирование * вопрос, это было бы лучше на [math.se] (где он почти наверняка уже дублируется) – AakashM

+1

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

+1

Было бы хорошо указать, на каком языке вы хотите это сделать. – ThomasW

ответ

14

Доказательство: точка D находится на линии CD, перпендикулярной к АВ, и, конечно, D принадлежит к АВ. Запишите произведение Dot двух векторов CD.AB = 0 и выражаем факт, что D принадлежит AB как D = A + t (B-A).

Мы в конечном итоге с 3-х уравнений:

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

Subtitute первых двух уравнений третьего дает:

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

Раздача решить для т получаем:

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

который дает:

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

избавление от негативных признаков:

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

После того, как у вас есть т, вы можете выяснить координаты D из первых двух уравнений.

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

Это игнорирует компонент Z исходного вопроса. – Stephen

0

Поскольку вы не о том, какой язык вы используете, я дам вам общий ответ:

Просто иметь петлю, проходящую через все точки в своем сегменте AB, «нарисовать сегмент» для C от них, получить расстояние от C до D и от A до D и применить теорему pithagoras. Если AD^2 + CD^2 = AC^2, вы нашли свою точку.

Кроме того, вы можете оптимизировать свой код, запустив цикл по кратчайшей (учитывая стороны AD и BD), так как вы найдете эту точку раньше.

4

Существует простая замкнутая форма решения для этого (не требуя никаких петель или приближения) с помощью продукта вектор точки.

Представьте свои точки в виде векторов, где точка A находится в начале координат (0,0), и все остальные точки ссылаются на нее (вы можете легко преобразовать свои точки в этот опорный кадр, вычитая точку A из каждой точки).

В этой системе отсчета точка D является просто vector projection точкой C на вектор B, который выражается в виде:

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

В результате вектор может быть преобразован обратно в исходную систему координат, добавив точку А Это.

3

Точка на линии АВ может быть параметризованных:

М (х) = А + х * (В-А), при х реального.

Вы хотите D = М (х) такое, что DC и AB ортогональны:

точка (В-А, С-М (х)) = 0.

То есть: точка (В, CAx * (В)) = 0, или точка (В, СА) = х * точка (BA, BA), что дает:

х = точка (BA, CA)/точка (BA, BA), которая определена, если 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

Было бы неплохо увидеть небольшое объяснение того, что вы сделали. –

+0

Привет. У меня есть точка a, b и d, и я хочу рассчитать координаты x и y точки c. Могу ли я использовать вашу функцию? Если нет, скажите мне изменения. –

+0

@ MeanCoder точка c имеет бесчисленные возможности, если известны только точки a, b, d. – cuixiping

1

Здесь я преобразовал ответный код с «cuixiping» в код 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

Я не видел ответа на этот вопрос, но у Рона Уорхолика было большое предложение с Vector Projection. ACD - просто правый треугольник.

  1. Создание вектора AC т.е. (Cx - Ах, Cy - Ay)
  2. Создание вектора AB т.е. (Bx - Ax, By - Ay)
  3. Dot продукт AC и AB равен косинус угла между векторами. т. е. cos (theta) = ACx * ABx + ACy * ABy.
  4. Длина вектора равна SQRT (х * х + у * у)
  5. Длина AD = соз (тета) * длина (AC)
  6. Нормализация АВ т.е. (АВх/длина (AB), ПБЯ/длина (AB))
  7. D = A + NAB * длина (AD)
0

Вот реализация питон на основе ответа Corey Ogburn в от this thread.
Он проектирует точку q на отрезок линии, определяемой p1 и p2 приводит к точке r.
Она возвращает нулевое значение, если r выходит за пределы отрезка:

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