垂直于给定点的直线

发布于 2024-08-13 12:50:18 字数 94 浏览 10 评论 0原文

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

How can I draw a perpendicular on a line segment from a given point? My line segment is defined as (x1, y1), (x2, y2), If I draw a perpendicular from a point (x3,y3) and it meets to line on point (x4,y4). I want to find out this (x4,y4).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

追风人 2024-08-20 12:50:19

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

I agree with peter.murray.rust, vectors make the solution clearer:

// 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;
差↓一点笑了 2024-08-20 12:50:19

您知道该点和斜率,因此新直线的方程为:

y-y3=m*(x-x3)

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

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

You know both the point and the slope, so the equation for the new line is:

y-y3=m*(x-x3)

Since the line is perpendicular, the slope is the negative reciprocal. You now have two equations and can solve for their intersection.

y-y3=-(1/m)*(x-x3)
y-y1=m*(x-x1)
把昨日还给我 2024-08-20 12:50:19

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

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

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

You will often find that using vectors makes the solution clearer...

Here is a routine from my own library:

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

}

You will have to implement Real2 (a point) and Vector2 and dotProduct() but these should be simple:

The code then looks something like:

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

The library (org.xmlcml.euclid) is at:
http://sourceforge.net/projects/cml/

and there are unit tests which will exercise this method and show you how to use it.

@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);
}
长伴 2024-08-20 12:50:19

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

我希望这个有帮助。

干杯

Compute the slope of the line joining points (x1,y1) and (x2,y2) as m=(y2-y1)/(x2-x1)

Equation of the line joining (x1,y1) and (x2,y2) using point-slope form of line equation, would be y-y2 = m(x-x2)

Slope of the line joining (x3,y3) and (x4,y4) would be -(1/m)

Again, equation of the line joining (x3,y3) and (x4,y4) using point-slope form of line equation, would be y-y3 = -(1/m)(x-x3)

Solve these two line equations as you solve a linear equation in two variables and the values of x and y you get would be your (x4,y4)

I hope this helps.

cheers

﹏半生如梦愿梦如真 2024-08-20 12:50:19

找出两个方向的斜率
线,假设斜率是 m1 和 m2 那么
m1*m2=-1 是条件
垂直度。

Find out the slopes for both the
lines, say slopes are m1 and m2 then
m1*m2=-1 is the condition for
perpendicularity.

旧夏天 2024-08-20 12:50:19

下面问题的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

Matlab function code for the following problem

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
你怎么这么可爱啊 2024-08-20 12:50:19

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

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

Mathematica introduced the function RegionNearest[] in version 10, 2014. This function could be used to return an answer to this question:

{x4,y4} = RegionNearest[Line[{{x1,y1},{x2,y2}}],{x3,y3}]
苄①跕圉湢 2024-08-20 12:50:19

这主要是阿恩克里希恩答案的重复。我只是想用完整的 Mathematica 代码片段来完成他的部分:

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

This is mostly a duplicate of Arnkrishn's answer. I just wanted to complete his section with a complete Mathematica code snippet:

m = (y2 - y1)/(x2 - x1)
eqn1 = y - y3 == -(1/m)*(x - x3)
eqn2 = y - y1 == m*(x - x1)
Solve[eqn1 && eqn2, {x, y}]
梦回旧景 2024-08-20 12:50:19

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

感谢雷,这对我来说非常有效。

This is a C# implementation of the accepted answer. It's also using ArcGis to return a MapPoint as that's what we're using for this project.

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

Thanks to Ray as this worked perfectly for me.

天荒地未老 2024-08-20 12:50:19

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

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

Just for the sake of completeness, here is a solution using homogeneous coordinates.

  1. The homogeneous points are:

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

  2. a line through two points is their cross-product

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

  3. The (signed) distance of a point to a line is their dot product.

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

  4. The vector from p4 to p3 is d times the normal vector of l_12 divided by the squared length of the normal vector.

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

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

Note: if you divide l_12 by the length of the normal vector

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

the distance d will be the euclidean distance.

绝對不後悔。 2024-08-20 12:50:19

