web-dev-qa-db-ja.com

3Dポイントを2D平面に投影する

Aを3D座標x、y、zを持つポイントとし、それらを2D座標x、yに変換したいとします。投影は、与えられた法線によって定義される平面上で直交します。法線が実際に軸の1つである単純なケースでは、座標を削除するだけで簡単に解決できますが、発生する可能性が高い他のケースはどうですか?

31
Lighthink

ターゲットポイントがある場合[〜#〜] p [〜#〜]座標r_P = (x,y,z)で、通常のn=(nx,ny,nz)の平面で、Originを定義する必要があります平面、およびxおよびyの2つの直交方向。たとえば、Originがr_O = (ox, oy, oz)にあり、平面内の2つの座標軸がe_1 = (ex_1,ey_1,ez_1)e_2 = (ex_2,ey_2,ez_2)で定義されている場合、直交性はDot(n,e_1)=0Dot(n,e_2)=0Dot(e_1,e_2)=0(ベクトルドット積)。すべての方向ベクトルshouldは正規化されていることに注意してください(大きさは1でなければなりません)。

ターゲットポイント[〜#〜] p [〜#〜]は、方程式に従う必要があります。

r_P = r_O + t_1*e_1 + t_2*e_2 + s*n

ここで、t_1およびt_2は、e_1およびe_2およびsに沿った2D座標で、平面と点の間の通常の分離(距離)です。

投影によってスカラーが見つかります:

s = Dot(n, r_P-r_O)
t_1 = Dot(e_1, r_P-r_O)    
t_2 = Dot(e_2, r_P-r_O)

平面Origin r_O = (-1,3,1)と法線の例:

n = r_O/|r_O| = (-1/√11, 3/√11, 1/√11)

たとえば、2D座標の直交方向を選択する必要があります。

e_1 = (1/√2, 0 ,1/√2)
e_2 = (-3/√22, -2/√22, 3/√22)

Dot(n,e_1) = 0およびDot(n,e_2) = 0およびDot(e_1, e_2) = 0など。

ポイントの2D座標[〜#〜] p [〜#〜]r_P=(1,7,-3)は次のとおりです。

t_1 = Dot(e_1, r_P-r_O) = ( 1/√2,0,1/√2)·( (1,7,-3)-(-1,3,1) ) =  -√2
t_2 = Dot(e_2, r_P-r_O) = (-3/√22, -2/√22, 3/√22)·( (1,7,-3)-(-1,3,1) ) = -26/√22

面外分離:

s = Dot(n, r_P-r_O) = 6/√11
31
ja72

Aの法線方向への射影を見つける 。次に、その投影をAから減算します。残っているのは、Aの直交平面への投影です。

ユニットの法線方向nへのAの射影は、次の式で与えられます。

_(A · n) n
_

A = (x, y, z)で、法線の単位がn = (nx, ny, nz)で与えられる場合、nへのAの射影は

_(x*nx + y*ny + z*nz) n
_

したがって、直交平面へのAの投影は

_A - (A · n) n
= (x, y, z) - (x*nx + y*ny + z*nz) (nx, ny, nz)
_

たとえば、A =(1,2,3)で、nが方向(4,5,6)の法線単位である場合、

_In [12]: A
Out[12]: array([1, 2, 3])
In [17]: d
Out[17]: array([4, 5, 6])

In [20]: n = d/sqrt(4*4 + 5*5 + 6*6)   # make n a unit vector
In [13]: n
Out[13]: array([ 0.45584231,  0.56980288,  0.68376346])
_

したがって、直交平面へのAの投影は

_In [15]: A - np.dot(A,n)*n
Out[15]: array([-0.66233766, -0.07792208,  0.50649351])
_

2D座標を見つける方法:

直交平面上に2D座標系を定義する必要があります。つまり、_x-axis_と_y-axis_の場所を定義する必要があります。たとえば、(上記の計算を使用して)_x-axis_を(1,0,0)の直交平面への射影になるように定義できます。これは、(1,0,0)が平面に垂直である縮退した場合を除いて機能します。

xおよびy軸方向の単位ベクトルを作成したら、Aおよびxyを直接投影できます。これらのベクトルの大きさは2D座標です。

たとえば、これは平面への(1,0,0)の投影です。これをx軸方向とします。

_In [42]: x = np.array([1,0,0])    
In [45]: x = x - np.dot(x, n) * n
In [52]: x /= sqrt((x**2).sum())   # make x a unit vector    
In [53]: x
Out[53]: array([ 0.89006056, -0.29182313, -0.35018776])
_

ここで、y軸方向を計算します。_y-axis_方向は、法線方向nxの両方に垂直でなければなりません。したがって、y外積nxに定義できます。

_In [68]: y = np.cross(n, x)

In [69]: y
Out[69]: array([ -2.77555756e-17,   7.68221280e-01,  -6.40184400e-01])
_

平面内のAの座標は次のとおりです。

_In [70]: np.dot(A, x), np.dot(A, y)
Out[70]: (-0.74414898890755965, -0.38411063979868798)
_
5
unutbu