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