#【概要】
タイトルの通り、指定した座標に一番近い、直線上の座標を求めます。
今回は例として、下の画像のようにコーンから伸びる青い線上の、スフィアの座標に一番近い座標(赤い点の座標)を求めます。
尚、直線はただの方向ベクトルとして扱うので、終点は考慮していません。
※2021/05/21追記
相対座標への変換などを行わなくても、UKismetMathLibrary::FindClosestPointOnLine
で同じ結果が得られるようです。
#【実装】
先に実装をお見せすると、以下のような形になります。
ProjectVectorOnToVector
のノードを使うことにより、座標を線に投影することが出来ます。
引数のVにはコーンから見たスフィアの相対座標、TargetにはコーンのUpVector(尖っている方向)のベクトルを与えています。
ReturnValueは原点基準の座標になっているので、コーンの座標に足して最終的な座標としています。
#【解説】
折角なのでProjectVectorOnToVector
の中身でやっていることを含め、見ていきたいと思います。
まず現状のActorの配置を図に表すと以下のようになります。
原点:ワールドの原点
A:コーンの座標
A':コーンの座標にコーンのUpVectorを足した座標
B:スフィアの座標
P:求めたい座標
点に一番近い直線上の座標を求めるには、正射影ベクトルの公式を使用します。
https://examist.jp/mathematics/planar-vector/seisyaei-vector/
この公式に今回の例を当てはめると以下のようになります。
\vec{AP} = \vec{AA'}*((\vec{AA'}・\vec{AB})/(|\vec{AA'}|*|\vec{AA'}|))\\
ベクトルの内積は各成分同士を掛けて全部足すことで求められるので、以下のようになります。
\vec{AP} = (1,0)*(((1*3)+(0*2)/(1*1))\\
=(3,0)
これでPの座標が(3,0)であることが分かりました。
最後に、原点基準で計算していたので、元の座標系に戻す為にコーンの座標を足して、最終的な座標は(6,3)になりました。
以上が実装のところでお見せしたBlueprintの詳細になります。
実際にProjectVectorOnToVector
の中を見ると、同じように正射影ベクトルの公式を使用していることが分かると思います。
FORCEINLINE FVector FVector::ProjectOnTo(const FVector& A) const
{
return (A * ((*this | A) / (A | A)));
}
割る値が公式のように|→a|の2乗ではないですが、同じベクトルの内積は大きさの2乗とイコールなので、同じ意味になります。
https://kou.benesse.co.jp/nigate/math/a13m1502.html