首先计算点确定的线性函数
(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。

First, calculate the linear function determined by the points
(x1,y2),(x2,y2).

We get:

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

This step is easy to calculate by the formula of linear function between two points.


Then, calculate the linear function y that goes through (x3,y3).

The function slope is -m, where m is the slope of y1.


Then calculate the const b2 by the coordinates of the point (x3,y3).

We get y2 = -mx+b2 where m and b2 are constants.


The last thing to do is to find the intersection of y1, y2.
You can find x by solving the equation: -mx+b2 = mx+b1, then place x in one of the equations to find y.

俏︾媚 2024-08-20 12:50:19

这工作完美:

function PerpendicularIntersection(p1, p2, p3) {
  let a = p2.y - p1.y
  let a_c = a * a
  let b = p1.x - p2.x
  let b_c = b * b
  let c = p2.x * p1.y - p1.x * p2.y

  var x = ((b_c * p3.x) - (a * b * p3.y) - (a * c)) / (a_c + b_c)
  var y = ((a_c * p3.y) - (a * b * p3.x) - (b * c)) / (a_c + b_c)

  return { x: x, y: y }
}

This work perfectly :

function PerpendicularIntersection(p1, p2, p3) {
  let a = p2.y - p1.y
  let a_c = a * a
  let b = p1.x - p2.x
  let b_c = b * b
  let c = p2.x * p1.y - p1.x * p2.y

  var x = ((b_c * p3.x) - (a * b * p3.y) - (a * c)) / (a_c + b_c)
  var y = ((a_c * p3.y) - (a * b * p3.x) - (b * c)) / (a_c + b_c)

  return { x: x, y: y }
}

安静被遗忘 2024-08-20 12:50:19

这是一个矢量化 Matlab 函数,用于查找 m 点到 n 线段上的成对投影。这里,xpypm x 1 向量,保存 m 个不同点的坐标,并且 x1< /code>、y1x2y2n x 1 向量,保存起始点和结束点的坐标n 条不同的线段。
它返回 m x n 矩阵、xy,其中 x(i, j)y(i, j) 是第 i 点到第 j 线上的投影坐标。

实际工作在前几行中完成,函数的其余部分运行一个自测试演示,以防不带参数调用它。它相对较快,我在不到 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

This is a vectorized Matlab function for finding pairwise projections of m points onto n line segments. Here xp and yp are m by 1 vectors holding coordinates of m different points, and x1, y1, x2 and y2 are n by 1 vectors holding coordinates of start and end points of n different line segments.
It returns m by n matrices, x and y, where x(i, j) and y(i, j) are coordinates of projection of i-th point onto j-th line.

The actual work is done in first few lines and the rest of the function runs a self-test demo, just in case where it is called with no parameters. It's relatively fast, I managed to find projections of 2k points onto 2k line segments in less than 0.05s.

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
想挽留 2024-08-20 12:50:18

我为你解出了方程:

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 均方

I solved the equations for you:

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)

Where ^2 means squared

花辞树 2024-08-20 12:50:18

来自关于垂直性的维基百科文章

在代数中,对于任何线性方程
y=mx + b,垂线全部
坡度为 (-1/m),相反
原始斜率的倒数。它
有助于记住口号“to
求垂线的斜率
线,翻转分数并更改
符号。”回想一下,任何整数 a
本身大于一,并且可以写成
作为(a/1)

求给定点的垂线
线也穿过
特定点 (x, y),求解
方程 y = (-1/m)x + b,代入
已知 m、x 和 y 值
求解b。

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

From the Wikipedia article on Perpendicularity:

In algebra, for any linear equation
y=mx + b, the perpendiculars will all
have a slope of (-1/m), the opposite
reciprocal of the original slope. It
is helpful to memorize the slogan "to
find the slope of the perpendicular
line, flip the fraction and change the
sign." Recall that any whole number a
is itself over one, and can be written
as (a/1)

To find the perpendicular of a given
line which also passes through a
particular point (x, y), solve the
equation y = (-1/m)x + b, substituting
in the known values of m, x, and y to
solve for b.

The slope of the line, m, through (x1, y1) and (x2, y2) is m = (y2 – y1)/(x2 – x1)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文