Перпендикуляр на прямой из заданной точки

Как я могу нарисовать перпендикуляр на отрезке прямой из заданной точки? Мой отрезок линии определяется как (x1, y1), (x2, y2), если я нарисую перпендикуляр из точки (x3, y3), и он пересечется с линией в точке (x4, y4). Я хочу это выяснить (x4, y4).


person Zinx    schedule 28.11.2009    source источник
comment
См. Здесь: stackoverflow.com/questions/10301001/   -  person jdbertron    schedule 03.03.2013


Ответы (14)


Я решил для вас уравнения:

k = ((y2-y1) * (x3-x1) - (x2-x1) * (y3-y1)) / ((y2-y1)^2 + (x2-x1)^2)
x4 = x3 - k * (y2-y1)
y4 = y3 + k * (x2-x1)

Где ^ 2 означает квадрат

person Ray Hidayat    schedule 28.11.2009
comment
Надеюсь, я не ошибся, перенеся их с бумаги на компьютер! - person Ray Hidayat; 28.11.2009
comment
Это близко, но неправильно. Ознакомьтесь с доказательством этого ответа здесь: ‹br/› stackoverflow.com/questions/10301001/ - person jdbertron; 04.03.2013
comment
Мои краткие тесты согласны с @jdbertron, что это неверно. - person ThomasW; 30.09.2014
comment
@jbertron: ответ правильный, но убедитесь, что при запуске этого кода вы используете длинные или двойные числа в качестве типа для всех варов, так как с большими числами расчет может легко переполниться, и вы получите неправильный ответ. - person Tom De Leu; 17.10.2014
comment
@RayHidayat: Как мы можем это сделать, если точки находятся в трехмерном пространстве, это означает, что точки (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4). Как мы можем найти конечную точку перпендикулярной прямой (x4, y4, z4), ведущую к линии между (x1, y1, z1) и (x2, y2, z2) и начинающуюся с (x3, y3, z3)? - person manoos; 19.09.2017
comment
Не могли бы вы объяснить, как вы это рассчитали? - person Davidos; 12.04.2021

Из wiki:

В алгебре для любого линейного уравнения y = mx + b все перпендикуляры будут иметь наклон (-1 / m), противоположный исходному наклону. Полезно запомнить слоган «найти наклон перпендикулярной прямой, перевернуть дробь и поменять знак». Напомним, что любое целое число a больше единицы и может быть записано как (a / 1)

Чтобы найти перпендикуляр данной линии, который также проходит через конкретную точку (x, y), решите уравнение y = (-1 / m) x + b, подставляя известные значения m, x и y для решения для б.

Наклон прямой m через (x1, y1) и (x2, y2) равен m = (y1 - y2) / (x1 - x2).

person Mitch Wheat    schedule 28.11.2009

Я согласен с peter.murray.rust, векторы делают решение более понятным:

// first convert line to normalized unit vector
double dx = x2 - x1;
double dy = y2 - y1;
double mag = sqrt(dx*dx + dy*dy);
dx /= mag;
dy /= mag;

// translate the point and get the dot product
double lambda = (dx * (x3 - x1)) + (dy * (y3 - y1));
x4 = (dx * lambda) + x1;
y4 = (dy * lambda) + y1;
person Abraxas    schedule 10.01.2014
comment
Работает как шарм! - person Amjay; 25.02.2017
comment
Использует квадратные корни. Плохой. - person Andrey Tyukin; 02.01.2019
comment
Я знаю, что вопрос был задан 9 лет назад, и теперь я в той же лодке. Как мне вместо этого компьютер (x3, y3)? если я уже знаю прямую, перпендикулярную линию и точку пересечения? - person raisa_; 04.03.2019

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

Вот процедура из моей собственной библиотеки:

public class Line2  {

Real2 from;
Real2 to;
Vector2 vector;
Vector2 unitVector = null;


    public Real2 getNearestPointOnLine(Real2 point) {
        unitVector = to.subtract(from).getUnitVector();
        Vector2 lp = new Vector2(point.subtract(this.from));
        double lambda = unitVector.dotProduct(lp);
        Real2 vv = unitVector.multiplyBy(lambda);
        return from.plus(vv);
    }

}

Вам нужно будет реализовать Real2 (точка), Vector2 и dotProduct (), но они должны быть простыми:

Тогда код будет выглядеть примерно так:

Point2 p1 = new Point2(x1, y1);
Point2 p2 = new Point2(x2, y2);
Point2 p3 = new Point2(x3, y3);
Line2 line = new Line2(p1, p2);
Point2 p4 = getNearestPointOnLine(p3);

Библиотека (org.xmlcml.euclid) находится по адресу: http://sourceforge.net/projects/cml/

и есть модульные тесты, которые будут проверять этот метод и показать вам, как его использовать.

@Test
public final void testGetNearestPointOnLine() {
    Real2 p = l1112.getNearestPointOnLine(new Real2(0., 0.));
    Real2Test.assertEquals("point", new Real2(0.4, -0.2), p, 0.0000001);
}
person peter.murray.rust    schedule 28.11.2009
comment
Также вычисляет ненужные квадратные корни в getUnitVector(). Тоже плохо. - person Andrey Tyukin; 02.01.2019

Вы знаете и точку, и наклон, поэтому уравнение для новой линии:

y-y3=m*(x-x3)

Поскольку линия перпендикулярна, наклон обратный. Теперь у вас есть два уравнения, и вы можете решить их пересечение.

y-y3=-(1/m)*(x-x3)
y-y1=m*(x-x1)
person Dan Lorenc    schedule 28.11.2009
comment
Я знаю только один отрезок (x1, y1) (x2, y2) и точку (x3, y3). Мне нужен способ найти (x4, y4). - person Zinx; 28.11.2009
comment
Итак, найдите наклон между точками 1 и 2 и возьмите отрицательную обратную величину. Помните, что линия имеет вид y=mx+b - m, это наклон, который вы только что нашли, b вы можете рассчитать, используя p3. Теперь у вас есть все, что нужно для линии. - person Thanatos; 28.11.2009

Вычислите наклон линии, соединяющей точки (x1, y1) и (x2, y2) как m=(y2-y1)/(x2-x1)

Уравнение линии, соединяющей (x1, y1) и (x2, y2) с использованием формы линейного уравнения точки-наклона, будет y-y2 = m(x-x2)

Наклон линии, соединяющей (x3, y3) и (x4, y4), будет -(1/m)

Опять же, уравнение линии, соединяющей (x3, y3) и (x4, y4) с использованием формы линейного уравнения точечного уклона, будет y-y3 = -(1/m)(x-x3)

Решите эти два линейных уравнения, решая линейное уравнение с двумя переменными, и значения x и y, которые вы получите, будут вашими (x4, y4)

Надеюсь, это поможет.

ваше здоровье

person Arnkrishn    schedule 28.11.2009

Найдите уклоны для обеих линий, скажем, это m1 и m2, тогда m1 * m2 = -1 является условием перпендикулярности.

person Prasoon Saurav    schedule 28.11.2009
comment
вы не знаете уравнения обеих линий, пока не определите точку пересечения. - person Mitch Wheat; 28.11.2009
comment
взяв точку пересечения как x4, y4, у нас будет два линейных уравнения относительно x4 и y4, и мы сможем легко их решить. - person Prasoon Saurav; 28.11.2009

Код функции 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
person Rajnikant Sharma    schedule 09.03.2016
comment
Я не знаком с Matlab, это встроенная функция? - person oddRaven; 26.11.2016
comment
Нет, это не встроенная функция - person Rajnikant Sharma; 28.11.2016

Mathematica представила функцию RegionNearest[] в версии 10, 2014. Эта функция может использоваться для возврата ответа на этот вопрос:

{x4,y4} = RegionNearest[Line[{{x1,y1},{x2,y2}}],{x3,y3}]
person BeanSith    schedule 10.01.2017

Это в основном дубликат ответа Арнкришна. Я просто хотел завершить его раздел полным фрагментом кода системы Mathematica:

m = (y2 - y1)/(x2 - x1)
eqn1 = y - y3 == -(1/m)*(x - x3)
eqn2 = y - y1 == m*(x - x1)
Solve[eqn1 && eqn2, {x, y}]
person BeanSith    schedule 10.01.2017

Это реализация принятого ответа на C #. Он также использует ArcGis для возврата MapPoint, поскольку это то, что мы используем в этом проекте.

        private MapPoint GenerateLinePoint(double startPointX, double startPointY, double endPointX, double endPointY, double pointX, double pointY)
        {
            double k = ((endPointY - startPointY) * (pointX - startPointX) - (endPointX - startPointX) * (pointY - startPointY)) / (Math.Pow(endPointY - startPointY, 2) 
                + Math.Pow(endPointX - startPointX, 2));
            double resultX = pointX - k * (endPointY - startPointY);
            double resultY = pointY + k * (endPointX - startPointX);

            return new MapPoint(resultX, resultY, 0, SpatialReferences.Wgs84);
        }

Спасибо Рэю, так как у меня это отлично сработало. c # arcgis

person wakeboardfit    schedule 01.05.2019

Это векторизованная функция Matlab для поиска попарных проекций m точек на n отрезки линии. Здесь xp и yp - это m by 1 векторы, содержащие координаты m различных точек, а x1, y1, x2 и y2 - это n by 1 векторы, содержащие координаты начальной и конечной точек n различных отрезков линии. Возвращает m by n матриц, x и y, где x(i, j) и y(i, j) - координаты проекции i -й точки на j-ю линию.

Фактическая работа выполняется в первых нескольких строках, а остальная часть функции запускает демонстрацию самопроверки, на всякий случай, когда она вызывается без параметров. Это относительно быстро, мне удалось найти проекции 2k точек на 2k отрезков линии менее чем за 0,05 секунды.

function [x, y] = projectPointLine(xp, yp, x1, y1, x2, y2)
if nargin > 0
        xd = (x2-x1)';
    yd = (y2-y1)';
    dAB = xd.*xd + yd.*yd;
    u = bsxfun(@rdivide, bsxfun(@times, bsxfun(@minus, xp, x1'), xd) + ...
        bsxfun(@times, bsxfun(@minus, yp, y1'), yd), dAB);
    x = bsxfun(@plus, x1', bsxfun(@times, u, xd));
    y = bsxfun(@plus, y1', bsxfun(@times, u, yd));
else
    nLine = 3;
    nPoint = 2;
    xp = rand(nPoint, 1) * 2 -1;
    yp = rand(nPoint, 1) * 2 -1;
    x1 = rand(nLine, 1) * 2 -1;
    y1 = rand(nLine, 1) * 2 -1;
    x2 = rand(nLine, 1) * 2 -1;
    y2 = rand(nLine, 1) * 2 -1;
    tic;
    [x, y] = projectPointLine(xp, yp, x1, y1, x2, y2);
    toc
    close all;
    plot([x1'; x2'], [y1'; y2'], '.-', 'linewidth', 2, 'markersize', 20);
    axis equal;
    hold on
    C = lines(nPoint + nLine);
    for i=1:nPoint
        scatter(x(i, :), y(i, :), 100, C(i+nLine, :), 'x', 'linewidth', 2);
        scatter(xp(i), yp(i), 100, C(i+nLine, :), 'x', 'linewidth', 2);
    end
    for i=1:nLine
        scatter(x(:, i)', y(:, i)', 100, C(i, :), 'o', 'linewidth', 2);
    end
end
end
person saastn    schedule 28.05.2019

Вот решение, использующее однородные координаты, для полноты картины.

  1. Однородные точки:

    p1 = (x1,y1,1), p2 = (x2,y2,1), p3 = (x3,y3,1)

  2. линия, проходящая через две точки, является их перекрестным произведением

    l_12 := p1 x p2 = (y1-y2, x2-x1, x1*y2 - x2*y1)

  3. Расстояние (подписанное) от точки до линии - это их скалярное произведение.

    d := l_12 * p3 = x3*(y1-y2) + y3*(x2-x1) + x1*y2 - x2*y1

  4. Вектор от p4 до p3 в d раз больше вектора нормали l_12, деленного на квадрат длины вектора нормали.

    n2 := (y1-y2)^2 + (x2-x1)^2

    p4 := p3 + d/n2*(y1-y2, x2-x1, 0)

Примечание: если вы разделите l_12 на длину вектора нормали

l_12: = l_12 / sqrt ((y1-y2) ^ 2 + (x2-x1) ^ 2)

расстояние d будет евклидовым расстоянием.

person Tobias    schedule 03.11.2019

Сначала вычислите линейную функцию, определяемую точками (x1,y2),(x2,y2).

Мы получили:

y1 = mx+b1 where m and b1 are constants.

Этот шаг легко вычислить по формуле линейной функции между двумя точками.


Затем вычислите линейную функцию y, проходящую через (x3, y3).

Наклон функции равен -m, где m - наклон y1.


Затем вычислите const b2 по координатам точки (x3, y3).

Получаем y2 = -mx + b2, где m и b2 - константы.


Последнее, что нужно сделать, это найти пересечение y1, y2. Вы можете найти x, решив уравнение: -mx+b2 = mx+b1, затем поместите x в одно из уравнений, чтобы найти y.

person Michael Toker    schedule 16.11.2020