Перпендикулярно отрезку линии от заданной точки
Я хочу вычислить точку на заданной прямой, перпендикулярную к данной точке.
У меня есть отрезок AB и есть сегмент внешней линии точки C. Я хочу вычислить точку D на AB так, что CD перпендикулярен AB.
![Find point D]()
Мне нужно найти точку D.
Это очень похоже на this, но я хочу рассмотреть и координату Z, так как она не отображается правильно в 3D-пространстве.
Ответы
Ответ 1
Доказательство:
Точка D находится на линии CD, перпендикулярной AB, и, конечно, D принадлежит AB.
Запишем произведение 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
Подставляем первые два уравнения в третий:
(Ax+t(Bx-Ax)-Cx)(Bx-Ax)+(Ay+t(By-Ay)-Cy)(By-Ay)=0
Распространение решения для t дает:
(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]
Как только у вас есть t, вы можете определить координаты для D из первых двух уравнений.
Dx=Ax+t(Bx-Ax)
Dy=Ay+t(By-Ay)
Ответ 2
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]()
Ответ 3
Для этого есть простое замкнутое решение (не требующее петель или аппроксимаций) с использованием векторного точечного произведения.
Представьте свои точки как векторы, где точка A находится в начале координат (0,0), и все остальные точки ссылаются на нее (вы можете легко преобразовать свои точки в этот опорный кадр, вычитая точку A из каждой точки).
В этой точке отсчета D является просто вектор проекции точки 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
Вектор результата можно преобразовать обратно в исходную систему координат, добавив к нему точку A.
Ответ 4
Точку на линии AB можно параметризовать:
M (x) = A + x * (B-A), для вещественного x.
Вы хотите, чтобы D = M (x), что DC и AB ортогональны:
точка (В-А, С-М (х)) = 0.
То есть: точка (B-A, C-A-x * (B-A)) = 0 или точка (B-A, C-A) = x * точка (B-A, B-A), дающая:
x = точка (B-A, C-A)/точка (B-A, B-A), которая определена, если A = B.
Ответ 5
То, что вы пытаетесь сделать, называется векторная проекция
Ответ 6
Здесь я преобразовал ответный код из "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
Ответ 7
Поскольку вы не указываете, какой язык вы используете, я дам вам общий ответ:
Просто проведите петлю, проходящую через все точки вашего сегмента AB, "отрисуйте отрезок" до C от них, получите расстояние от C до D и от A до D и примените теорему pithagoras. Если AD ^ 2 + CD ^ 2 = AC ^ 2, вы нашли свою точку.
Кроме того, вы можете оптимизировать свой код, запустив цикл по кратчайшей (учитывая стороны AD и BD), так как вы найдете эту точку раньше.
Ответ 8
Я не видел ответа на этот вопрос, но у Рона Уорхолика было большое предложение с Vector Projection. ACD - просто правый треугольник.
- Создайте вектор AC i.e(Cx-Ax, Cy-Ay)
- Создайте вектор AB i.e(Bx - Ax, By - Ay)
- Точечный продукт AC и AB равен косинусу угла между векторами. i.e cos (theta) = ACx * ABx + ACy * ABy.
- Длина вектора - это sqrt (x * x + y * y)
- Длина AD = cos (theta) * длина (AC)
- Нормализовать AB i.e(ABx/length (AB), ABy/length (AB))
- D = A + NAB * length (AD)
Ответ 9
Вот реализация python на основе ответа Кори Огберна из этого потока.
Он проецирует точку q
на сегмент линии, определяемый p1
и p2
, в результате чего точка r
.
Он вернет значение null, если 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