Проект для создания чертежей в svg, на нативном js.
Столкнулся со следующей задачей:
Известны координаты 3х точек A B C на плоскости. Точки A B являются началом и концом отрезка AB. Нужно найти координаты ортогональной проекции (точка D) точки С на отрезок АВ. Как это сделать?
Проекцию можно найти, используя скалярное произведение векторов
D = A + AB * Dot(AC, AB) / Dot(AB, AB)
В псевдокоде:
abx = B.X - A.X
aby = B.Y - A.Y
dacab = (C.X - A.X) * abx + (C.Y - A.Y) * aby
dab = abx * abx + aby * aby
t = dacab / dab
D.X = A.X + abx * t
D.Y = A.Y + aby * t
Здесь немного другие обозначения (C=P, N=D) и пояснения
Метод "пересечения":
Если построить точку С' = (Cx - (By - Ay), Cy + (Bx - Ax)), то прямая CC' будет перпендикулярна прямой AB. Пересечение прямых AB и CC' даст вам точку D.
Метод "тяжеловат" с вычислительной точки зрения из-за того, что использует пересечение двух прямых в качестве примитива. Но прост в реализации, если такой примитив уже есть под руками.
Метод "расстояния":
Если AA, BB и CC - коэффициенты уравнения прямой, содержащей отрезок AB (легко вычисляются через координаты точек A и B), то величина
DD = AA * Cx + BB * Cy + CC
даст вам знаковое расстояние от этой прямой до точки C, домноженное на |(AA, BB)|. Если к точке C прибавить вектор DD * (-AA, -BB), то мы получим точку, которая смещена относительно C в правильном направлении, но, условно выражаясь, "слишком далеко": расстояние превышает требуемое в |(AA, BB)|^2 раз. Достаточно разделить смещение на эту величину - мы получим требуемую точку D
DD
D = C + ------------ * (-AA, -BB)
|(AA, BB)|^2
Этот метод тоже несколько громоздок из-за "лишних" вычислений уравнения прямой, но может быть полезен, если вы и так уже знаете/вычисляете уравнение прямой, а также если вам в дополнение к точке проекции нужно еще вычислять и расстояние от C до AB.
Метод "скалярного произведения":
Очевидно, что
|(A, D)|
D = A + -------- * (A, B)
|(A, B)|
При этом скалярное произведение вектора (A, C) на вектор (A, B) - это длина проекции (A, D), домноженная на |(A, B)|.
(A, C)•(A, B) = |(A, D)| * |(A, B)|
Тогда
(A, C)•(A, B)
D = A + ------------- * (A, B)
|(A, B)|^2
(Можно показать, что если собрать все вычисления второго метода в одну формулу, то она "сократится" до третьего метода.)
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости