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

StackOverflow https://stackoverflow.com/questions/1811549

Вопрос

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

Это было полезно?

Решение

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

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 означает квадрат

Другие советы

Из вики :

  

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

     

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

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

Я согласен с 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;

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

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

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);
}

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

y-y3=m*(x-x3)

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

y-y3=-(1/m)*(x-x3)
y-y1=m*(x-x1)

Вычислите наклон точек соединения линий (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).

Я надеюсь, что это поможет.

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

  

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

Код функции 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

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

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

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

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

Это реализация принятого ответа на 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);
        }

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

Это векторизованная функция Matlab для нахождения попарных проекций точек m на отрезки n . Здесь xp и yp представляют собой векторы m на 1 , содержащие координаты m различных точек, и x1 , y1 , x2 и y2 - это векторы n на 1 , содержащие координаты начальной и конечной точек n разные отрезки. Возвращает матрицы m по 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top