41

如何从给定点在线段上绘制垂线?我的线段定义为 (x1, y1), (x2, y2),如果我从点 (x3,y3) 画一条垂线,它与点 (x4,y4) 上的线相交。我想找出这个(x4,y4)。

4

14 回答 14

71

我为你解了方程:

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

于 2009-11-28T05:07:04.747 回答
19

来自维基

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

要找到也通过特定点 (x, y) 的给定直线的垂线,请求解方程 y = (-1/m)x + b,代入 m、x 和 y 的已知值以求解对于 b。

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

于 2009-11-28T04:29:41.547 回答
11

我同意 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;
于 2014-01-10T22:29:44.300 回答
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 (a point) 和 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);
}
于 2009-11-28T04:45:09.480 回答
7

你知道点和斜率,所以新线的方程是:

y-y3=m*(x-x3)

因为直线是垂直的,所以斜率是负倒数。您现在有两个方程,可以求解它们的交集。

y-y3=-(1/m)*(x-x3)
y-y1=m*(x-x1)
于 2009-11-28T04:31:53.460 回答
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)

我希望这有帮助。

干杯

于 2009-11-28T04:45:19.270 回答
2

找出两条线的斜率,假设斜率为 m1 和 m2,则 m1*m2=-1是垂直度的条件。

于 2009-11-28T04:31:03.197 回答
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
于 2016-03-09T11:46:55.720 回答
1

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

{x4,y4} = RegionNearest[Line[{{x1,y1},{x2,y2}}],{x3,y3}]
于 2017-01-10T01:47:08.350 回答
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}]
于 2017-01-10T04:49:16.477 回答
1

这是已接受答案的 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,因为这对我来说非常有效。

于 2019-05-01T15:16:40.403 回答
0

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

实际工作在前几行中完成,函数的其余部分运行自检演示,以防不带参数调用它。它相对较快,我设法在不到 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
于 2019-05-28T16:38:38.910 回答
0

只是为了完整起见,这里是使用齐次坐标的解决方案。

  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 将是欧几里得距离。

于 2019-11-03T13:31:11.753 回答
0

首先,计算由点确定的线性函数 (x1,y2),(x2,y2)

我们得到:

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

这一步很容易通过两点之间的线性函数公式来计算。


然后,计算通过 (x3,y3) 的线性函数 y。

函数斜率是 -m,其中 m 是 y1 的斜率。


然后通过点 (x3,y3) 的坐标计算 const b2。

我们得到 y2 = -mx+b2 其中 m 和 b2 是常数。


最后要做的是找到y1,y2的交点。您可以通过求解方程找到 x:-mx+b2 = mx+b1,然后将 x 放入其中一个方程以找到 y。

于 2020-11-16T14:52:15.997 回答