特定の点から垂直な特定の線上の点を計算したい。
線分ABがあり、線分の外側に点Cがあります。CDがABに垂直になるように、AB上の点Dを計算したいと思います。
点 D を見つけなければなりません。
これとよく似ていますが、3D空間では正しく表示されないのでZ座標についても考えてみたいと思います。
証明: 点 D は AB に垂直な線 CD 上にあり、もちろん D は AB に属します。2 つのベクトル CD.AB = 0 の内積を書き、D が AB に属することを D=A+t(BA) として表します。
最終的に 3 つの方程式が得られます。
Dx=Ax+t(Bx-Ax)
Dy=Ay+t(By-Ay)
(Dx-Cx)(Bx-Ax)+(Dy-Cy)(By-Ay)=0
最初の 2 つの方程式を 3 番目の方程式に代入すると、次のようになります。
(Ax+t(Bx-Ax)-Cx)(Bx-Ax)+(Ay+t(By-Ay)-Cy)(By-Ay)=0
t について解くために配布すると、次のようになります。
(Ax-Cx)(Bx-Ax)+t(Bx-Ax)(Bx-Ax)+(Ay-Cy)(By-Ay)+t(By-Ay)(By-Ay)=0
これは次を与えます:
t= -[(Ax-Cx)(Bx-Ax)+(Ay-Cy)(By-Ay)]/[(Bx-Ax)^2+(By-Ay)^2]
負の兆候を取り除く:
t=[(Cx-Ax)(Bx-Ax)+(Cy-Ay)(By-Ay)]/[(Bx-Ax)^2+(By-Ay)^2]
t を取得したら、最初の 2 つの方程式から D の座標を計算できます。
Dx=Ax+t(Bx-Ax)
Dy=Ay+t(By-Ay)
function getSpPoint(A,B,C){
var x1=A.x, y1=A.y, x2=B.x, y2=B.y, x3=C.x, y3=C.y;
var px = x2-x1, py = y2-y1, dAB = px*px + py*py;
var u = ((x3 - x1) * px + (y3 - y1) * py) / dAB;
var x = x1 + u * px, y = y1 + u * py;
return {x:x, y:y}; //this is D
}
ベクトル内積を使用した、これに対する単純な閉形式のソリューション(ループや近似を必要としない)があります。
ポイントAが原点(0,0)にあり、他のすべてのポイントがそこから参照されているベクトルとしてポイントを想像してください(すべてのポイントからポイントAを引くことで、ポイントをこの参照フレームに簡単に変換できます)。
この参照フレームでは、点Dは、ベクトルB上の点Cのベクトル射影であり、次のように表されます。
// Per wikipedia this is more efficient than the standard (A . Bhat) * Bhat
Vector projection = Vector.DotProduct(A, B) / Vector.DotProduct(B, B) * B
結果のベクトルは、点Aを追加することにより、元の座標系に戻すことができます。
線分 AB 上の点は、次のようにパラメーター化できます。
M(x)=A+x*(BA)、x 実数の場合。
DC と AB が直交するように D=M(x) が必要です。
dot(BA,CM(x))=0.
つまり、dot(BA,CAx*(BA))=0、または dot(BA,CA)=x*dot(BA,BA) の場合、次のようになります。
x=dot(BA,CA)/dot(BA,BA) であり、A=B でない場合に定義されます。
あなたがやろうとしていることはベクトル投影と呼ばれています
C# でこれが必要な人のために、時間を節約します。
double Ax = ;
double Ay = ;
double Az = ;
double Bx = ;
double By = ;
double Bz = ;
double Cx = ;
double Cy = ;
double Cz = ;
double t = ((Cx - Ax) * (Bx - Ax) + (Cy - Ay) * (By - Ay)) / (Math.Pow(Bx - Ax, 2) + Math.Pow(By - Ay, 2));
double Dx = Ax + t*(Bx - Ax);
double Dy = Ay + t*(By - Ay);
私はこの回答が提供されているのを見ませんでしたが、Ron Warholic が Vector Projection に関して素晴らしい提案をしました。ACD は単なる直角三角形です。
ここで、回答コードを「cuixiping」から 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
使用している言語を述べていないため、一般的な回答を提供します。
ABセグメントのすべてのポイントを通過するループを作成し、それらからCに「セグメントを描画」し、CからDまで、およびAからDまでの距離を取得し、ピタゴラスの定理を適用します. AD^2 + CD^2 = AC^2 の場合、ポイントが見つかりました。
また、最短の側 (AD 側と BD 側を考慮) からループを開始することで、コードを最適化できます。