Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpArit.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Le module "arit.c" contient les procedures arithmetiques.
32 */
33
34#include "vpArit.h"
35#include "vpMy.h"
36#include <math.h>
37#include <stdio.h>
38#include <string.h>
39#include <visp3/core/vpMath.h>
40
41#ifndef DOXYGEN_SHOULD_SKIP_THIS
43/*
44 * La procedure "fprintf_matrix" affiche une matrice sur un fichier.
45 * Entree :
46 * fp Fichier en sortie.
47 * m Matrice a ecrire.
48 */
49 void fprintf_matrix(FILE *fp, Matrix m)
50{
51 int i;
52
53 fprintf(fp, "(matrix\n");
54 for (i = 0; i < 4; i++)
55 fprintf(fp, "\t%.4f\t%.4f\t%.4f\t%.4f\n", m[i][0], m[i][1], m[i][2], m[i][3]);
56 fprintf(fp, ")\n");
57}
58
59/*
60 * La procedure "ident_matrix" initialise la matrice par la matrice identite.
61 * Entree :
62 * m Matrice a initialiser.
63 */
64void ident_matrix(Matrix m)
65{
66 static Matrix identity = IDENTITY_MATRIX;
67
68 // bcopy ((char *) identity, (char *) m, sizeof (Matrix));
69 memmove((char *)m, (char *)identity, sizeof(Matrix));
70 /*
71 * Version moins rapide.
72 *
73 * int i, j;
74 *
75 * for (i = 0; i < 4; i++)
76 * for (j = 0; j < 4; j++)
77 * m[i][j] = (i == j) ? 1.0 : 0.0;
78 */
79}
80
81/*
82 * La procedure "premult_matrix" pre multiplie la matrice par la seconde.
83 * Entree :
84 * a Premiere matrice du produit a = b * a.
85 * b Seconde matrice du produit.
86 */
87void premult_matrix(Matrix a, Matrix b)
88{
89 Matrix m;
90 int i, j;
91
92 for (i = 0; i < 4; i++)
93 for (j = 0; j < 4; j++)
94 m[i][j] = b[i][0] * a[0][j] + b[i][1] * a[1][j] + b[i][2] * a[2][j] + b[i][3] * a[3][j];
95 // bcopy ((char *) m, (char *) a, sizeof (Matrix));
96 memmove((char *)a, (char *)m, sizeof(Matrix));
97}
98
99/*
100 * La procedure "premult3_matrix" premultiplie la matrice par une matrice 3x3.
101 * Note : La procedure "premult3_matrix" optimise "premutl_matrix".
102 * Entree :
103 * a Premiere matrice du produit a = b * a.
104 * b Seconde matrice du produit 3x3.
105 */
106void premult3_matrix(Matrix a, Matrix b)
107{
108 Matrix m;
109 int i, j;
110
111 // bcopy ((char *) a, (char *) m, sizeof (Matrix));
112 memmove((char *)m, (char *)a, sizeof(Matrix));
113 for (i = 0; i < 3; i++)
114 for (j = 0; j < 4; j++)
115 a[i][j] = b[i][0] * m[0][j] + b[i][1] * m[1][j] + b[i][2] * m[2][j];
116}
117
118/*
119 * La procedure "prescale_matrix" premultiplie la matrice par l'homothetie.
120 * Entree :
121 * m Matrice a multiplier m = vp * m.
122 * vp Vecteur d'homothetie.
123 */
124void prescale_matrix(Matrix m, Vector *vp)
125{
126 int i;
127
128 for (i = 0; i < 4; i++) {
129 m[0][i] *= vp->x;
130 m[1][i] *= vp->y;
131 m[2][i] *= vp->z;
132 }
133}
134
135/*
136 * La procedure "pretrans_matrix" premultiplie la matrice par la translation.
137 * Entree :
138 * m Matrice a multiplier m = vp * m.
139 * vp Vecteur de translation.
140 */
141void pretrans_matrix(Matrix m, Vector *vp)
142{
143 int i;
144
145 for (i = 0; i < 4; i++)
146 m[3][i] += vp->x * m[0][i] + vp->y * m[1][i] + vp->z * m[2][i];
147}
148
149/*
150 * La procedure "postleft_matrix" postmultiplie la matrice
151 * par une matrice gauche sur un des axes.
152 * Entree :
153 * m Matrice a rendre gauche m = m * left.
154 * axis Axe de la matrice gauche 'x', 'y' ou 'z'.
155 */
156void postleft_matrix(Matrix m, char axis)
157{
158
159 int i;
160
161 switch (axis) {
162 case 'x':
163 for (i = 0; i < 4; i++)
164 m[i][0] = -m[i][0];
165 break;
166 case 'y':
167 for (i = 0; i < 4; i++)
168 m[i][1] = -m[i][1];
169 break;
170 case 'z':
171 for (i = 0; i < 4; i++)
172 m[i][2] = -m[i][2];
173 break;
174 default: {
175 static char proc_name[] = "postleft_matrix";
176 fprintf(stderr, "%s: axis unknown\n", proc_name);
177 break;
178 }
179 }
180}
181
182/*
183 * La procedure "postmult_matrix" post multiplie la matrice par la seconde.
184 * Entree :
185 * a Premiere matrice du produit a = a * b.
186 * b Seconde matrice du produit.
187 */
188void postmult_matrix(Matrix a, Matrix b)
189{
190 Matrix m;
191 int i, j;
192
193 for (i = 0; i < 4; i++)
194 for (j = 0; j < 4; j++)
195 m[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j] + a[i][3] * b[3][j];
196 // bcopy ((char *) m, (char *) a, sizeof (Matrix));
197 memmove((char *)a, (char *)m, sizeof(Matrix));
198}
199
200/*
201 * La procedure "postmult3_matrix" postmultiplie la matrice par une matrice
202 * 3x3. Note : La procedure "postmult3_matrix" optimise "postmutl_matrix".
203 * Entree :
204 * a Premiere matrice du produit a = a * b.
205 * b Seconde matrice du produit 3x3.
206 */
207void postmult3_matrix(Matrix a, Matrix b)
208{
209 Matrix m;
210 int i, j;
211
212 // bcopy ((char *) a, (char *) m, sizeof (Matrix));
213 memmove((char *)m, (char *)a, sizeof(Matrix));
214 for (i = 0; i < 4; i++)
215 for (j = 0; j < 3; j++)
216 a[i][j] = m[i][0] * b[0][j] + m[i][1] * b[1][j] + m[i][2] * b[2][j];
217}
218
219/*
220 * La procedure "postscale_matrix" post multiplie la matrice par l'homothetie.
221 * Entree :
222 * m Matrice a multiplier m = m * vp.
223 * vp Vecteur d'homothetie.
224 */
225void postscale_matrix(Matrix m, Vector *vp)
226{
227 int i;
228
229 for (i = 0; i < 4; i++) {
230 m[i][0] *= vp->x;
231 m[i][1] *= vp->y;
232 m[i][2] *= vp->z;
233 }
234}
235
236/*
237 * La procedure "posttrans_matrix" post mutiplie la matrice par la
238 * translation. Entree : m Matrice a multiplier m = m * vp. vp
239 * Vecteur de translation.
240 */
241void posttrans_matrix(Matrix m, Vector *vp)
242{
243 int i;
244
245 for (i = 0; i < 4; i++) {
246 m[i][0] += m[i][3] * vp->x;
247 m[i][1] += m[i][3] * vp->y;
248 m[i][2] += m[i][3] * vp->z;
249 }
250}
251
252/*
253 * La procedure "transpose_matrix" transpose la matrice.
254 * Entree :
255 * m Matrice a transposer.
256 */
257void transpose_matrix(Matrix m)
258{
259 unsigned int i, j;
260 float t;
261
262 for (i = 0; i < 4; i++)
263 for (j = 0; j < i; j++)
264 SWAP(m[i][j], m[j][i], t);
265}
266
267/*
268 * La procedure "cosin_to_angle" calcule un angle a partir d'un cosinus
269 * et d'un sinus.
270 * Entree :
271 * ca, sa Cosinus et Sinus de l'angle.
272 * Sortie :
273 * Angle en radians.
274 */
275float cosin_to_angle(float ca, float sa)
276{
277 float a; /* angle a calculer */
278
279 if (FABS(ca) < M_EPSILON) {
280 a = (sa > 0.0f) ? static_cast<float>(M_PI_2) : static_cast<float>(-M_PI_2);
281 }
282 else {
283 a = static_cast<float>(atan(static_cast<double>(sa / ca)));
284 if (ca < 0.0f)
285 a += (sa >0.0f) ? static_cast<float>(M_PI) : static_cast<float>(-M_PI);
286 }
287 return (a);
288}
289
290/*
291 * La procedure "cosin_to_lut" precalcule les tables des "cosinus" et "sinus".
292 * Les tables possedent "2 ** level" entrees pour M_PI_2 radians.
293 * Entree :
294 * level Niveau de decomposition.
295 * coslut Table pour la fonction "cosinus".
296 * sinlut Table pour la fonction "sinus".
297 */
298void cosin_to_lut(Index level, float *coslut, float *sinlut)
299{
300 int i;
301 int i_pi_2 = TWO_POWER(level);
302 int quad; /* quadrant courant */
303 double a; /* angle courant */
304 double step = M_PI_2 / static_cast<double>(i_pi_2);
305
306 quad = 0;
307 coslut[quad] = 1.0;
308 sinlut[quad] = 0.0; /* 0 */
309 quad += i_pi_2;
310 coslut[quad] = 0.0;
311 sinlut[quad] = 1.0; /* PI/2 */
312 quad += i_pi_2;
313 coslut[quad] = -1.0;
314 sinlut[quad] = 0.0; /* PI */
315 quad += i_pi_2;
316 coslut[quad] = 0.0;
317 sinlut[quad] = -1.0; /* 3PI/2*/
318
319 for (i = 1, a = step; i < i_pi_2; i++, a += step) {
320 float ca = static_cast<float>(cos(a));
321 quad = 0;
322 coslut[quad + i] = ca; /* cos(a) */
323 quad += i_pi_2;
324 sinlut[quad - i] = ca; /* sin(PI/2-a) */
325 sinlut[quad + i] = ca; /* sin(PI/2+a) */
326 quad += i_pi_2;
327 coslut[quad - i] = -ca; /* cos(PI-a) */
328 coslut[quad + i] = -ca; /* cos(PI+a) */
329 quad += i_pi_2;
330 sinlut[quad - i] = -ca; /* sin(3PI/2-a) */
331 sinlut[quad + i] = -ca; /* sin(3PI/2+a) */
332 quad += i_pi_2;
333 coslut[quad - i] = ca; /* cos(2PI-a) */
334 }
335}
336
337/*
338 * La procedure "norm_vector" normalise le vecteur.
339 * Si la norme est nulle la normalization n'est pas effectuee.
340 * Entree :
341 * vp Le vecteur a norme.
342 * Sortie :
343 * La norme du vecteur.
344 */
345float norm_vector(Vector *vp)
346{
347 float norm; /* norme du vecteur */
348
349 if ((norm = static_cast<float>(sqrt(static_cast<double>(DOT_PRODUCT(*vp, *vp))))) > M_EPSILON) {
350 vp->x /= norm;
351 vp->y /= norm;
352 vp->z /= norm;
353 }
354 else {
355 static char proc_name[] = "norm_vector";
356 fprintf(stderr, "%s: nul vector\n", proc_name);
357 }
358 return (norm);
359}
360
361/*
362 * La procedure "plane_norme" calcule le vecteur norme orthogonal au plan
363 * defini par les 3 points.
364 * Entree :
365 * np Le vecteur norme orthogonal au plan.
366 * ap, bp, cp Points formant un repere du plan.
367 */
368void plane_norme(Vector *np, Point3f *ap, Point3f *bp, Point3f *cp)
369{
370 Vector u, v;
371
372 DIF_COORD3(u, *bp, *ap) /* base orthonorme (ap, u, v) */
373 DIF_COORD3(v, *cp, *ap)
374 norm_vector(&u);
375 norm_vector(&v);
376 CROSS_PRODUCT(*np, u, v);
377}
378
379/*
380 * La procedure "point_matrix" deplace un point 3D dans un espace 4D.
381 * Une matrice homogene 4x4 effectue le changement de repere.
382 * Entree :
383 * p4 Point homogene resultat = p3 x m.
384 * p3 Point a deplacer.
385 * m Matrice de changement de repere.
386 */
387void point_matrix(Point4f *p4, Point3f *p3, Matrix m)
388{
389 float x = p3->x, y = p3->y, z = p3->z;
390
391 p4->x = COORD3_COL(x, y, z, m, 0);
392 p4->y = COORD3_COL(x, y, z, m, 1);
393 p4->z = COORD3_COL(x, y, z, m, 2);
394 p4->w = COORD3_COL(x, y, z, m, 3);
395}
396
397/*
398 * La procedure "point_3D_3D" deplace un tableau de points 3D dans un espace
399 * 3D. Une matrice 4x3 effectue le changement de repere. La quatrieme colonne
400 * de la matrice vaut [0, 0, 0, 1] et n'est pas utilisee. Entree : ip
401 * Tableau de points 3D a deplacer. size Taille du tableau
402 * "ip". m Matrice de changement de repere. Entree/Sortie : op
403 * Tableau de points 3D resultat.
404 */
405void point_3D_3D(Point3f *ip, int size, Matrix m, Point3f *op)
406{
407 Point3f *pend = ip + size; /* borne de ip */
408
409 for (; ip < pend; ip++, op++) {
410 float x = ip->x;
411 float y = ip->y;
412 float z = ip->z;
413
414 op->x = COORD3_COL(x, y, z, m, 0);
415 op->y = COORD3_COL(x, y, z, m, 1);
416 op->z = COORD3_COL(x, y, z, m, 2);
417 }
418}
419
420/*
421 * La procedure "point_3D_4D" deplace un tableau de points 3D dans un espace
422 * 4D. Une matrice homogene 4x4 effectue le changement de repere. Entree : p3
423 * Tableau de points 3D a deplacer. size Taille du tableau
424 * "p3". m Matrice de changement de repere. Entree/Sortie : p4
425 * Tableau de points 4D resultat.
426 */
427void point_3D_4D(Point3f *p3, int size, Matrix m, Point4f *p4)
428{
429 Point3f *pend = p3 + size; /* borne de p3 */
430
431 for (; p3 < pend; p3++, p4++) {
432 float x = p3->x;
433 float y = p3->y;
434 float z = p3->z;
435
436 p4->x = COORD3_COL(x, y, z, m, 0);
437 p4->y = COORD3_COL(x, y, z, m, 1);
438 p4->z = COORD3_COL(x, y, z, m, 2);
439 p4->w = COORD3_COL(x, y, z, m, 3);
440 }
441}
442
443/*
444 * La procedure "rotate_vector" transforme le vecteur
445 * par la rotation de sens trigonometrique d'angle et d'axe donnes.
446 * Entree :
447 * vp Vecteur a transformer.
448 * a Angle de rotation en degres.
449 * axis Vecteur directeur de l'axe de rotation.
450 */
451void rotate_vector(Vector *vp, float a, Vector *axis)
452{
453 Vector n, u, v, cross;
454 float f;
455
456 a *= static_cast<float>(M_PI) / 180.0f; /* passage en radians */
457
458 n = *axis; /* norme le vecteur directeur */
459 norm_vector(&n);
460
461 /*
462 * Avant rotation, vp vaut :
463 * u + v
464 * Apres rotation, vp vaut :
465 * u + cos(a) * v + sin(a) * (n^vp)
466 * = u + cos(a) * v + sin(a) * (n^v)
467 * avec u = (vp.n) * n, v = vp-u;
468 * ou "u" est la projection de "vp" sur l'axe "axis",
469 * et "v" est la composante de "vp" perpendiculaire a "axis".
470 */
471 f = DOT_PRODUCT(*vp, n);
472 u = n;
473 MUL_COORD3(u, f, f, f) /* (vp.n) * n */
474
475 DIF_COORD3(v, *vp, u) /* calcule "v" */
476
477 f = static_cast<float>(cos(static_cast<double>(a)));
478 MUL_COORD3(v, f, f, f) /* v * cos(a) */
479
480 CROSS_PRODUCT(cross, n, *vp);
481 f = static_cast<float>(sin(static_cast<double>(a)));
482 MUL_COORD3(cross, f, f, f) /* (n^v) * sin(a) */
483
484 SET_COORD3(*vp, u.x + v.x + cross.x, u.y + v.y + cross.y, u.z + v.z + cross.z)
485}
486
487/*
488 * La procedure "upright_vector" calcule un vecteur perpendiculaire.
489 * Les vecteurs ont un produit scalaire nul.
490 * Entree :
491 * vp Vecteur origine.
492 * Entree/Sortie :
493 * up Vecteur perpendiculaire a vp.
494 */
495void upright_vector(Vector *vp, Vector *up)
496{
497 if (FABS(vp->z) > M_EPSILON) { /* x et y sont fixes */
498 up->z = -(vp->x + vp->y) / vp->z;
499 up->x = up->y = 1.0;
500 }
501 else if (FABS(vp->y) > M_EPSILON) { /* x et z sont fixes */
502 up->y = -(vp->x + vp->z) / vp->y;
503 up->x = up->z = 1.0;
504 }
505 else if (FABS(vp->x) > M_EPSILON) { /* y et z sont fixes */
506 up->x = -(vp->y + vp->z) / vp->x;
507 up->y = up->z = 1.0;
508 }
509 else {
510 static char proc_name[] = "upright_vector";
511 up->x = up->y = up->z = 0.0;
512 fprintf(stderr, "%s: nul vector\n", proc_name);
513 return;
514 }
515}
516
517/*
518 * La procedure "Matrix_to_Position" initialise la position par la matrice.
519 * Si M est la matrice, et P la position : M = R.Sid.T, P = (R,Sid,T).
520 * On suppose que la matrice de rotation 3x3 de M est unitaire.
521 * Entree :
522 * m Matrice de rotation et de translation.
523 * pp Position a initialiser.
524 */
525void Matrix_to_Position(Matrix m, AritPosition *pp)
526{
527 Matrix_to_Rotate(m, &pp->rotate);
528 SET_COORD3(pp->scale, 1.0, 1.0, 1.0)
529 SET_COORD3(pp->translate, m[3][0], m[3][1], m[3][2])
530}
531
532/*
533 * La procedure "Matrix_to_Rotate" initialise la rotation par la matrice.
534 * Si M est la matrice, si R est la matrice de rotation :
535 *
536 * | m00 m01 m02 0 |
537 * M = Rx.Ry.Rz = | m10 m11 m12 0 |
538 * | m20 m21 m22 0 |
539 * | 0 0 0 1 |
540 *
541 * et m00 = cy.cz m01 = cy.sz m02 = -sy
542 * m10 = sx.sy.cz-cx.sz m11 = sx.sy.sz+cx.cz m12 = sx.cy
543 * m20 = cx.sy.cz+sx.sz m21 = cx.sy.sz-sx.cz m22 = cx.cy
544 * avec ci = cos Oi et si = sin Oi.
545 *
546 * R = Rx.Ry.Rz
547 * Rx rotation autour de Ox d'angle O1
548 * Ry rotation autour de Oy d'angle O2
549 * Rz rotation autour de Oz d'angle O3
550 *
551 * Singularite : si |ry| == 90 degres alors rz = 0,
552 * soit une rotation d'axe 0z et d'angle "rx + rz".
553 *
554 * Entree :
555 * m Matrice contenant la composition des rotations.
556 * vp Rotations par rapport aux axes d'un repere droit en degres.
557 */
558void Matrix_to_Rotate(Matrix m, Vector *vp)
559{
560 float sy = -m[0][2];
561 float cy = static_cast<float>(sqrt(1.0 - static_cast<double>(sy * sy)));
562 float cx, sx;
563
564 if (FABS(cy) > M_EPSILON) {
565 float sz = m[0][1] / cy;
566 float cz = m[0][0] / cy;
567
568 sx = m[1][2] / cy;
569 cx = m[2][2] / cy;
570
571 SET_COORD3(*vp, cosin_to_angle(cx, sx), cosin_to_angle(cy, sy), cosin_to_angle(cz, sz))
572 }
573 else { /* RZ = 0 => Ry = +/- 90 degres */
574 sx = m[1][1];
575 cx = -m[2][1];
576
577 SET_COORD3(*vp, cosin_to_angle(cx, sx), (sy > 0.0f) ? static_cast<float>(M_PI_2) : static_cast<float>(-M_PI_2), 0.0f)
578 }
579 vp->x *= 180.0f / static_cast<float>(M_PI); /* passage en degres */
580 vp->y *= 180.0f / static_cast<float>(M_PI);
581 vp->z *= 180.0f / static_cast<float>(M_PI);
582}
583
584/*
585 * La procedure "Position_to_Matrix" initialise la matrice par la position.
586 * Matrice resultat : M = Sx.Sy.Sz.Rx.Ry.Rz.Tx.Ty.Tz
587 * Entree :
588 * pp Position de reference.
589 * m Matrice a initialiser.
590 */
591void Position_to_Matrix(AritPosition *pp, Matrix m)
592{
593 Rotate_to_Matrix(&pp->rotate, m); /* rotation */
594 prescale_matrix(m, &pp->scale); /* homothetie */
595 m[3][0] = pp->translate.x; /* translation */
596 m[3][1] = pp->translate.y;
597 m[3][2] = pp->translate.z;
598}
599
600/*
601 * La procedure "Rotate_to_Matrix" initialise la matrice par la rotation.
602 *
603 * | m00 m01 m02 0 |
604 * M = Rx.Ry.Rz = | m10 m11 m12 0 |
605 * | m20 m21 m22 0 |
606 * | 0 0 0 1 |
607 *
608 * Rx rotation autour de Ox d'angle O1
609 * Ry rotation autour de Oy d'angle O2
610 * Rz rotation autour de Oz d'angle O3
611 * et m00 = cy.cz m01 = cy.sz m02 = -sy
612 * m10 = sx.sy.cz-cx.sz m11 = sx.sy.sz+cx.cz m12 = sx.cy
613 * m20 = cx.sy.cz+sx.sz m21 = cx.sy.sz-sx.cz m22 = cx.cy
614 * avec ci = cos Oi et si = sin Oi.
615 *
616 * Entree :
617 * vp Rotations par rapport aux axes d'un repere droit en degres.
618 * m Matrice a initialiser.
619 */
620void Rotate_to_Matrix(Vector *vp, Matrix m)
621{
622 float rx = vp->x * static_cast<float>(M_PI) / 180.0f;
623 float ry = vp->y * static_cast<float>(M_PI) / 180.0f;
624 float rz = vp->z * static_cast<float>(M_PI) / 180.0f;
625 float cx = static_cast<float>(cos(static_cast<double>(rx)));
626 float sx = static_cast<float>(sin(static_cast<double>(rx)));
627 float cy = static_cast<float>(cos(static_cast<double>(ry)));
628 float sy = static_cast<float>(sin(static_cast<double>(ry)));
629 float cz = static_cast<float>(cos(static_cast<double>(rz)));
630 float sz = static_cast<float>(sin(static_cast<double>(rz)));
631
632 m[0][0] = cy * cz;
633 m[1][0] = (sx * sy * cz) - (cx * sz);
634 m[2][0] = (cx * sy * cz) + (sx * sz);
635
636 m[0][1] = cy * sz;
637 m[1][1] = (sx * sy * sz) + (cx * cz);
638 m[2][1] = (cx * sy * sz) - (sx * cz);
639
640 m[0][2] = -sy;
641 m[1][2] = sx * cy;
642 m[2][2] = cx * cy;
643
644 m[0][3] = m[1][3] = m[2][3] = 0.0;
645 m[3][0] = m[3][1] = m[3][2] = 0.0;
646 m[3][3] = 1.0;
647}
648
649/*
650 * La procedure "Rotaxis_to_Matrix" initialise la matrice par la rotation
651 * d'angle et d'axe donnes.
652 * Si M est la matrice, O l'angle et N le vecteur directeur de l'axe :
653 *
654 * M = cos(O) Id3 + (1 - cosO) Nt N + sinO N~
655 *
656 * | NxNxverO+ cosO NxNyverO+NzsinO NxNzverO-NxsinO 0 |
657 * M = | NxNyverO-NzsinO NyNyverO+ cosO NyNzverO+NxsinO 0 |
658 * | NxNzverO+NysinO NyNzverO-NxsinO NzNzverO+ cosO 0 |
659 * | 0 0 0 1 |
660 *
661 * O angle de rotation.
662 * N Vecteur directeur norme de l'axe de rotation.
663 * Nt Vecteur transpose.
664 * N~ | 0 Nz -Ny|
665 * |-Nz 0 Nx|
666 * | Ny -Nx 0 |
667 * Entree :
668 * a Angle de rotation en degres.
669 * axis Vecteur directeur de l'axe de la rotation.
670 * m Matrice a initialiser.
671 */
672void Rotaxis_to_Matrix(float a, Vector *axis, Matrix m)
673{
674 float cosa;
675 float sina;
676 float vera; /* 1 - cosa */
677 Vector n; /* vecteur norme*/
678 Vector conv; /* verO n */
679 Vector tilde; /* sinO n */
680
681 a *= static_cast<float>(M_PI) / 180.0f; /* passage en radians */
682
683 cosa = static_cast<float>(cos(static_cast<double>(a)));
684 sina = static_cast<float>(sin(static_cast<double>(a)));
685 vera = 1.0f - cosa;
686
687 n = *axis; /* norme le vecteur directeur */
688 norm_vector(&n);
689 tilde = conv = n;
690 MUL_COORD3(conv, vera, vera, vera)
691 MUL_COORD3(tilde, sina, sina, sina)
692
693 m[0][0] = conv.x * n.x + cosa;
694 m[0][1] = conv.x * n.y + tilde.z;
695 m[0][2] = conv.x * n.z - tilde.y;
696
697 m[1][0] = conv.y * n.x - tilde.z;
698 m[1][1] = conv.y * n.y + cosa;
699 m[1][2] = conv.y * n.z + tilde.x;
700
701 m[2][0] = conv.z * n.x + tilde.y;
702 m[2][1] = conv.z * n.y - tilde.x;
703 m[2][2] = conv.z * n.z + cosa;
704
705 m[0][3] = m[2][3] = m[1][3] = 0.0;
706 m[3][0] = m[3][1] = m[3][2] = 0.0;
707 m[3][3] = 1.0;
708}
709
710/*
711 * La procedure "Rotrans_to_Matrix" initialise la matrice par la rotation
712 * et de la translation.
713 * Entree :
714 * rp Vecteur des angles de rotation en degres.
715 * tp Vecteur des coordonnees de translation.
716 * m Matrice a initialiser.
717 */
718void Rotrans_to_Matrix(Vector *rp, Vector *tp, Matrix m)
719{
720 Rotate_to_Matrix(rp, m); /* matrice de rotation */
721 m[3][0] = tp->x; /* matrice de translation */
722 m[3][1] = tp->y;
723 m[3][2] = tp->z;
724}
725
726/*
727 * La procedure "Scale_to_Matrix" initialise la matrice par l'homothetie.
728 * Entree :
729 * vp Vecteur des coordonnees d'homothetie.
730 * m Matrice a initialiser.
731 */
732void Scale_to_Matrix(Vector *vp, Matrix m)
733{
734 ident_matrix(m);
735 m[0][0] = vp->x;
736 m[1][1] = vp->y;
737 m[2][2] = vp->z;
738}
739
740/*
741 * La procedure "Translate_to_Matrix" initialise la matrice par la
742 * translation. Entree : vp Vecteur des coordonnees de
743 * translation. m Matrice a initialiser.
744 */
745void Translate_to_Matrix(Vector *vp, Matrix m)
746{
747 ident_matrix(m);
748 m[3][0] = vp->x;
749 m[3][1] = vp->y;
750 m[3][2] = vp->z;
751}
752END_VISP_NAMESPACE
753#endif