Вычислить координаты ортогональной проекции точки на отрезок

126
13 августа 2019, 09:50

Проект для создания чертежей в svg, на нативном js.

Столкнулся со следующей задачей:

Известны координаты точек A B C на плоскости. Точки A B являются началом и концом отрезка AB. Нужно найти координаты ортогональной проекции (точка D) точки С на отрезок АВ. Как это сделать?

Answer 1

Проекцию можно найти, используя скалярное произведение векторов

 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) и пояснения

Answer 2
  • Метод "пересечения":

    Если построить точку С' = (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
    

(Можно показать, что если собрать все вычисления второго метода в одну формулу, то она "сократится" до третьего метода.)

READ ALSO
Упорядоченный массив в JavaScript

Упорядоченный массив в JavaScript

Задан какой-то массив из цифр (JavaScript)Надо проверить,если удалить один элемент из массива,то станет ли массив упорядоченным? (Например - [1,4,2,3]...

114
Возврат view после ajax

Возврат view после ajax

Столкнулся с проблемой: при переходе по страницам через клавиши вперёд и назад браузера (Chrome), загружаемая страница распадается на кодТочнее...

119
Как передать name кнопки при клике с помощью классов?

Как передать name кнопки при клике с помощью классов?

Помогите пожалуйстаНужно, чтобы во время клика на кнопку в соседнем div-e выводился name этой кнопки

138
MySQL индексы и неравенства

MySQL индексы и неравенства

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

198