CAMA : Exercices

Exercice 1.1

Écrire sous forme d'un produit matriciel la symétrie axiale par rapport à un axe qui ne passe pas par (0,0). On prendra l'axe qui passe par (2,0) et qui a un angle de π/3 par rapport à l'horizontale.

Est-ce un automorphisme orthogonal ? Le montrer.

Solution
def R3(α): return np.array([[np.cos(α), -np.sin(α), 0], [np.sin(α), np.cos(α), 0], [0, 0, 1]]) Sx3 = np.array([[1,0,0], [0,-1,0], [0,0,1]]) def T(v): # translation of v T = np.identity(3) T[0:2,2] = v return T θ = np.pi / 3 a = np.array([2,0]) S = T(a) @ R3(θ) @ Sx3 @ R3(-θ) @ T(-a) print("Matrix of symmetry:\n", S) shape2 = S @ shape1_3d plt.plot(shape1[0], shape1[1], ":") plt.plot(shape2[0], shape2[1]) plt.plot([a[0]-3*np.cos(θ),a[0]+np.cos(θ)],[a[1]-3*np.sin(θ),a[1]+np.sin(θ)], "-.") # axe de symétrie plt.axis('equal');
Matrix of symmetry:
 [[-0.5    0.866  3.   ]
 [ 0.866  0.5   -1.732]
 [ 0.     0.     1.   ]]

# Ce n'est pas un automorphisme orthogonal car S n'est pas orthogonale : S @ S.T
array([[10.   , -5.196,  3.   ],
       [-5.196,  4.   , -1.732],
       [ 3.   , -1.732,  1.   ]])

Exercice 3.1 (rotation de la caméra autour de son axe)

On a indiqué que 𝜃 est l'angle que la caméra fait par rapport à l'horizontal (à supposer que dans le monde réel un des axes est la verticale). Ajouter à toutes les transformations la possibilité de faire tourner la caméra sur son axe principal.

Solution
# on fait une simple matrice de rotation autour de z après être dans le repère de la caméra roll = lambda t: np.array([[np.cos(t), -np.sin(t), 0, 0], [np.sin(t), np.cos(t), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
view(F(2.3) @ roll(np.pi/4) @ R @ T(c))

Exercice 3.2

Définir la direction dans laquelle regarde la caméra avec un vecteur et non 2 angles de rotation. Rédigez pour expliquer vos calculs.

direction = [1,1,0] # à gauche à 45 degré
Solution

On a vu que dans la monde 3D réel la direction initiale de la caméra est x.

Il faut transformer la nouvelle direction qu'on nous donne pour la caméra en 2 angles de rotation ce qui donnera nos 2 matrices de rotation. On calcule les angles en fonction de la direction donnée grace aux formules de trigonométrie qu'on retrouve sur le cercle unité.

En 2D on a :

  • x=cos(α)
  • y=sin(α)

Donc si on a la direction (x,y) cela veut dire que l'angle qui nous intéresse est

α=arccos(x) mais ATTENTION cela n'est juste que si la direction est de norme = 1. Aussi on prend le ratio entre x et y qui est égale au ratio des valeurs normées. Ainsi
α=arctan(y/x)

En 3D on doit se rapportee au cas 2D qui différe suivant qu'on cherche l'angle vertical ou horizontal.

La rotation horizontale se fait dans le plan [x,y] :

  • x=cos(ψ)
  • y=sin(ψ)

et donc

ψ=arctan(y/x)
La rotation verticale se fait dans le plan [x+y, z] avec
ψ[π/2,π/2]

  • ||x+y||=cos(ϕ)
  • z=sin(ϕ)

et donc

ϕ=arctan(z/||x+y||)

def D(direction): if len(direction) == 2: # 2 angles ah = direction[0] av = direction[1] else: # on convertit la direction en angle norm = np.sqrt(direction[0]**2 + direction[1]**2) if norm == 0: # alors c'est vertical ah = 0 av = 1 else: av = np.arctan(direction[2]/norm) if direction[0] == 0: if direction[1] != 0: ah = np.sign(direction[1]) * np.pi/2 else: ah = np.arctan(direction[1]/direction[0]) print(ah, av) if type(ah) == int: ah = ah * 2 * np.pi / 360 av = av * 2 * np.pi / 360 rh = np.array([[np.cos(ah), -np.sin(ah), 0, 0], [np.sin(ah), np.cos(ah), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) rv = np.array([[np.cos(av), 0, np.sin(av), 0], [0, 1, 0, 0], [-np.sin(av), 0, np.cos(av), 0], [0, 0, 0, 1]]) return rv @ rh
view(F(2.3) @ R @ D([1,1,0]) @ T(c))
0.7853981633974483 0.0