質問

特定の点から線分上に垂線を描画するにはどうすればよいですか?私の線分は、(x3、y3)から垂線を引き、それが点(x4、y4)の線と交わる場合、(x1、y1)、(x2、y2)として定義されます。これを見つけたい(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は2乗を意味する

他のヒント

wiki から:

  

代数では、任意の一次方程式   y = mx + b、垂線はすべて   傾きが(-1 / m)、反対   元の勾配の逆数。それ   スローガンを覚えるのに役立ちます"   垂線の勾配を見つける   行、分数を反転し、変更   サイン。"任意の整数a   それ自体が1以上であり、書くことができます   as(a / 1)

     

特定の垂線を見つけるには   を通過する線   特定の点(x、y)、解く   方程式y =(-1 / m)x + b、代入   m、x、yの既知の値で   bを解きます。

(x1、y1)および(x2、y2)を通る線mの勾配は、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)

直線は垂直なので、勾配は負の逆数です。これで2つの方程式ができ、それらの交差を解くことができます。

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)になります

2つの変数で線形方程式を解くときにこれらの2つの線形方程式を解き、得られる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は、バージョン10、2014で関数 RegionNearest [] を導入しました。この関数を使用して、この質問に対する答えを返すことができます。

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

これは主に、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}]

これは、受け入れられた回答の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に感謝します。

これは、 m 点の n 線分へのペアワイズ投影を見つけるためのベクトル化されたMatlab関数です。ここで、 xp および yp は、 m の異なる点の座標を保持する m x 1 ベクトル、および x1 y1 x2 、および y2 は、 n x 1 ベクトルの開始点と終了点の座標を保持します n 異なる線分。 m x n 行列、 x および y を返します。ここで、 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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top