垂直于给定点的直线

问题描述 投票:34回答:11

如何在给定点的线段上绘制垂线?我的线段定义为(x1,y1),(x2,y2),如果我从点(x3,y3)绘制一个垂直线并且它在点(x4,y4)上遇到线。我想找出这个(x4,y4)。

math geometry 2d computational-geometry
11个回答
62
投票

我为你解决了方程式:

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表示平方


1
投票

这大部分都与Arnkrishn的答案重复。我只想用完整的Mathematica代码片段完成他的部分:

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

0
投票

这是接受的答案的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);
        }

感谢Ray,因为这对我来说非常合适。


0
投票

这是一个矢量化的Matlab函数,用于在m线段上找到n点的成对投影。这里xpyp是持有m by 1不同点坐标的m向量,x1y1x2y2n by 1向量,保持n不同线段的起点和终点的坐标。它返回m by n矩阵,xy,其中x(i, j)y(i, j)i-th点投影到j-th线的坐标。

实际工作在前几行完成,函数的其余部分运行自测试演示,以防在没有参数的情况下调用它。它相对较快,我设法在不到0.05秒的时间内找到了2k点到2k线段的投影。

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

17
投票

来自wiki

在代数中,对于任何线性方程y = mx + b,垂线都将具有(-1 / m)的斜率,与原始斜率的倒数相反。记住“找到垂直线的斜率,翻转分数并改变符号”的口号是有帮助的。回想一下,任何整数a本身都超过一个,可以写成(a / 1)

为了找到也通过特定点(x,y)的给定线的垂线,求解方程y =( - 1 / m)x + b,用m,x和y的已知值代替求解对于b。

线的斜率m,通过(x1,y1)和(x2,y2)是m =(y1-y2)/(x1-x2)


9
投票

我同意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;

8
投票

您经常会发现使用矢量可以使解决方案更清晰......

这是我自己的库中的例程:

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

7
投票

你知道点和斜率,所以新线的等式是:

y-y3=m*(x-x3)

由于线是垂直的,因此斜率是负倒数。你现在有两个方程式,可以求解它们的交集。

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

3
投票

计算连接点(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)

我希望这有帮助。

干杯


2
投票

找出这两条线的斜率,比如斜率是m1和m2,那么m1 * m2 = -1是垂直度的条件。


2
投票

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

1
投票

Mathematica在2014年第10版中引入了RegionNearest[]函数。此函数可用于返回此问题的答案:

{x4,y4} = RegionNearest[Line[{{x1,y1},{x2,y2}}],{x3,y3}]
© www.soinside.com 2019 - 2024. All rights reserved.