web-dev-qa-db-fra.com

Projection de points 3D sur un plan 2D

Soit A un point pour lequel j'ai les coordonnées 3D x, y, z et je veux les transformer en coordonnées 2D: x, y. La projection doit être orthogonale sur un plan défini par une normale donnée. Le cas trivial, où la normale est en fait l'un des axes, est facile à résoudre, en éliminant simplement une coordonnée, mais qu'en est-il des autres cas, qui sont plus susceptibles de se produire?

31
Lighthink

Si vous avez votre point cible P avec les coordonnées r_P = (x,y,z) et un plan avec normal n=(nx,ny,nz) vous devez définir un Origine sur le plan, ainsi que deux directions orthogonales pour x et y. Par exemple, si votre origine est à r_O = (ox, oy, oz) et vos deux axes de coordonnées dans le plan sont définis par e_1 = (ex_1,ey_1,ez_1), e_2 = (ex_2,ey_2,ez_2) alors l'orthogonalité a cette Dot(n,e_1)=0, Dot(n,e_2)=0, Dot(e_1,e_2)=0 (produit vectoriel vectoriel). Notez que tous les vecteurs de direction devraient être normalisés (la magnitude doit être de un).

Votre point cible P doit obéir à l'équation:

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

t_1 et t_2 sont vos coordonnées 2D le long de e_1 et e_2 et s la séparation normale (distance) entre l'avion et le point.

Là, les scalaires sont trouvés par des projections:

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)

Exemple avec un plan Origin r_O = (-1,3,1) et normal:

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

Vous devez choisir des directions orthogonales pour les coordonnées 2D, par exemple:

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

tels que Dot(n,e_1) = 0 et Dot(n,e_2) = 0 et Dot(e_1, e_2) = 0.

Les coordonnées 2D d'un point P r_P=(1,7,-3) sont:

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

et la séparation hors plan:

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

Trouvez la projection de A sur la direction normale . Soustrayez ensuite cette projection de A. Ce qui reste est la projection de A sur le plan orthogonal.

La projection de A sur la direction normale de l'unité n est donnée par:

(A · n) n

Si A = (x, y, z) et l'unité normale est donnée par n = (nx, ny, nz), alors la projection de A sur n est

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

Ainsi, la projection de A sur le plan orthogonal est

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

Par exemple, si A = (1,2,3) et n est l'unité normale dans la direction (4,5,6), alors

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

Ainsi, la projection de A sur le plan orthogonal est

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

Comment trouver des coordonnées 2D:

Vous devrez définir un système de coordonnées 2D sur le plan orthogonal. En d'autres termes, vous devez définir où se trouvent x-axis Et y-axis. Par exemple, vous pouvez définir le x-axis Comme la projection de (1,0,0) sur le plan orthogonal (en utilisant le calcul illustré ci-dessus). Cela fonctionnera sauf dans le cas dégénéré où (1,0,0) est normal au plan.

Une fois que vous avez des vecteurs unitaires pour les directions des axes x et y, vous pouvez projeter A directement sur x et y. La magnitude de ces vecteurs sont les coordonnées 2D.

Par exemple, il s'agit de la projection de (1,0,0) sur le plan. Nous considérons que c'est la direction de l'axe des 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])

Ici, nous calculons la direction de l'axe y: La direction y-axis Doit être perpendiculaire à la fois à la direction normale n et à x. Nous pourrions donc définir y comme produit croisé de n et x:

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

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

Voici donc les coordonnées de A dans le plan:

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