Code_TYMPAN  4.4.0
Industrial site acoustic simulation
3d.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012-2014> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
16 #include <math.h>
17 #include <stdio.h>
18 
19 #include "3d.h"
20 
21 #define MAX(A, B) (((A) > (B)) ? (A) : (B))
22 #define MIN(A, B) (((A) > (B)) ? (B) : (A))
23 #define minP(A, B, C) ((((A).C) > ((B).C)) ? (B) : (A))
24 #define coeff_ang(PA, PB) (((PB)._y - (PA)._y) / ((PB)._x - (PA)._x))
25 #define DOT(u, v) ((u)._x * (v)._x + (u)._y * (v)._y + (u)._z * (v)._z)
26 
27 /* OCoord3D *******************************************************************/
28 
29 OCoord3D::OCoord3D() : _x(0), _y(0), _z(0) {}
30 
31 OCoord3D::OCoord3D(double x, double y, double z) : _x(x), _y(y), _z(z) {}
32 
34 {
35  *this = coord;
36 }
37 
39 
41 {
42  if (this != &coord)
43  {
44  _x = coord._x;
45  _y = coord._y;
46  _z = coord._z;
47  }
48  return *this;
49 }
50 
51 bool OCoord3D::operator==(const OCoord3D& coord) const
52 {
53  if (this != &coord)
54  {
55  if (fabs(_x - coord._x) > EPSILON_6)
56  {
57  return false;
58  }
59  if (fabs(_y - coord._y) > EPSILON_6)
60  {
61  return false;
62  }
63  if (fabs(_z - coord._z) > EPSILON_6)
64  {
65  return false;
66  }
67  }
68  return true;
69 }
70 
71 bool OCoord3D::operator!=(const OCoord3D& coord) const
72 {
73  return !operator==(coord);
74 }
75 
76 void OCoord3D::setCoords(double x, double y, double z)
77 {
78  _x = x;
79  _y = y;
80  _z = z;
81 }
82 
83 void OCoord3D::setCoords(double coords[3])
84 {
85  _x = coords[0];
86  _y = coords[1];
87  _z = coords[2];
88 }
89 
90 void OCoord3D::getCoords(double coords[3])
91 {
92  coords[0] = _x;
93  coords[1] = _y;
94  coords[2] = _z;
95 }
96 
98 {
99  double* res = new double[3];
100  res[0] = _x;
101  res[1] = _y;
102  res[2] = _z;
103  return res;
104 }
105 
106 ::std::ostream& operator<<(::std::ostream& os, const OCoord3D& c)
107 {
108  return os << "(" << c._x << ", " << c._y << ", " << c._z << ")";
109 }
110 
111 /* OVector3D ******************************************************************/
112 
114 
115 OVector3D::OVector3D(const OVector3D& vector) : OCoord3D(vector) {}
116 
117 OVector3D::OVector3D(const OCoord3D& coord) : OCoord3D(coord) {}
118 
119 OVector3D::OVector3D(const OCoord3D& coordFrom, const OCoord3D& coordTo)
120 {
121  OVector3D vecFrom(coordFrom);
122  OVector3D vecTo(coordTo);
123  *this = vecTo - vecFrom;
124 }
125 
126 OVector3D::OVector3D(double x, double y, double z) : OCoord3D(x, y, z) {}
127 
129 
131 {
132  _x = 0.0;
133  _y = 0.0;
134  _z = 0.0;
135 }
136 
138 {
139  OCoord3D::operator=(vector);
140  return *this;
141 }
142 
143 bool OVector3D::operator==(const OVector3D& vector) const
144 {
145  return OCoord3D::operator==(vector);
146 }
147 
148 bool OVector3D::operator!=(const OVector3D& vector) const
149 {
150  return !operator==(vector);
151 }
152 
154 {
155  OVector3D vectorRet = *this;
156  vectorRet._x = this->_x + vector._x;
157  vectorRet._y = this->_y + vector._y;
158  vectorRet._z = this->_z + vector._z;
159  return vectorRet;
160 }
161 
163 {
164  OVector3D vectorRet;
165  vectorRet._x = this->_x - vector._x;
166  vectorRet._y = this->_y - vector._y;
167  vectorRet._z = this->_z - vector._z;
168  return vectorRet;
169 }
170 
172 {
173  OVector3D vectorRet;
174  // XXX This is meaningless
175  vectorRet._x = this->_x * vector._x;
176  vectorRet._y = this->_y * vector._y;
177  vectorRet._z = this->_z * vector._z;
178  return vectorRet;
179 }
180 
181 OVector3D OVector3D::operator*(const double a) const
182 {
183  // Appel l'operateur (double) * (OVector3D)
184  return (a * (*this));
185 }
186 
187 OVector3D operator*(const double a, const OVector3D& vector)
188 {
189  OVector3D vectorRet;
190  vectorRet._x = vector._x * a;
191  vectorRet._y = vector._y * a;
192  vectorRet._z = vector._z * a;
193  return vectorRet;
194 }
195 
197 {
198  OVector3D vectorRet;
199  vectorRet._x = (this->_y * vector._z) - (this->_z * vector._y);
200  vectorRet._y = (this->_z * vector._x) - (this->_x * vector._z);
201  vectorRet._z = (this->_x * vector._y) - (this->_y * vector._x);
202  return vectorRet;
203 }
204 
205 void OVector3D::balance(double c1, const OVector3D& vector2, double c2)
206 {
207  *this = *this * c1 + vector2 * c2;
208 }
209 
210 double OVector3D::scalar(const OVector3D& vector) const
211 {
212  return (this->_x * vector._x + this->_y * vector._y + this->_z * vector._z);
213 }
214 
215 double OVector3D::norme() const
216 {
217  return sqrt(_x * _x + _y * _y + _z * _z);
218 }
219 
220 OVector3D OVector3D::normal(const OVector3D& vector2, const OVector3D& vector3) const
221 {
222  return (vector2 - *this).cross(vector3 - *this);
223 }
224 
226 {
227  double n = norme();
228  if (n > 0.0)
229  {
230  _x /= n;
231  _y /= n;
232  _z /= n;
233  }
234 }
235 
237 {
238  _x = -_x;
239  _y = -_y;
240  _z = -_z;
241 }
242 
243 double OVector3D::angle(const OVector3D& vector) const
244 {
245  double norme = (this->norme() * vector.norme());
246  if (norme == 0.0)
247  {
248  return norme;
249  }
250  double cosVal = this->scalar(vector) / norme;
251  return (acos(BORNE(cosVal, -1.0, 1.0)));
252 }
253 
255 {
256  OVector3D& V = *this;
257  double cosA = cos(alpha);
258  double sinA = sin(alpha);
259  OVector3D Vfinal;
260  // Computes the calculations
261  Vfinal._x = cosA * V._x - sinA * V._y;
262  Vfinal._y = sinA * V._x + cosA * V._y;
263  Vfinal._z = V._z;
264  return Vfinal;
265 }
266 
268 {
269  OVector3D& V = *this;
270  double cosA = cos(alpha);
271  double sinA = sin(alpha);
272  OVector3D Vfinal;
273  // Computes the calculations
274  Vfinal._x = cosA * V._x - sinA * V._z;
275  Vfinal._y = V._y;
276  Vfinal._z = sinA * V._x + cosA * V._z;
277  return Vfinal;
278 }
279 
281 {
282  OVector3D& V = *this;
283  double cosA = cos(alpha);
284  double sinA = sin(alpha);
285  OVector3D Vfinal;
286  // Computes the calculations
287  Vfinal._x = cosA * V._x + sinA * V._y;
288  Vfinal._y = -sinA * V._x + cosA * V._y;
289  Vfinal._z = V._z;
290  return Vfinal;
291 }
292 
294 {
295  OVector3D& V = *this;
296  double cosA = cos(alpha);
297  double sinA = sin(alpha);
298  OVector3D Vfinal;
299  // Computes the calculations
300  Vfinal._x = cosA * V._x + sinA * V._z;
301  Vfinal._y = V._y;
302  Vfinal._z = -sinA * V._x + cosA * V._z;
303  return Vfinal;
304 }
305 
306 OVector3D OVector3D::getRotationOzOy(double alpha, double theta)
307 {
308  OVector3D& V = *this;
309  double cosA = cos(alpha);
310  double sinA = sin(alpha);
311  double cosB = cos(theta);
312  double sinB = sin(theta);
313  OVector3D Vfinal;
314  // Computes the calculations
315  Vfinal._x = cosA * cosB * V._x - sinA * V._y - cosA * sinB * V._z;
316  Vfinal._y = sinA * cosB * V._x + cosA * V._y - sinA * sinB * V._z;
317  Vfinal._z = sinB * V._x + cosB * V._z;
318  return Vfinal;
319 }
320 
321 ::std::ostream& operator<<(::std::ostream& os, const OVector3D& v)
322 {
323  return os << "OVector3D" << static_cast<const OCoord3D&>(v);
324 }
325 
326 /* OPoint3D *******************************************************************/
327 
329 
331 
332 OPoint3D::OPoint3D(const OCoord3D& coord) : OCoord3D(coord) {}
333 
334 OPoint3D::OPoint3D(double x, double y, double z) : OCoord3D(x, y, z) {}
335 
336 OPoint3D::OPoint3D(double v[]) : OCoord3D(v[0], v[1], v[2]) {}
337 
339 
340 void OPoint3D::setFromOGL(double x, double y, double z)
341 {
342  _x = x;
343  _y = -z;
344  _z = y;
345 }
346 
347 void OPoint3D::setFromOGL(float x, float y, float z)
348 {
349  _x = x;
350  _y = -z;
351  _z = y;
352 }
353 
354 void OPoint3D::setFromOGL(float coords[3])
355 {
356  setFromOGL(coords[0], coords[1], coords[2]);
357 }
358 
359 void OPoint3D::getToOGL(double& x, double& y, double& z)
360 {
361  x = _x;
362  y = _z;
363  z = -_y;
364 }
365 
366 void OPoint3D::getToOGL(double coords[3])
367 {
368  getToOGL(coords[0], coords[1], coords[2]);
369 }
370 
371 double OPoint3D::distFrom(const OPoint3D& pt) const
372 {
373  return OVector3D(*this, pt).norme();
374 }
375 
376 double OPoint3D::dist2DFrom(const OPoint3D& pt) const
377 {
378  return sqrt((_x - pt._x) * (_x - pt._x) + (_y - pt._y) * (_y - pt._y));
379 }
380 
381 void OPoint3D::set(double x, double y, double z)
382 {
383  OCoord3D::setCoords(x, y, z);
384 }
385 
386 TabPoint3D OPoint3D::checkPointsMaxDistance(const TabPoint3D& points, const double& distanceMax)
387 {
388  TabPoint3D retTab;
389  if (points.empty() || (distanceMax <= 0.1))
390  {
391  return points;
392  }
393  bool pointAdded = false;
394  // On verifie que les points ne sont pas trop eloignes les uns des autres
395  OSegment3D seg;
396  seg._ptA = points[0];
397  retTab.push_back(seg._ptA);
398  double dist(0.0);
399  for (unsigned int i = 1; i < points.size(); i++)
400  {
401  seg._ptB = points[i];
402  dist = seg.longueur();
403  // Si les points sont trop eloignes...
404  if (dist > distanceMax)
405  {
406  // On ajoute un point entre les deux
407  OVector3D vec(seg._ptA, seg._ptB);
408  vec.normalize();
409  OPoint3D newPt = OVector3D(seg._ptA) + (vec * (dist / 2));
410  retTab.push_back(newPt);
411  pointAdded = true;
412  }
413  retTab.push_back(seg._ptB);
414  seg._ptA = seg._ptB;
415  }
416  if (pointAdded)
417  {
418  retTab = checkPointsMaxDistance(retTab, distanceMax);
419  }
420  return retTab;
421 }
422 
424  const double& distanceMax)
425 {
426  TabPoint3D tabPoints;
427  tabPoints.push_back(point1);
428  tabPoints.push_back(point2);
429  return checkPointsMaxDistance(tabPoints, distanceMax);
430 }
431 
432 ::std::ostream& operator<<(::std::ostream& os, const OPoint3D& v)
433 {
434  return os << "OPoint3D" << static_cast<const OCoord3D&>(v);
435 }
436 
437 /* Matrix *********************************************************************/
438 
440 {
441  unite();
442 }
443 
444 OMatrix::OMatrix(const OMatrix& matrix)
445 {
446  *this = matrix;
447 }
448 
449 OMatrix::OMatrix(double matrix[4][4])
450 {
451  int i = 0, j = 0;
452  for (i = 0; i < 4; i++)
453  {
454  for (j = 0; j < 4; j++)
455  {
456  _m[i][j] = matrix[i][j];
457  }
458  }
459 }
460 
462 
464 {
465  if (this != &matrix)
466  {
467  for (int i = 0; i < 4; i++)
468  {
469  for (int j = 0; j < 4; j++)
470  {
471  _m[i][j] = matrix._m[i][j];
472  }
473  }
474  }
475  return *this;
476 }
477 
478 bool OMatrix::operator==(const OMatrix& matrix) const
479 {
480  if (this != &matrix)
481  {
482  for (int i = 0; i < 4; i++)
483  {
484  for (int j = 0; j < 4; j++)
485  {
486  if (_m[i][j] != matrix._m[i][j])
487  {
488  return false;
489  }
490  }
491  }
492  }
493  return true;
494 }
495 
496 bool OMatrix::operator!=(const OMatrix& matrix) const
497 {
498  return !operator==(matrix);
499 }
500 
501 OMatrix OMatrix::operator+(const OMatrix& matrix) const
502 {
503  OMatrix matrixRes;
504  for (int i = 0; i < 3; i++)
505  {
506  for (int j = 0; j < 3; j++)
507  {
508  matrixRes._m[i][j] = _m[i][j] + matrix._m[i][j];
509  }
510  }
511  return matrixRes;
512 }
513 
514 OMatrix OMatrix::operator-(const OMatrix& matrix) const
515 {
516  OMatrix matrixRes;
517  for (int i = 0; i < 3; i++)
518  {
519  for (int j = 0; j < 3; j++)
520  {
521  matrixRes._m[i][j] = _m[i][j] - matrix._m[i][j];
522  }
523  }
524  return matrixRes;
525 }
526 
527 OMatrix OMatrix::operator*(const OMatrix& matrix) const
528 {
529  OMatrix matrixRes;
530  for (int i = 0; i < 4; i++)
531  {
532  for (int j = 0; j < 4; j++)
533  {
534  double t = 0;
535  for (int k = 0; k < 4; k++)
536  {
537  t += _m[i][k] * matrix._m[k][j];
538  }
539  matrixRes._m[i][j] = t;
540  }
541  }
542  return matrixRes;
543 }
544 
545 OCoord3D OMatrix::dot(const OCoord3D& coord) const
546 {
547  OCoord3D coordRes;
548  coordRes._x = _m[0][0] * coord._x + _m[0][1] * coord._y + _m[0][2] * coord._z;
549  coordRes._y = _m[1][0] * coord._x + _m[1][1] * coord._y + _m[1][2] * coord._z;
550  coordRes._z = _m[2][0] * coord._x + _m[2][1] * coord._y + _m[2][2] * coord._z;
551  return coordRes;
552 }
553 
554 OCoord3D OMatrix::scale(const OCoord3D& coord) const
555 {
556  OCoord3D coordRes(coord);
557  double scale = NAN;
558  scale = _m[3][0] * coord._x + _m[3][1] * coord._y + _m[3][2] * coord._z + _m[3][3];
559  if ((scale != 1) && (ABS(scale) >= EPSILON_13))
560  {
561  coordRes._x /= scale;
562  coordRes._y /= scale;
563  coordRes._z /= scale;
564  }
565  return coordRes;
566 }
567 
568 OVector3D operator*(const OMatrix& mat, const OVector3D& vec)
569 {
570  OVector3D resVec = mat.dot(vec);
571  resVec = mat.scale(resVec);
572  return resVec;
573 }
574 
575 OPoint3D operator*(const OMatrix& mat, const OPoint3D& pt)
576 {
577  OPoint3D resPt = mat.dot(pt);
578  // Translation
579  resPt._x = resPt._x + mat._m[0][3];
580  resPt._y = resPt._y + mat._m[1][3];
581  resPt._z = resPt._z + mat._m[2][3];
582  return resPt;
583 }
584 
586 {
587  double echelle = NAN;
588  OVector3D vecRes;
589  // Same as operator* but without the translation (column _m[0->2][3])
590  vecRes._x = _m[0][0] * normal._x + _m[0][1] * normal._y + _m[0][2] * normal._z;
591  vecRes._y = _m[1][0] * normal._x + _m[1][1] * normal._y + _m[1][2] * normal._z;
592  vecRes._z = _m[2][0] * normal._x + _m[2][1] * normal._y + _m[2][2] * normal._z;
593  echelle = _m[3][0] * normal._x + _m[3][1] * normal._y + _m[3][2] * normal._z + _m[3][3];
594  if (ABS(echelle) < EPSILON_13)
595  {
596  }
597  else
598  {
599  if (echelle != 1)
600  {
601  vecRes._x /= echelle;
602  vecRes._y /= echelle;
603  vecRes._z /= echelle;
604  }
605  }
606  return vecRes;
607 }
608 
610 {
611  int i = 0, j = 0;
612  for (i = 0; i < 4; i++)
613  {
614  for (j = 0; j < 4; j++)
615  {
616  printf("%12.7f ", _m[i][j]);
617  }
618  printf("\n");
619  }
620 }
621 
623 {
624  int i = 0, j = 0;
625  for (i = 0; i < 4; i++)
626  {
627  for (j = 0; j < 4; j++)
628  {
629  _m[i][j] = 0;
630  }
631  }
632 }
633 
635 {
636  int i = 0, j = 0;
637  for (i = 0; i < 4; i++)
638  {
639  for (j = 0; j < 4; j++)
640  {
641  _m[i][j] = (i == j ? 1 : 0);
642  }
643  }
644 }
645 
646 int OMatrix::setTranslation(double x, double y, double z)
647 {
648  unite();
649  _m[0][3] = x;
650  _m[1][3] = y;
651  _m[2][3] = z;
652  return 1;
653 }
654 
655 int OMatrix::setScale(double x, double y, double z)
656 {
657  unite();
658  _m[0][0] = x;
659  _m[1][1] = y;
660  _m[2][2] = z;
661  return 1;
662 }
663 
665 {
666  double cosa = cos(a);
667  double sina = sin(a);
668  unite();
669  _m[1][1] = cosa;
670  _m[1][2] = -sina;
671  _m[2][1] = sina;
672  _m[2][2] = cosa;
673  return 1;
674 }
675 
677 {
678  double cosa = cos(a);
679  double sina = sin(a);
680  unite();
681  _m[0][0] = cosa;
682  _m[0][2] = sina;
683  _m[2][0] = -sina;
684  _m[2][2] = cosa;
685  return 1;
686 }
687 
689 {
690  double cosa = cos(a);
691  double sina = sin(a);
692  unite();
693  _m[0][0] = cosa;
694  _m[0][1] = -sina;
695  _m[1][0] = sina;
696  _m[1][1] = cosa;
697  return 1;
698 }
699 
701 {
702  int res = 0;
703  double n2 = vector.norme();
704  if (n2 > EPSILON_13)
705  {
706  double n1 = NAN, cos1 = NAN, sin1 = NAN, cos2 = NAN, sin2 = NAN;
707  res = 1;
708  n1 = sqrt(vector._x * vector._x + vector._y * vector._y);
709  if (n1 < EPSILON_13)
710  {
711  cos1 = 1;
712  sin1 = 0;
713  cos2 = 0;
714  sin2 = (vector._z >= 0 ? 1 : -1);
715  }
716  else
717  {
718  cos1 = vector._x / n1;
719  sin1 = vector._y / n1;
720  cos2 = n1 / n2;
721  sin2 = vector._z / n2;
722  }
723  _m[0][0] = cos2 * cos1;
724  _m[0][1] = cos2 * sin1;
725  _m[0][2] = sin2;
726  _m[0][3] = 0;
727  _m[1][0] = -sin1;
728  _m[1][1] = cos1;
729  _m[1][2] = 0;
730  _m[1][3] = 0;
731  _m[2][0] = -sin2 * cos1;
732  _m[2][1] = -sin2 * sin1;
733  _m[2][2] = cos2;
734  _m[2][3] = 0;
735  _m[3][0] = 0;
736  _m[3][1] = 0;
737  _m[3][2] = 0;
738  _m[3][3] = 1;
739  }
740  return res;
741 }
742 
744 {
745  int res = 0;
746  double n2 = vector.norme();
747  if (n2 > EPSILON_13)
748  {
749  double n1 = NAN, cos1 = NAN, sin1 = NAN, cos2 = NAN, sin2 = NAN;
750  res = 1;
751  n1 = sqrt(vector._x * vector._x + vector._y * vector._y);
752  if (n1 < EPSILON_13)
753  {
754  cos1 = 1;
755  sin1 = 0;
756  cos2 = 0;
757  sin2 = (vector._z >= 0 ? 1 : -1);
758  }
759  else
760  {
761  /* Si le vecteur est dans le plan yOz, */
762  /* on evite la rotation autour de Oz */
763  if (ABS(vector._x) < EPSILON_13)
764  {
765  n1 = (vector._y < 0.0 ? -n1 : n1);
766  }
767  cos1 = vector._y / n1;
768  sin1 = vector._x / n1;
769  cos2 = n1 / n2;
770  sin2 = vector._z / n2;
771  }
772  _m[0][0] = cos1;
773  _m[0][1] = -sin1;
774  _m[0][2] = 0;
775  _m[0][3] = 0;
776  _m[1][0] = sin1 * cos2;
777  _m[1][1] = cos1 * cos2;
778  _m[1][2] = sin2;
779  _m[1][3] = 0;
780  _m[2][0] = -sin1 * sin2;
781  _m[2][1] = -cos1 * sin2;
782  _m[2][2] = cos2;
783  _m[2][3] = 0;
784  _m[3][0] = 0;
785  _m[3][1] = 0;
786  _m[3][2] = 0;
787  _m[3][3] = 1;
788  }
789  return res;
790 }
791 
793 {
794  double det = determinant();
795  adjoint();
796  // if the determinant is zero,
797  // then the inverse matrix is not unique.
798  if (fabs(det) < EPSILON_50)
799  {
800  return 0;
801  }
802  // Scale the adjoint matrix to get the inverse.
803  for (int i = 0; i < 4; i++)
804  {
805  for (int j = 0; j < 4; j++)
806  {
807  _m[i][j] = _m[i][j] / det;
808  }
809  }
810  return 1;
811 }
812 
813 OMatrix OMatrix::getInvert(int* ok /*=0*/) const
814 {
815  OMatrix mat(*this);
816  int ret = mat.invert();
817  if (ok)
818  {
819  *ok = ret;
820  }
821  return mat;
822 }
823 
825 {
826  double a1 = NAN, a2 = NAN, a3 = NAN, a4 = NAN, b1 = NAN, b2 = NAN, b3 = NAN, b4 = NAN;
827  double c1 = NAN, c2 = NAN, c3 = NAN, c4 = NAN, d1 = NAN, d2 = NAN, d3 = NAN, d4 = NAN;
828  // Assign to individual variable names to aid
829  // selecting correct values.
830  a1 = _m[0][0];
831  b1 = _m[0][1];
832  c1 = _m[0][2];
833  d1 = _m[0][3];
834  a2 = _m[1][0];
835  b2 = _m[1][1];
836  c2 = _m[1][2];
837  d2 = _m[1][3];
838  a3 = _m[2][0];
839  b3 = _m[2][1];
840  c3 = _m[2][2];
841  d3 = _m[2][3];
842  a4 = _m[3][0];
843  b4 = _m[3][1];
844  c4 = _m[3][2];
845  d4 = _m[3][3];
846  // Row column labeling reversed since we transpose rows & columns.
847  _m[0][0] = OMatrix::mat3x3Det(b2, b3, b4, c2, c3, c4, d2, d3, d4);
848  _m[1][0] = -OMatrix::mat3x3Det(a2, a3, a4, c2, c3, c4, d2, d3, d4);
849  _m[2][0] = OMatrix::mat3x3Det(a2, a3, a4, b2, b3, b4, d2, d3, d4);
850  _m[3][0] = -OMatrix::mat3x3Det(a2, a3, a4, b2, b3, b4, c2, c3, c4);
851  _m[0][1] = -OMatrix::mat3x3Det(b1, b3, b4, c1, c3, c4, d1, d3, d4);
852  _m[1][1] = OMatrix::mat3x3Det(a1, a3, a4, c1, c3, c4, d1, d3, d4);
853  _m[2][1] = -OMatrix::mat3x3Det(a1, a3, a4, b1, b3, b4, d1, d3, d4);
854  _m[3][1] = OMatrix::mat3x3Det(a1, a3, a4, b1, b3, b4, c1, c3, c4);
855  _m[0][2] = OMatrix::mat3x3Det(b1, b2, b4, c1, c2, c4, d1, d2, d4);
856  _m[1][2] = -OMatrix::mat3x3Det(a1, a2, a4, c1, c2, c4, d1, d2, d4);
857  _m[2][2] = OMatrix::mat3x3Det(a1, a2, a4, b1, b2, b4, d1, d2, d4);
858  _m[3][2] = -OMatrix::mat3x3Det(a1, a2, a4, b1, b2, b4, c1, c2, c4);
859  _m[0][3] = -OMatrix::mat3x3Det(b1, b2, b3, c1, c2, c3, d1, d2, d3);
860  _m[1][3] = OMatrix::mat3x3Det(a1, a2, a3, c1, c2, c3, d1, d2, d3);
861  _m[2][3] = -OMatrix::mat3x3Det(a1, a2, a3, b1, b2, b3, d1, d2, d3);
862  _m[3][3] = OMatrix::mat3x3Det(a1, a2, a3, b1, b2, b3, c1, c2, c3);
863 }
864 
866 {
867  OMatrix mat(*this);
868  // Adjoint
869  mat.adjoint();
870  return mat;
871 }
872 
874 {
875  // Assign to individual variable names to aid selecting
876  // correct elements.
877  double a1 = NAN, a2 = NAN, a3 = NAN, a4 = NAN, b1 = NAN, b2 = NAN, b3 = NAN, b4 = NAN, c1 = NAN, c2 = NAN,
878  c3 = NAN, c4 = NAN, d1 = NAN, d2 = NAN, d3 = NAN, d4 = NAN;
879  a1 = _m[0][0];
880  b1 = _m[0][1];
881  c1 = _m[0][2];
882  d1 = _m[0][3];
883  a2 = _m[1][0];
884  b2 = _m[1][1];
885  c2 = _m[1][2];
886  d2 = _m[1][3];
887  a3 = _m[2][0];
888  b3 = _m[2][1];
889  c3 = _m[2][2];
890  d3 = _m[2][3];
891  a4 = _m[3][0];
892  b4 = _m[3][1];
893  c4 = _m[3][2];
894  d4 = _m[3][3];
895  return a1 * OMatrix::mat3x3Det(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
896  b1 * OMatrix::mat3x3Det(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
897  c1 * OMatrix::mat3x3Det(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
898  d1 * OMatrix::mat3x3Det(a2, a3, a4, b2, b3, b4, c2, c3, c4);
899 }
900 
901 double OMatrix::mat2x2Det(double a, double b, double c, double d)
902 {
903  return a * d - b * c;
904 }
905 
906 double OMatrix::mat3x3Det(double a1, double a2, double a3, double b1, double b2, double b3, double c1,
907  double c2, double c3)
908 {
909  return a1 * OMatrix::mat2x2Det(b2, b3, c2, c3) - b1 * OMatrix::mat2x2Det(a2, a3, c2, c3) +
910  c1 * OMatrix::mat2x2Det(a2, a3, b2, b3);
911 }
912 
913 /* OGeometry ******************************************************************/
914 
915 /*static*/ bool OGeometrie::intersDemiSegmentAvecSegment(const OPoint3D& ptS, const OPoint3D& ptA,
916  const OPoint3D& ptB)
917 {
918  double eps = 0.0;
919  if (ptS._y == MAX(ptA._y, ptB._y) || ptS._y == MIN(ptA._y, ptB._y))
920  {
921  eps = EPSILON_5;
922  }
923  if ((ptS._y + eps) > MAX(ptA._y, ptB._y) || (ptS._y + eps) < MIN(ptA._y, ptB._y) ||
924  ptS._x > MAX(ptA._x, ptB._x))
925  {
926  return false;
927  }
928  if (ptS._x <= MIN(ptA._x, ptB._x))
929  {
930  return true;
931  }
932  double ca = (ptA._x != ptB._x) ? coeff_ang(ptA, ptB) : HUGE_VAL;
933  OPoint3D my = minP(ptA, ptB, _y);
934  double cp = (ptS._x - my._x) ? coeff_ang(my, ptS) : HUGE_VAL;
935  return cp >= ca;
936 }
937 
938 /*static*/ int OGeometrie::intersDroitesPoints(const OPoint3D& ptA, const OPoint3D& ptB, const OPoint3D& ptC,
939  const OPoint3D& ptD, OPoint3D& ptI)
940 {
941  int res = INTERS_NULLE;
942  double k = NAN;
943  double d = (ptC._x - ptD._x) * (ptA._y - ptB._y) - (ptC._y - ptD._y) * (ptA._x - ptB._x);
944  k = 0;
945  if (ABS(d) > 0.0)
946  {
947  k = ((ptA._x - ptD._x) * (ptA._y - ptB._y) - (ptA._y - ptD._y) * (ptA._x - ptB._x)) / d;
948  res = INTERS_OUI;
949  }
950  else
951  {
952  d = (ptC._x - ptD._x) * (ptA._z - ptB._z) - (ptC._z - ptD._z) * (ptA._x - ptB._x);
953  if (ABS(d) > 0.0)
954  {
955  k = ((ptA._x - ptD._x) * (ptA._z - ptB._z) - (ptA._z - ptD._z) * (ptA._x - ptB._x)) / d;
956  res = INTERS_OUI;
957  }
958  else
959  {
960  d = (ptC._y - ptD._y) * (ptA._z - ptB._z) - (ptC._z - ptD._z) * (ptA._y - ptB._y);
961  if (ABS(d) > 0.0)
962  {
963  k = ((ptA._y - ptD._y) * (ptA._z - ptB._z) - (ptA._z - ptD._z) * (ptA._y - ptB._y)) / d;
964  res = INTERS_OUI;
965  }
966  }
967  }
968  if (res)
969  {
970  ptI._x = ptD._x + k * (ptC._x - ptD._x);
971  ptI._y = ptD._y + k * (ptC._y - ptD._y);
972  ptI._z = ptD._z + k * (ptC._z - ptD._z);
973  }
974  return res;
975 }
976 
977 /*static*/ int OGeometrie::intersDroitesPointVecteur(const OPoint3D& ptA, const OVector3D& vecA,
978  const OPoint3D& ptB, const OVector3D& vecB,
979  OPoint3D& ptI)
980 {
981  OVector3D vecA1, vecB1;
982  vecA1 = OVector3D(ptA) + vecA;
983  vecB1 = OVector3D(ptB) + vecB;
984  return intersDroitesPoints(ptA, OPoint3D(vecA1), ptB, OPoint3D(vecB1), ptI);
985 }
986 
987 /*static*/ double OGeometrie::symPointDroite(const OPoint3D& ptA, const OPoint3D& ptB, const OPoint3D& ptP,
988  OPoint3D& ptI)
989 {
990  // Determination du point M tel que :
991  // Vecteur PM perpendiculaire a Vecteur AB
992  // Vecteur AM colineaire a Vecteur AB
993  OVector3D vecAB(ptA, ptB);
994  OVector3D vecPtA(ptA);
995  OVector3D vecPtP(ptP);
996  double k = NAN;
997  k = (ptP._x - ptA._x) * vecAB._x + (ptP._y - ptA._y) * vecAB._y + (ptP._z - ptA._z) * vecAB._z;
998  k /= vecAB._x * vecAB._x + vecAB._y * vecAB._y + vecAB._z * vecAB._z;
999  // Determination de P', image de P par rapport a M
1000  // P' = OA + AM + MP' = OA + AM + PM
1001  // Avec OA = ptA
1002  // AM = k.AB
1003  // PM = PA + kAB = (ptA - ptP) + kAB
1004  // Soit P' = ptA + kAB + ptA - ptP + kAB
1005  // = 2(ptA + kAB) - ptP
1006 
1007  // This is evil ! What the hell has it been put here for ?
1008  // *(OCoord3D*)&ptI = *(OCoord3D*) & (2 * (vecPtA + (k * vecAB)) - vecPtP);
1009  // Why be so complicated
1010  // (OCoord3D)ptI = (OCoord3D)(2 * (vecPtA + (k * vecAB)) - vecPtP);
1011  // A very simple solution !
1012  ptI = 2 * (vecPtA + (k * vecAB)) - vecPtP;
1013  return k;
1014 }
1015 
1016 /*static*/ bool OGeometrie::pointInPolygonAngleSum(const OPoint3D& ptP, const OPoint3D* pts, int nbPts)
1017 {
1018  int i = 0;
1019  double m1m2 = NAN;
1020  double angle = NAN;
1021  double anglesum = 0;
1022  double sign = 1;
1023  OVector3D vec1(ptP, pts[0]);
1024  OVector3D vec2;
1025  for (i = 0; i < nbPts; i++)
1026  {
1027  vec2 = OVector3D(ptP, pts[(i + 1) % nbPts]);
1028  m1m2 = vec1.norme() * vec2.norme();
1029  if (m1m2 <= EPSILON_6)
1030  {
1031  // We are on a node, consider this inside
1032  return true;
1033  }
1034  // Angle forme par les 2 vecteurs
1035  angle = acos((vec1.scalar(vec2)) / (m1m2));
1036  // Signe de l'angle
1037  sign = (vec1.cross(vec2)._z > 0) ? -1 : 1;
1038  anglesum += (angle * sign);
1039  vec1 = vec2;
1040  }
1041  // Le total des angles doit etre egal a 2Pi (a Epsilon pres)
1042  return ((ABS(anglesum) > (M_2PI - EPSILON_6)) && (ABS(anglesum) < (M_2PI + EPSILON_6)));
1043 }
1044 
1045 // in 2D
1046 /*static*/ bool OGeometrie::pointInPolygonRayCasting(const OPoint3D& ptP, const OPoint3D* pts, int nbPts)
1047 {
1048  int cross = 0, i = 0;
1049  for (i = 0; i < nbPts - 1; i++)
1050  {
1051  if (intersDemiSegmentAvecSegment(ptP, pts[i], pts[i + 1]))
1052  {
1053  cross++;
1054  }
1055  }
1056  if (intersDemiSegmentAvecSegment(ptP, pts[i], pts[0]))
1057  {
1058  cross++;
1059  }
1060  return cross % 2 != 0;
1061 }
1062 
1063 /*static*/ bool OGeometrie::shortestSegBetween2Lines(const OPoint3D& pt1, const OPoint3D& pt2,
1064  const OPoint3D& pt3, const OPoint3D& pt4, OPoint3D& ptA,
1065  OPoint3D& ptB, double* mua, double* mub)
1066 {
1067  OPoint3D p13, p43, p21;
1068  double d1343 = NAN, d4321 = NAN, d1321 = NAN, d4343 = NAN, d2121 = NAN;
1069  double numer = NAN, denom = NAN;
1070  p13._x = pt1._x - pt3._x;
1071  p13._y = pt1._y - pt3._y;
1072  p13._z = pt1._z - pt3._z;
1073  p43._x = pt4._x - pt3._x;
1074  p43._y = pt4._y - pt3._y;
1075  p43._z = pt4._z - pt3._z;
1076  if ((ABS(p43._x) < EPSILON_6) && (ABS(p43._y) < EPSILON_6) && (ABS(p43._z) < EPSILON_6))
1077  {
1078  return false;
1079  }
1080  p21._x = pt2._x - pt1._x;
1081  p21._y = pt2._y - pt1._y;
1082  p21._z = pt2._z - pt1._z;
1083  if ((ABS(p21._x) < EPSILON_6) && (ABS(p21._y) < EPSILON_6) && (ABS(p21._z) < EPSILON_6))
1084  {
1085  return false;
1086  }
1087  d1343 = p13._x * p43._x + p13._y * p43._y + p13._z * p43._z;
1088  d4321 = p43._x * p21._x + p43._y * p21._y + p43._z * p21._z;
1089  d1321 = p13._x * p21._x + p13._y * p21._y + p13._z * p21._z;
1090  d4343 = p43._x * p43._x + p43._y * p43._y + p43._z * p43._z;
1091  d2121 = p21._x * p21._x + p21._y * p21._y + p21._z * p21._z;
1092  denom = d2121 * d4343 - d4321 * d4321;
1093  if (ABS(denom) < EPSILON_6)
1094  {
1095  return false;
1096  }
1097  numer = d1343 * d4321 - d1321 * d4343;
1098  *mua = numer / denom;
1099  *mub = (d1343 + d4321 * (*mua)) / d4343;
1100  ptA._x = pt1._x + *mua * p21._x;
1101  ptA._y = pt1._y + *mua * p21._y;
1102  ptA._z = pt1._z + *mua * p21._z;
1103  ptB._x = pt3._x + *mub * p43._x;
1104  ptB._y = pt3._y + *mub * p43._y;
1105  ptB._z = pt3._z + *mub * p43._z;
1106  return true;
1107 }
1108 
1109 /*static*/ void OGeometrie::boundingBox(OPoint3D* pts, int nbPts, OPoint3D& ptMin, OPoint3D& ptMax)
1110 {
1111  if (nbPts <= 0)
1112  {
1113  return;
1114  }
1115  ptMax = ptMin = pts[0];
1116  for (int i = 0; i < nbPts; i++)
1117  {
1118  // Minimuns
1119  if (pts[i]._x <= ptMin._x)
1120  {
1121  ptMin._x = pts[i]._x;
1122  }
1123  if (pts[i]._y <= ptMin._y)
1124  {
1125  ptMin._y = pts[i]._y;
1126  }
1127  if (pts[i]._z <= ptMin._z)
1128  {
1129  ptMin._z = pts[i]._z;
1130  }
1131  // Maximums
1132  if (pts[i]._x >= ptMax._x)
1133  {
1134  ptMax._x = pts[i]._x;
1135  }
1136  if (pts[i]._y >= ptMax._y)
1137  {
1138  ptMax._y = pts[i]._y;
1139  }
1140  if (pts[i]._z >= ptMax._z)
1141  {
1142  ptMax._z = pts[i]._z;
1143  }
1144  }
1145 }
1146 
1147 /* static */ void OGeometrie::computeNormal(OPoint3D* pts, int nbPts, OVector3D& normal)
1148 {
1149  double ax = NAN, ay = NAN, az = NAN, bx = NAN, by = NAN, bz = NAN;
1150  // Because polygon may be concave, need to accumulate cross products to
1151  // determine true normal.
1152  // assert(nbPts>=3);
1153  OVector3D vec(0, 0, 0);
1154  OVector3D vecPt0; // set things up for loop
1155  OVector3D vecPt1(pts[0]);
1156  OVector3D vecPt2(pts[1]);
1157  for (int i = 2; i < nbPts; i++)
1158  {
1159  vecPt0 = vecPt1;
1160  vecPt1 = vecPt2;
1161  vecPt2 = OVector3D(pts[i]);
1162  // order is important!!! to maintain consistency with polygon vertex order
1163  ax = vecPt2._x - vecPt1._x;
1164  ay = vecPt2._y - vecPt1._y;
1165  az = vecPt2._z - vecPt1._z;
1166  bx = vecPt0._x - vecPt1._x;
1167  by = vecPt0._y - vecPt1._y;
1168  bz = vecPt0._z - vecPt1._z;
1169  vec._x += (ay * bz - az * by);
1170  vec._y += (az * bx - ax * bz);
1171  vec._z += (ax * by - ay * bx);
1172  }
1173  vec.normalize();
1174  normal = vec;
1175 }
1176 
1177 /* OSegment3D *****************************************************************/
1178 
1180 {
1181  _ptA._x = 0;
1182  _ptA._y = 0;
1183  _ptA._z = 0;
1184  _ptB._x = 0;
1185  _ptB._y = 1;
1186  _ptB._z = 0;
1187 }
1188 
1190 {
1191  *this = other;
1192 }
1193 
1195 {
1196  _ptA = ptA;
1197  _ptB = ptB;
1198 }
1199 
1201 
1203 {
1204  if (this != &other)
1205  {
1206  _ptA = other._ptA;
1207  _ptB = other._ptB;
1208  }
1209  return *this;
1210 }
1211 
1212 bool OSegment3D::operator==(const OSegment3D& other) const
1213 {
1214  if (this != &other)
1215  {
1216  if (_ptA != other._ptA)
1217  {
1218  return false;
1219  }
1220  if (_ptB != other._ptB)
1221  {
1222  return false;
1223  }
1224  }
1225  return true;
1226 }
1227 
1228 bool OSegment3D::operator!=(const OSegment3D& other) const
1229 {
1230  return !operator==(other);
1231 }
1232 
1234 {
1235  return OSegment3D(matrix * _ptA, matrix * _ptB);
1236 }
1237 
1238 double OSegment3D::longueur() const
1239 {
1240  return OVector3D(_ptA, _ptB).norme();
1241 }
1242 
1243 int OSegment3D::symetrieOf(const OPoint3D& pt, OPoint3D& ptSym) const
1244 {
1245  int res = 0;
1246  // Calcul le pt image a ptSym (pt source) par rapport a la droite definie passant
1247  // par ce segment
1248  double k = OGeometrie::symPointDroite(_ptA, _ptB, pt, ptSym);
1249  // Le coefficient k indique si le segment [Point source / Point image] coupe
1250  // ce segment, pour cela il faut : 0 < k < 1.
1251  if ((0.0 <= k) && (k <= 1.0))
1252  {
1253  res = 1;
1254  }
1255  return res;
1256 }
1257 
1258 int OSegment3D::projection(const OPoint3D& pt, OPoint3D& ptProj, double seuilConfondus) const
1259 {
1260  int res = 0;
1261  OPoint3D ptSym;
1262  res = symetrieOf(pt, ptSym);
1263  res = res && intersects(OSegment3D(pt, ptSym), ptProj, seuilConfondus);
1264  return res;
1265 }
1266 
1267 int OSegment3D::intersects(const OSegment3D& seg, OPoint3D& pt, double seuilConfondus) const
1268 {
1269  int res = INTERS_NULLE;
1270  OPoint3D ptA, ptB;
1271  double mua = NAN, mub = NAN;
1272  // Calcul le segment le plus court entre les 2 segments dont on recherche l'eventuelle intersection
1273  if (OGeometrie::shortestSegBetween2Lines(this->_ptA, this->_ptB, seg._ptA, seg._ptB, ptA, ptB, &mua,
1274  &mub))
1275  {
1276  // Les coefs mua et mub doivent etre compris entre 0 et 1 pour que les points constituant
1277  // le segment trouve se trouve sur les segments respectifs a tester
1278  if ((0.0 <= mua) && (mua <= 1.0) && (0.0 <= mub) && (mub <= 1.0))
1279  {
1280  // La norme du segment trouve doit etre inferieur a un seuil pour que l'on puisse admettre
1281  // que les 2 points constituant ce segment sont quasi confondus
1282  OVector3D vecSeg(ptA, ptB);
1283  if (vecSeg.norme() <= seuilConfondus)
1284  {
1285  res = INTERS_OUI;
1286  // Arbitrairement on prend le 1er point du segment trouve comme point d'intersection.
1287  pt = ptA;
1288  }
1289  }
1290  }
1291  return res;
1292 }
1293 
1295 {
1296  double x = NAN, y = NAN, z = NAN;
1297  x = ((_ptB._x - _ptA._x) / 2.0) + _ptA._x;
1298  y = ((_ptB._y - _ptA._y) / 2.0) + _ptA._y;
1299  z = ((_ptB._z - _ptA._z) / 2.0) + _ptA._z;
1300  return OPoint3D(x, y, z);
1301 }
1302 
1304 {
1305  OPoint3D point;
1306  OPoint3D milieu = centreOf();
1307  double demiLongueur = longueur() / 2;
1308  double x = NAN, y = NAN, z = NAN;
1309  x = milieu._x;
1310  y = milieu._y;
1311  z = milieu._z;
1312  if (R > demiLongueur)
1313  {
1314  double d = sqrt(R * R - demiLongueur * demiLongueur);
1315  if (_ptA._z != _ptB._z)
1316  {
1317  d = d * SIGNE(_ptA._z - _ptB._z);
1318  double q = (_ptB._y - _ptA._y) / (_ptB._z - _ptA._z);
1319  y = milieu._y + d / sqrt(1 + q * q);
1320  }
1321  z = milieu._z + sqrt(ABS(d * d - (y - milieu._y) * (y - milieu._y)));
1322  }
1323  point.setCoords(x, y, z);
1324  return point;
1325 }
1326 
1327 double OSegment3D::lengthOfCurvedPath(const double& R)
1328 {
1329  // Longueur du cote du triangle rectangle
1330  double cote = longueur() / 2.0;
1331  // Angle d'ouverture du segment
1332  double angle = 2 * asin(cote / R);
1333  return angle * R;
1334 }
1335 
1337 {
1338  OSegment3D seg(*this);
1339  OPoint3D PT = seg._ptA;
1340  seg._ptA = seg._ptB;
1341  seg._ptB = PT;
1342  return seg;
1343 }
1344 
1345 /* ORepere3D ******************************************************************/
1346 
1347 ORepere3D::ORepere3D() : _origin(0, 0, 0), _vecI(1, 0, 0), _vecJ(0, 1, 0), _vecK(0, 0, 1) {}
1348 
1350 {
1351  *this = repere;
1352 }
1353 
1354 ORepere3D::ORepere3D(const OPoint3D& origin, const OVector3D& vecI, const OVector3D& vecJ,
1355  const OVector3D& vecK)
1356  : _origin(origin), _vecI(vecI), _vecJ(vecJ), _vecK(vecK)
1357 {
1358 }
1359 
1361 {
1362  set(matrix);
1363 }
1364 
1365 ORepere3D::ORepere3D(const OPoint3D& origin, const OVector3D& vec) : _origin(origin), _vecI(vec)
1366 {
1367  /*
1368  1. On pose x1 = x2 et z1 = z2 (sinon infinité de solution)
1369  x1.x1 + y1.y2 + z1.z1 = 0 (produit scalaire)
1370  y1.y2 = - (x1.x2 + z1.z2)
1371  donc y2 = - (x1.x2 + z1.z2) / y1
1372 
1373  Si y1 = 0 (plan xOz) -> n'importe quelle valeur de y valide
1374  */
1375  double x1 = _vecI._x, y1 = _vecI._y, z1 = _vecI._z;
1376  double y2 = (y1 != 0.) ? -(x1 * x1 + z1 * z1) / y1 : -(x1 * x1 + z1 * z1);
1377  _vecJ = OVector3D(x1, -y2, z1); // -y pour orienter correctement le repère
1378  _vecK = _vecI.cross(_vecJ);
1379  _vecI.normalize();
1380  _vecJ.normalize();
1381  _vecK.normalize();
1382 }
1383 
1385 
1387 {
1388  if (this != &repere)
1389  {
1390  _origin = repere._origin;
1391  _vecI = repere._vecI;
1392  _vecJ = repere._vecJ;
1393  _vecK = repere._vecK;
1394  }
1395  return *this;
1396 }
1397 
1398 bool ORepere3D::operator==(const ORepere3D& repere) const
1399 {
1400  if (this != &repere)
1401  {
1402  if (_origin != repere._origin)
1403  {
1404  return false;
1405  }
1406  if (_vecI != repere._vecI)
1407  {
1408  return false;
1409  }
1410  if (_vecJ != repere._vecJ)
1411  {
1412  return false;
1413  }
1414  if (_vecK != repere._vecK)
1415  {
1416  return false;
1417  }
1418  }
1419  return true;
1420 }
1421 
1422 bool ORepere3D::operator!=(const ORepere3D& repere) const
1423 {
1424  return !operator==(repere);
1425 }
1426 
1427 void ORepere3D::set(const OPoint3D& origin, const OVector3D& vecI, const OVector3D& vecJ,
1428  const OVector3D& vecK)
1429 {
1430  _origin = origin;
1431  _vecI = vecI;
1432  _vecJ = vecJ;
1433  _vecK = vecK;
1434 }
1435 
1436 void ORepere3D::set(const OMatrix& matrix)
1437 {
1438  _vecI._x = matrix._m[0][0];
1439  _vecI._y = matrix._m[1][0];
1440  _vecI._z = matrix._m[2][0];
1441  _vecI.normalize();
1442  _vecJ._x = matrix._m[0][1];
1443  _vecJ._y = matrix._m[1][1];
1444  _vecJ._z = matrix._m[2][1];
1445  _vecJ.normalize();
1446  _vecK._x = matrix._m[0][2];
1447  _vecK._y = matrix._m[1][2];
1448  _vecK._z = matrix._m[2][2];
1449  _vecK.normalize();
1450  _origin._x = matrix._m[0][3];
1451  _origin._y = matrix._m[1][3];
1452  _origin._z = matrix._m[2][3];
1453 }
1454 
1456 {
1457  _vecI.normalize();
1458  _vecJ.normalize();
1459  _vecK.normalize();
1460 }
1461 
1463 {
1464  ORepere3D rep;
1465  rep.set(_origin, _vecI, _vecJ, _vecK);
1466  rep.normalize();
1467  OMatrix matrix;
1468  matrix.unite();
1469  matrix._m[0][0] = rep._vecI._x;
1470  matrix._m[0][1] = rep._vecJ._x;
1471  matrix._m[0][2] = rep._vecK._x;
1472  matrix._m[0][3] = rep._origin._x;
1473  matrix._m[1][0] = rep._vecI._y;
1474  matrix._m[1][1] = rep._vecJ._y;
1475  matrix._m[1][2] = rep._vecK._y;
1476  matrix._m[1][3] = rep._origin._y;
1477  matrix._m[2][0] = rep._vecI._z;
1478  matrix._m[2][1] = rep._vecJ._z;
1479  matrix._m[2][2] = rep._vecK._z;
1480  matrix._m[2][3] = rep._origin._z;
1481  return matrix;
1482 }
1483 
1484 /* OBox ***********************************************************************/
1485 
1487 {
1488  _min._x = _min._y = _min._z = _max._x = _max._y = _max._z = 0;
1489 }
1490 
1491 OBox::OBox(const OBox& box)
1492 {
1493  _min = box._min;
1494  _max = box._max;
1495 }
1496 
1497 OBox::OBox(const OCoord3D& min, const OCoord3D& max)
1498 {
1499  _min = min;
1500  _max = max;
1501 }
1502 
1503 OBox::OBox(double x1, double y1, double z1, double x2, double y2, double z2)
1504 {
1505  _min = OPoint3D(x1, y1, z1);
1506  _max = OPoint3D(x2, y2, z2);
1507 }
1508 
1510 {
1511  if (this != &box)
1512  {
1513  _min = box._min;
1514  _max = box._max;
1515  }
1516  return *this;
1517 }
1518 
1519 bool OBox::operator==(const OBox& box) const
1520 {
1521  if (this != &box)
1522  {
1523  if (_min != box._min)
1524  {
1525  return false;
1526  }
1527  if (_max != box._max)
1528  {
1529  return false;
1530  }
1531  }
1532  return true;
1533 }
1534 
1535 bool OBox::isInside(const OPoint3D& pt) const
1536 {
1537  if (pt._x < _min._x)
1538  {
1539  return false;
1540  }
1541  if (pt._x > _max._x)
1542  {
1543  return false;
1544  }
1545  if (pt._y < _min._y)
1546  {
1547  return false;
1548  }
1549  if (pt._y > _max._y)
1550  {
1551  return false;
1552  }
1553  if (pt._z < _min._z)
1554  {
1555  return false;
1556  }
1557  if (pt._z > _max._z)
1558  {
1559  return false;
1560  }
1561  return true;
1562 }
1563 
1564 bool OBox::isInside2D(const OPoint3D& pt) const
1565 {
1566  if (pt._x < _min._x)
1567  {
1568  return false;
1569  }
1570  if (pt._x > _max._x)
1571  {
1572  return false;
1573  }
1574  if (pt._y < _min._y)
1575  {
1576  return false;
1577  }
1578  if (pt._y > _max._y)
1579  {
1580  return false;
1581  }
1582  return true;
1583 }
1584 
1585 bool OBox::isInContact(const OBox& box) const
1586 {
1587  if (_max._x < box._min._x)
1588  {
1589  return false;
1590  }
1591  if (_min._x > box._max._x)
1592  {
1593  return false;
1594  }
1595  if (_max._y < box._min._y)
1596  {
1597  return false;
1598  }
1599  if (_min._y > box._max._y)
1600  {
1601  return false;
1602  }
1603  if (_max._z < box._min._z)
1604  {
1605  return false;
1606  }
1607  if (_min._z > box._max._z)
1608  {
1609  return false;
1610  }
1611  return true;
1612 }
1613 
1614 void OBox::Enlarge(const OPoint3D& pt)
1615 {
1616  if (_min._x == 0 && _min._y == 0 && _min._z == 0 && _max._x == 0 && _max._y == 0 && _max._z == 0)
1617  {
1618  _min._x = pt._x;
1619  _max._x = pt._x;
1620  _min._y = pt._y;
1621  _max._y = pt._y;
1622  _min._z = pt._z;
1623  _max._z = pt._z;
1624  }
1625  else
1626  {
1627  if (pt._x < _min._x)
1628  {
1629  _min._x = pt._x;
1630  }
1631  if (pt._x > _max._x)
1632  {
1633  _max._x = pt._x;
1634  }
1635  if (pt._y < _min._y)
1636  {
1637  _min._y = pt._y;
1638  }
1639  if (pt._y > _max._y)
1640  {
1641  _max._y = pt._y;
1642  }
1643  if (pt._z < _min._z)
1644  {
1645  _min._z = pt._z;
1646  }
1647  if (pt._z > _max._z)
1648  {
1649  _max._z = pt._z;
1650  }
1651  }
1652 }
1653 
1654 void OBox::Enlarge(float x, float y, float z)
1655 {
1656  OPoint3D pt(x, y, z);
1657  Enlarge(pt);
1658 }
1659 
1660 void OBox::Enlarge(const OBox& box)
1661 {
1662  if (box._min._x < _min._x)
1663  {
1664  _min._x = box._min._x;
1665  }
1666  if (box._min._y < _min._y)
1667  {
1668  _min._y = box._min._y;
1669  }
1670  if (box._min._z < _min._z)
1671  {
1672  _min._z = box._min._z;
1673  }
1674  if (box._max._x > _max._x)
1675  {
1676  _max._x = box._max._x;
1677  }
1678  if (box._max._y > _max._y)
1679  {
1680  _max._y = box._max._y;
1681  }
1682  if (box._max._z > _max._z)
1683  {
1684  _max._z = box._max._z;
1685  }
1686 }
1687 
1688 void OBox::Translate(const OPoint3D& vectorTranslate)
1689 {
1690  _min._x += vectorTranslate._x;
1691  _min._y += vectorTranslate._y;
1692  _min._z += vectorTranslate._z;
1693  _max._x += vectorTranslate._x;
1694  _max._y += vectorTranslate._y;
1695  _max._z += vectorTranslate._z;
1696 }
1697 
1698 /* OBox2 **********************************************************************/
1699 
1701  : OBox(), _repere(ORepere3D()), _center(0.0, 0.0, 0.0), _A(0.0, 0.0, 0.0), _B(0.0, 0.0, 0.0),
1702  _C(0.0, 0.0, 0.0), _D(0.0, 0.0, 0.0), _E(0.0, 0.0, 0.0), _F(0.0, 0.0, 0.0), _G(0.0, 0.0, 0.0),
1703  _H(0.0, 0.0, 0.0), _length(0.0), _height(0.0), _width(0.0)
1704 {
1705 }
1706 
1707 OBox2::OBox2(const OBox2& box)
1708 {
1709  *this = box;
1710 }
1711 
1712 OBox2::OBox2(const OBox& box)
1713 {
1714  _repere = ORepere3D();
1715  _min = box._min;
1716  _max = box._max;
1717  double minX = _min._x, minY = _min._y, minZ = _min._z;
1718  double maxX = _max._x, maxY = _max._y, maxZ = _max._z;
1719  _center = OPoint3D((maxX - minX) / 2.0 + minX, (maxY - minY) / 2.0 + minY, (maxZ - minZ) / 2.0 + minZ);
1720  _length = maxX - minX;
1721  _width = maxY - minY;
1722  _height = maxZ - minZ;
1723  _A = OPoint3D(minX, minY, minZ);
1724  _B = OPoint3D(minX, maxY, minZ);
1725  _C = OPoint3D(maxX, maxY, minZ);
1726  _D = OPoint3D(maxX, minY, minZ);
1727  _E = OPoint3D(maxX, minY, maxZ);
1728  _F = OPoint3D(minX, minY, maxZ);
1729  _G = OPoint3D(minX, maxY, maxZ);
1730  _H = OPoint3D(maxX, maxY, maxZ);
1731  _repere._origin = _A;
1732 }
1733 
1734 OBox2::OBox2(const OBox2& box, const ORepere3D& repere, const OPoint3D& centre)
1735 {
1736  _min = box._min;
1737  _max = box._max;
1738  _repere = repere;
1739  _center = OPoint3D(centre._x, centre._y, centre._z);
1740  _length = box._max._x;
1741  _height = box._max._z;
1742  _width = box._max._y;
1743  _A = box._A;
1744  _B = box._B;
1745  _C = box._C;
1746  _D = box._D;
1747  _E = box._E;
1748  _F = box._F;
1749  _G = box._G;
1750  _H = box._H;
1751 }
1752 
1753 OBox2::OBox2(const double& length, const double& width, const double& height)
1754  : _center(OPoint3D(0.0, 0.0, 0.0)), _length(length), _height(height), _width(width)
1755 {
1756  double minX = -_length / 2.0, minY = -_width / 2.0, minZ = -_height / 2.0, maxX = minX + _length,
1757  maxY = minY + _width, maxZ = minZ + _height;
1758 
1759  _A = _min = OPoint3D(minX, minY, minZ);
1760  _B = OPoint3D(minX, maxY, minZ);
1761  _C = OPoint3D(maxX, maxY, minZ);
1762  _D = OPoint3D(maxX, minY, minZ);
1763  _E = OPoint3D(maxX, minY, maxZ);
1764  _F = OPoint3D(minX, minY, maxZ);
1765  _G = OPoint3D(minX, maxY, maxZ);
1766  _H = _max = OPoint3D(maxX, maxY, maxZ);
1767 }
1768 
1770 {
1771  if (this != &box)
1772  {
1773  OBox::operator=(box);
1774  _repere = box._repere;
1775  _center = box._center;
1776  _A = box._A;
1777  _B = box._B;
1778  _C = box._C;
1779  _D = box._D;
1780  _E = box._E;
1781  _F = box._F;
1782  _G = box._G;
1783  _H = box._H;
1784  _length = box._length;
1785  _height = box._height;
1786  _width = box._width;
1787  }
1788  return *this;
1789 }
1790 
1791 bool OBox2::operator==(const OBox2& box) const
1792 {
1793  if (this != &box)
1794  {
1795  if (_min != box._min)
1796  {
1797  return false;
1798  }
1799  if (_max != box._max)
1800  {
1801  return false;
1802  }
1803  if (_repere != box._repere)
1804  {
1805  return false;
1806  }
1807  if (_center != box._center)
1808  {
1809  return false;
1810  }
1811  if (_A != box._A)
1812  {
1813  return false;
1814  }
1815  if (_B != box._B)
1816  {
1817  return false;
1818  }
1819  if (_C != box._C)
1820  {
1821  return false;
1822  }
1823  if (_D != box._D)
1824  {
1825  return false;
1826  }
1827  if (_E != box._E)
1828  {
1829  return false;
1830  }
1831  if (_F != box._F)
1832  {
1833  return false;
1834  }
1835  if (_G != box._G)
1836  {
1837  return false;
1838  }
1839  if (_H != box._H)
1840  {
1841  return false;
1842  }
1843  if (_length != box._length)
1844  {
1845  return false;
1846  }
1847  if (_height != box._height)
1848  {
1849  return false;
1850  }
1851  if (_width != box._width)
1852  {
1853  return false;
1854  }
1855  }
1856  return true;
1857 }
1858 
1860 {
1861  switch (N)
1862  {
1863  case (0):
1864  return _center;
1865  case (1):
1866  return _A;
1867  case (2):
1868  return _B;
1869  case (3):
1870  return _C;
1871  case (4):
1872  return _D;
1873  case (5):
1874  return _E;
1875  case (6):
1876  return _F;
1877  case (7):
1878  return _G;
1879  case (8):
1880  return _H;
1881  default:
1882  OPoint3D zero = OPoint3D(0.0, 0.0, 0.0);
1883  return zero;
1884  }
1885 }
1886 
1887 bool OBox2::isInside(const OPoint3D& pt) const
1888 {
1889  OPoint3D point2;
1890  // OpM (OprimeM) is the vector from the box center to point p
1891  OVector3D OpM =
1893  // point2 has its coordinates in the other coordinates system (the box system)
1894  point2._x = OpM._x * _repere._vecI._x;
1895  point2._y = OpM._y * _repere._vecJ._y;
1896  point2._z = OpM._z * _repere._vecK._z;
1897  return OBox::isInside(point2);
1898 }
1899 
1900 bool OBox2::isInside2D(const OPoint3D& pt) const
1901 {
1902  OPoint3D point2;
1903  // OpM (OprimeM) is the vector from the box center to point p
1904  OVector3D OpM =
1906  // point2 has its coordinates in the other coordinates system (the box system)
1907  point2._x = OpM._x * _repere._vecI._x;
1908  point2._y = OpM._y * _repere._vecJ._y;
1909  point2._z = OpM._z * _repere._vecK._z;
1910 
1911  return OBox::isInside2D(point2);
1912 }
1913 
1914 void OBox2::Translate(const OVector3D& vect)
1915 {
1916  _center = _center + vect;
1917  _A = _A + vect;
1918  _B = _B + vect;
1919  _C = _C + vect;
1920  _D = _D + vect;
1921  _E = _E + vect;
1922  _F = _F + vect;
1923  _G = _G + vect;
1924  _H = _H + vect;
1925 }
1926 
1928 {
1929  OBox2 box, boxIn = *this;
1930  // 3/ Changement de repere pour faire pivoter la boite
1931  // The aim here is to make a rotation of the bounding box
1932  // We want its main axis to be aligned with Vector v2 i.e. [OPsuiv].
1933  // We have to keep in mind that axes are defined from the bottom left corner
1934  // of the box.
1935  // This step is a bit tricky : one has to keep in mind in
1936  // which plane(s) the rotation(s) occur(s).
1937  // 3D rotation : 2 rotations around two different axes
1938  // (pay attention to get the right ones!);
1939  // 2D rotation : only one movement => define the right axis.
1940  // Let x1, y1, z1 and x2, y2, z2 be the vectors after the first rotation
1941  // and the second one, respectively expressed in the new basis B1 and B2.
1942  // Let xf, yf, zf be the final vectors given to the box, i.e. x2,y2 and z2
1943  // in B0.
1944 
1945  // Let I be the point at coordinate(L, l/2, l/2)
1946  // This point will be useful to create a vector from the box centre to I
1947  // This is a way of creating an axis within the box in order to compute
1948  // the angle between the box main axis and vector v2
1949  OPoint3D I = OPoint3D(this->_H._x, O._y, O._z);
1950  // Let v1 be the vector between the box centre (O) and I
1951  // Let v2 be the vector between the box centre (O) and Psuiv
1952  OVector3D v1 = OVector3D(O, I);
1953  OVector3D v2 = OVector3D(O, P2);
1954 
1955  v2.normalize();
1956  v1.normalize();
1957 
1958  if (v1._z == 0 && v2._z == 0)
1959  {
1960  // When v1 and v2 are in xOy plane only
1961  return this->rotInXOYOnly(v1, v2, O, P2);
1962  }
1963  else if (v1._y == 0 && v2._y == 0)
1964  {
1965  // When v1 and v2 are in xOz plane only
1966  return this->rotInXOZOnly(v1, v2, O, P2);
1967  }
1968  else
1969  {
1970  // When it's a 3d rotation, things get a little more "funny".
1971  return this->rot3D(v1, v2, O, P2);
1972  }
1973  return box;
1974 }
1975 
1976 void OBox2::BoxRotationOzOy(double alpha, double theta)
1977 {
1978  // We create vectors from the box center to the corners
1979  OVector3D OA(_center, _A);
1980  OVector3D OB(_center, _B);
1981  OVector3D OC(_center, _C);
1982  OVector3D OD(_center, _D);
1983  OVector3D OE(_center, _E);
1984  OVector3D OF(_center, _F);
1985  OVector3D OG(_center, _G);
1986  OVector3D OH(_center, _H);
1987  // These vectors are modified by two rotations
1988  OVector3D OAf = OA.getRotationOzOy(alpha, theta);
1989  OVector3D OBf = OB.getRotationOzOy(alpha, theta);
1990  OVector3D OCf = OC.getRotationOzOy(alpha, theta);
1991  OVector3D ODf = OD.getRotationOzOy(alpha, theta);
1992  OVector3D OEf = OE.getRotationOzOy(alpha, theta);
1993  OVector3D OFf = OF.getRotationOzOy(alpha, theta);
1994  OVector3D OGf = OG.getRotationOzOy(alpha, theta);
1995  OVector3D OHf = OH.getRotationOzOy(alpha, theta);
1996  // It changes the box properties
1997  _A.setCoords(OAf._x + _center._x, OAf._y + _center._y, OAf._z + _center._z);
1998  _B.setCoords(OBf._x + _center._x, OBf._y + _center._y, OBf._z + _center._z);
1999  _C.setCoords(OCf._x + _center._x, OCf._y + _center._y, OCf._z + _center._z);
2000  _D.setCoords(ODf._x + _center._x, ODf._y + _center._y, ODf._z + _center._z);
2001  _E.setCoords(OEf._x + _center._x, OEf._y + _center._y, OEf._z + _center._z);
2002  _F.setCoords(OFf._x + _center._x, OFf._y + _center._y, OFf._z + _center._z);
2003  _G.setCoords(OGf._x + _center._x, OGf._y + _center._y, OGf._z + _center._z);
2004  _H.setCoords(OHf._x + _center._x, OHf._y + _center._y, OHf._z + _center._z);
2005  _min = _A;
2006  _max = _H;
2007 }
2008 
2009 OBox2 OBox2::rotInXOYOnly(const OVector3D& v1, const OVector3D& v2, const OPoint3D& O, const OPoint3D& P2)
2010 {
2011  OBox2 box = *this;
2012  OVector3D x0 = v1;
2013  // Creates a basis with 3 vectors x0, y0 and z0.
2014  // x0 -> x2, y0 -> y2 and z0 remains the same.
2015  OVector3D y0 = OCoord3D(0.0, 1.0, 0.0);
2016  OVector3D z0 = OCoord3D(0.0, 0.0, 1.0);
2017  double alpha = v1.angle(v2);
2018  OVector3D x2 = x0.getRotationOzOy(alpha, 0.0);
2019  OVector3D y2 = y0.getRotationOzOy(alpha, 0.0);
2020  x2.normalize();
2021  y2.normalize();
2022  // Final step : New ORepere3D
2023  ORepere3D r = ORepere3D(O, x2, y2, z0);
2024  box.BoxRotationOzOy(alpha, 0.0);
2025  return OBox2(box, r, O);
2026 }
2027 
2028 OBox2 OBox2::rotInXOZOnly(const OVector3D& v1, const OVector3D& v2, const OPoint3D& O, const OPoint3D& P2)
2029 {
2030  OBox2 box = *this;
2031  OVector3D x0 = v1;
2032  // Creates a basis with 3 vectors x0, y0 and z0.
2033  // x0 -> x2, z0 -> z2 and y0 remains the same.
2034  OVector3D y0 = OCoord3D(0.0, 1.0, 0.0);
2035  OVector3D z0 = OCoord3D(0.0, 0.0, 1.0);
2036  double theta = v1.angle(v2);
2037  OVector3D x2 = x0.getRotationOzOy(0.0, theta);
2038  OVector3D z2 = z0.getRotationOzOy(0.0, theta);
2039  x2.normalize();
2040  z2.normalize();
2041  // Final step : New ORepere3D
2042  ORepere3D r = ORepere3D(O, x2, y0, z2);
2043  box._center._x = O._x;
2044  box._center._y = O._y;
2045  box._center._z = O._z;
2046  box.BoxRotationOzOy(0.0, theta);
2047  return OBox2(box, r, O);
2048 }
2049 
2050 OBox2 OBox2::rot3D(const OVector3D& v1, const OVector3D& v2, const OPoint3D& O, const OPoint3D& P2)
2051 {
2052  // 2 steps needed : always a first rotation around Z axis to get Ox
2053  // just "under" v2 and then a rotation around Y depending on the angle.
2054  // Second step : rotate vectors x' and z' around Oy axis : x'' is now
2055  // aligned with vector v2.
2056  // Let's call them x0, x1, and x2.
2057  // Between the two rotations, (x1, y1, z1) have to become a new basis B1.
2058  OBox2 box = *this;
2059  OVector3D x0 = v1;
2060  // First step is to perform a rotation around Oz axis :
2061  // Vectors x and y will change and become x' and y', respectively.
2062  OVector3D y0 = OCoord3D(0.0, 1.0, 0.0);
2063  OVector3D z0 = OCoord3D(0.0, 0.0, 1.0);
2064  // Construction du projete en supposant un sol plat
2065  const OCoord3D proj = OCoord3D(P2._x, P2._y, 0.0);
2066  // Vector from the bb center to proj
2067  OVector3D O2H = OVector3D(O, proj);
2068  double alpha = v1.angle(O2H);
2069  OVector3D x1b0 = x0.getRotationOz(alpha);
2070  OVector3D y1b0 = y0.getRotationOz(alpha);
2071  // This step defines x1, y1 and z1 as a new basis B1.
2072  OVector3D x1b1 = x1b0.getRotationOzBase2(alpha);
2073  OVector3D y1b1 = y1b0.getRotationOzBase2(alpha);
2074  x1b1.normalize();
2075  y1b1.normalize();
2076  // Second step
2077  // Returns the angle necessary to perform the rotation around OY axis
2078  double theta = O2H.angle(v2);
2079  OVector3D x2b1 = x1b1.getRotationOy(theta);
2080  OVector3D z2b1 = z0.getRotationOy(theta);
2081  // x2 , y2 and z2 in B0
2082  OVector3D x2b0 = x0.getRotationOzOy(alpha, theta);
2083  OVector3D z2b0 = z0.getRotationOzOy(0.0, theta);
2084  // Final step : New ORepere3D
2085  ORepere3D r = ORepere3D(O, x2b0, y1b0, z2b0);
2086  box.BoxRotationOzOy(alpha, theta);
2087  return OBox2(box, r, O);
2088 }
2089 
2090 void OBox2::moveAndRotate(const OPoint3D& origin, const OVector3D& vec)
2091 {
2092  _center = origin;
2093  _repere = ORepere3D(origin, vec);
2094  OMatrix mat = _repere.asMatrix();
2095  _A = mat * _A;
2096  _B = mat * _B;
2097  _C = mat * _C;
2098  _D = mat * _D;
2099  _E = mat * _E;
2100  _F = mat * _F;
2101  _G = mat * _G;
2102  _H = mat * _H;
2103 }
2104 
2105 /* OHPlane3D ******************************************************************/
2106 
2108 
2110 {
2111  _N = Plane._N;
2112  _O = Plane._O;
2113  _p = Plane._p;
2114 }
2115 
2116 OHPlane3D::OHPlane3D(const OVector3D& normal, const OPoint3D& origin)
2117 {
2118  _N = normal;
2119  _O = origin;
2120  _p = -DOT(_N, _O);
2121 }
2122 
2124 
2125 void OHPlane3D::set(const OVector3D& normal, const OPoint3D& origin)
2126 {
2127  _N = normal;
2128  _O = origin;
2129  _p = -DOT(_N, _O);
2130 }
2131 
2133 {
2134  _N = Plane._N;
2135  _O = Plane._O;
2136  _p = Plane._p;
2137  return *this;
2138 }
2139 
2140 bool OHPlane3D::operator==(const OHPlane3D& Plane) const
2141 {
2142  bool res = true;
2143  res = res && (_N == Plane._N);
2144  res = res && (_p == Plane._p);
2145  return res;
2146 }
2147 
2148 bool OHPlane3D::operator!=(const OHPlane3D& Plane) const
2149 {
2150  return !operator==(Plane);
2151 }
2152 
2153 int OHPlane3D::intersects(const OSegment3D& seg, OPoint3D& ptIntersec) const
2154 {
2155  double t = NAN;
2156  return intersects(seg._ptA, seg._ptB, ptIntersec, t);
2157 }
2158 
2167 int OHPlane3D::intersects(const OPoint3D& pt1, const OPoint3D& pt2, OPoint3D& ptIntersec, double& t) const
2168 {
2169  OVector3D u(pt1, pt2);
2170  OVector3D w(_O, pt1);
2171  double D = DOT(_N, u);
2172  double N = -DOT(_N, w);
2173  if (ABS(D) < EPSILON_13) // segment is parallel to plane
2174  {
2175  if (ABS(N) < EPSILON_13) // segment lies in plane
2176  {
2177  return 2;
2178  }
2179  else
2180  {
2181  return 0; // no intersection
2182  }
2183  }
2184  // they are not parallel
2185  // compute intersect param
2186  double sI = N / D;
2187  if ((sI < 0.0f) || (sI > 1.0f))
2188  {
2189  return 0; // no intersection
2190  }
2191  ptIntersec = OVector3D(pt1) + sI * u; // compute segment intersect point
2192  t = sI;
2193  return 1;
2194 }
#define minP(A, B, C)
Definition: 3d.cpp:23
::std::ostream & operator<<(::std::ostream &os, const OCoord3D &c)
Definition: 3d.cpp:106
OVector3D operator*(const double a, const OVector3D &vector)
Definition: 3d.cpp:187
#define coeff_ang(PA, PB)
Definition: 3d.cpp:24
#define MAX(A, B)
Definition: 3d.cpp:21
#define MIN(A, B)
Definition: 3d.cpp:22
#define DOT(u, v)
Definition: 3d.cpp:25
All base classes related to 3D manipulation.
#define EPSILON_6
Definition: 3d.h:39
double BORNE(double a, double b, double c)
Limit a number.
Definition: 3d.h:205
#define EPSILON_50
Definition: 3d.h:42
#define M_2PI
2Pi.
Definition: 3d.h:55
#define INTERS_OUI
The intersection exists.
Definition: 3d.h:33
#define EPSILON_13
Definition: 3d.h:41
double SIGNE(double a)
Return the number sign.
Definition: 3d.h:78
double ABS(double a)
Return the absolute value.
Definition: 3d.h:67
#define EPSILON_5
Definition: 3d.h:38
std::vector< OPoint3D > TabPoint3D
Definition: 3d.h:483
#define INTERS_NULLE
No intersection.
Definition: 3d.h:35
NxReal c
Definition: NxVec3.cpp:317
#define min(a, b)
Class to define a box (not necessary parallel to the axis as OBox)
Definition: 3d.h:1380
virtual bool operator==(const OBox2 &box) const
Definition: 3d.cpp:1791
OPoint3D _H
Definition: 3d.h:1492
ORepere3D _repere
Definition: 3d.h:1483
double _width
Definition: 3d.h:1495
OPoint3D _D
Definition: 3d.h:1488
virtual bool isInside(const OPoint3D &pt) const
Test whether the point is inside the box or not.
Definition: 3d.cpp:1887
OBox2 rotInXOZOnly(const OVector3D &v1, const OVector3D &v2, const OPoint3D &O, const OPoint3D &P2)
Definition: 3d.cpp:2028
OPoint3D _E
Definition: 3d.h:1489
double _length
Definition: 3d.h:1493
OBox2()
Default constructor.
Definition: 3d.cpp:1700
OPoint3D _center
Definition: 3d.h:1484
virtual bool isInside2D(const OPoint3D &pt) const
Test whether the point is inside the box or not (from upper point of view).
Definition: 3d.cpp:1900
OPoint3D BoxCoord(int N) const
Returns the coordinates of one of the box corner. \ We consider that the first corner is the one on t...
Definition: 3d.cpp:1859
double _height
Definition: 3d.h:1494
OPoint3D _C
Definition: 3d.h:1487
OBox2 boxRotation(const OPoint3D &O, const OPoint3D &P2)
Definition: 3d.cpp:1927
OPoint3D _G
Definition: 3d.h:1491
OPoint3D _F
Definition: 3d.h:1490
OBox2 rot3D(const OVector3D &v1, const OVector3D &v2, const OPoint3D &O, const OPoint3D &P2)
Definition: 3d.cpp:2050
virtual OBox2 & operator=(const OBox2 &box)
Definition: 3d.cpp:1769
virtual void Translate(const OVector3D &vect)
Translate this box.
Definition: 3d.cpp:1914
void moveAndRotate(const OPoint3D &origin, const OVector3D &vec)
Move and rotate the box.
Definition: 3d.cpp:2090
OBox2 rotInXOYOnly(const OVector3D &v1, const OVector3D &v2, const OPoint3D &O, const OPoint3D &P2)
Definition: 3d.cpp:2009
OPoint3D _B
Definition: 3d.h:1486
void BoxRotationOzOy(double alpha, double theta)
Computes the box rotation around Oz and Oy (usual coordinates system).
Definition: 3d.cpp:1976
OPoint3D _A
Definition: 3d.h:1485
The box class.
Definition: 3d.h:1294
virtual bool isInContact(const OBox &box) const
Test whether the boxes are in contact or not.
Definition: 3d.cpp:1585
virtual bool isInside2D(const OPoint3D &pt) const
Test whether the point is inside the box or not (from upper point of view).
Definition: 3d.cpp:1564
virtual bool isInside(const OPoint3D &pt) const
Test whether the point is inside the box or not.
Definition: 3d.cpp:1535
virtual void Enlarge(const OPoint3D &pt)
Enlarge the box with the point if the point is outside the box.
Definition: 3d.cpp:1614
OPoint3D _min
Minimal coordinates of the OBox.
Definition: 3d.h:1371
virtual bool operator==(const OBox &box) const
Definition: 3d.cpp:1519
OPoint3D _max
Maximal coordinates of the OBox.
Definition: 3d.h:1372
virtual void Translate(const OPoint3D &vectorTranslate)
Translate this box.
Definition: 3d.cpp:1688
OBox()
Default constructor.
Definition: 3d.cpp:1486
virtual OBox & operator=(const OBox &box)
Definition: 3d.cpp:1509
The 3D coordinate class.
Definition: 3d.h:226
double _y
y coordinate of OCoord3D
Definition: 3d.h:283
OCoord3D & operator=(const OCoord3D &coord)
operator=
Definition: 3d.cpp:40
OCoord3D()
Default constructor.
Definition: 3d.cpp:29
double _z
z coordinate of OCoord3D
Definition: 3d.h:284
double _x
x coordinate of OCoord3D
Definition: 3d.h:282
bool operator==(const OCoord3D &coord) const
operator==
Definition: 3d.cpp:51
void setCoords(double x, double y, double z)
Sets the coordinates as an array of double.
Definition: 3d.cpp:76
bool operator!=(const OCoord3D &coord) const
operator!=
Definition: 3d.cpp:71
double * getCoords()
Gets the coordinates as an array of double.
Definition: 3d.cpp:97
virtual ~OCoord3D()
Destructor.
Definition: 3d.cpp:38
static void boundingBox(OPoint3D *pts, int nbPts, OPoint3D &ptMin, OPoint3D &ptMax)
Computes the simple bounding box for a volume using min-max method.
Definition: 3d.cpp:1109
static bool intersDemiSegmentAvecSegment(const OPoint3D &ptS, const OPoint3D &ptA, const OPoint3D &ptB)
Return true if the horizontal from the ptS point intersects the segment defined by ptA and ptB.
Definition: 3d.cpp:915
static void computeNormal(OPoint3D *pts, int nbPts, OVector3D &normal)
Computes the normal of the list of points.
Definition: 3d.cpp:1147
static bool shortestSegBetween2Lines(const OPoint3D &pt1, const OPoint3D &pt2, const OPoint3D &pt3, const OPoint3D &pt4, OPoint3D &ptA, OPoint3D &ptB, double *mua, double *mub)
Calculates the line segment PaPb that is the shortest route between two lines P1P2 and P3P4.
Definition: 3d.cpp:1063
static double symPointDroite(const OPoint3D &ptA, const OPoint3D &ptB, const OPoint3D &ptP, OPoint3D &ptI)
Calculate the symmetrical of a point with respect to a line (defined by two points).
Definition: 3d.cpp:987
static bool pointInPolygonAngleSum(const OPoint3D &ptP, const OPoint3D *pts, int nbPts)
Tests if a point is inside a polygon using angle sum algorithm.
Definition: 3d.cpp:1016
static bool pointInPolygonRayCasting(const OPoint3D &ptP, const OPoint3D *pts, int nbPts)
Tests if a point is inside a polygon using ray casting algorithm.
Definition: 3d.cpp:1046
static int intersDroitesPointVecteur(const OPoint3D &ptA, const OVector3D &vecA, const OPoint3D &ptB, const OVector3D &vecB, OPoint3D &ptI)
Calculate the intersection between two lines each defined by a point and a vector.
Definition: 3d.cpp:977
static int intersDroitesPoints(const OPoint3D &ptA, const OPoint3D &ptB, const OPoint3D &ptC, const OPoint3D &ptD, OPoint3D &ptI)
Calculate the intersection between two lines each defined by two points.
Definition: 3d.cpp:938
The 3D Plane class using Hessian normal form.
Definition: 3d.h:1514
bool operator!=(const OHPlane3D &Plane) const
Definition: 3d.cpp:2148
bool operator==(const OHPlane3D &Plane) const
Definition: 3d.cpp:2140
double _p
Definition: 3d.h:1582
int intersects(const OPoint3D &pt1, const OPoint3D &pt2, OPoint3D &ptIntersec, double &t) const
Calculate the intersection with a segment defined by two points.
Definition: 3d.cpp:2167
OHPlane3D & operator=(const OHPlane3D &Plane)
Definition: 3d.cpp:2132
virtual ~OHPlane3D()
Destructor.
Definition: 3d.cpp:2123
void set(const OVector3D &normal, const OPoint3D &origin)
set a new Plane.
Definition: 3d.cpp:2125
OVector3D _N
Definition: 3d.h:1580
OHPlane3D()
Default constructor.
Definition: 3d.cpp:2107
OPoint3D _O
Definition: 3d.h:1581
The 4x4 matrix class.
Definition: 3d.h:625
virtual ~OMatrix()
Destructor.
Definition: 3d.cpp:461
OCoord3D scale(const OCoord3D &coord) const
Definition: 3d.cpp:554
static double mat3x3Det(double a1, double a2, double a3, double b1, double b2, double b3, double c1, double c2, double c3)
Compute a 3 x 3 matrix determinant.
Definition: 3d.cpp:906
int setRotationOz(double a)
Update a rotation matrix (Oz axis).
Definition: 3d.cpp:688
int setRotationOy(double a)
Update a rotation matrix (Oy axis).
Definition: 3d.cpp:676
int invert()
Matrix inversion.
Definition: 3d.cpp:792
void reset()
Set the matrix elements to zero.
Definition: 3d.cpp:622
OMatrix getInvert(int *ok=0) const
Return the inverse matrix of this matrix.
Definition: 3d.cpp:813
static double mat2x2Det(double a, double b, double c, double d)
Compute a 2 x 2 matrix determinant.
Definition: 3d.cpp:901
void unite()
Initialize the matrix to the identity matrix.
Definition: 3d.cpp:634
OMatrix operator*(const OMatrix &matrix) const
Definition: 3d.cpp:527
OVector3D multNormal(const OVector3D &normal) const
Multiplication with a normal (the translation is removed).
Definition: 3d.cpp:585
int aligneVecteurSurOx(const OVector3D &vector)
Mise a jour d'une matrice d'alignement d'un vecteur quelconque avec l'axe des x.
Definition: 3d.cpp:700
OMatrix & operator=(const OMatrix &matrix)
operators
Definition: 3d.cpp:463
OMatrix operator-(const OMatrix &matrix) const
Definition: 3d.cpp:514
OMatrix()
Default constructor.
Definition: 3d.cpp:439
int setRotationOx(double a)
Update a rotation matrix (Ox axis).
Definition: 3d.cpp:664
bool operator==(const OMatrix &matrix) const
Definition: 3d.cpp:478
OMatrix operator+(const OMatrix &matrix) const
Definition: 3d.cpp:501
void adjoint()
Calculate the adjoint matrix from this matrix.
Definition: 3d.cpp:824
bool operator!=(const OMatrix &matrix) const
Definition: 3d.cpp:496
void show()
Print a matrix (debug).
Definition: 3d.cpp:609
int setTranslation(double x, double y, double z)
Update a translation matrix.
Definition: 3d.cpp:646
OMatrix getAdjoint()
Return the adjoint matrix.
Definition: 3d.cpp:865
double determinant()
Compute the matrix determinant.
Definition: 3d.cpp:873
int aligneVecteurSurOy(const OVector3D &vector)
Mise a jour d'une matrice d'alignement d'un vecteur quelconque avec l'axe des y.
Definition: 3d.cpp:743
OCoord3D dot(const OCoord3D &coord) const
Multiplication with a 3D coordinate.
Definition: 3d.cpp:545
int setScale(double x, double y, double z)
Update a zoom matrix.
Definition: 3d.cpp:655
double _m[4][4]
The 4x4 matrix array.
Definition: 3d.h:922
The 3D point class.
Definition: 3d.h:487
virtual ~OPoint3D()
Destructor.
Definition: 3d.cpp:338
virtual void set(double x, double y, double z)
Definition: 3d.cpp:381
double dist2DFrom(const OPoint3D &pt) const
Computes the distance from this point to another in 2D plan.
Definition: 3d.cpp:376
double distFrom(const OPoint3D &pt) const
Computes the distance from this point to another.
Definition: 3d.cpp:371
OPoint3D()
Default constructor.
Definition: 3d.cpp:328
virtual void getToOGL(double &x, double &y, double &z)
Definition: 3d.cpp:359
virtual void setFromOGL(double x, double y, double z)
Definition: 3d.cpp:340
static TabPoint3D checkPointsMaxDistance(const TabPoint3D &points, const double &distanceMax)
Definition: 3d.cpp:386
3D frame with a point and 3 vectors.
Definition: 3d.h:1211
void normalize()
Normalize each vectors composing this frame.
Definition: 3d.cpp:1455
OVector3D _vecK
Vector K for the Z axis.
Definition: 3d.h:1285
bool operator==(const ORepere3D &repere) const
operator==
Definition: 3d.cpp:1398
OVector3D _vecJ
Vector J for the Y axis.
Definition: 3d.h:1283
ORepere3D & operator=(const ORepere3D &repere)
operator=
Definition: 3d.cpp:1386
void set(const OPoint3D &origin, const OVector3D &vecI, const OVector3D &vecJ, const OVector3D &vecK)
Sets with a point and 3 vectors.
Definition: 3d.cpp:1427
OVector3D _vecI
Vector I for the X axis.
Definition: 3d.h:1281
OPoint3D _origin
The origin point.
Definition: 3d.h:1279
ORepere3D()
Default constructor.
Definition: 3d.cpp:1347
OMatrix asMatrix() const
return the transformation matrix from unity to this pose such as this = transform * unity
Definition: 3d.cpp:1462
bool operator!=(const ORepere3D &repere) const
operator!=
Definition: 3d.cpp:1422
virtual ~ORepere3D()
Destructor.
Definition: 3d.cpp:1384
Class to define a segment.
Definition: 3d.h:1089
virtual double longueur() const
Return the segment length.
Definition: 3d.cpp:1238
virtual OPoint3D centreOf() const
Return the position of the segment middle.
Definition: 3d.cpp:1294
virtual ~OSegment3D()
Destructor.
Definition: 3d.cpp:1200
virtual OPoint3D centerOfCurvedPath(const double &R) const
Return the position of the arc circle center of radius R passing by the segment extremities.
Definition: 3d.cpp:1303
OSegment3D()
Default constructor.
Definition: 3d.cpp:1179
virtual int symetrieOf(const OPoint3D &pt, OPoint3D &ptSym) const
Return the symmetrical of a point.
Definition: 3d.cpp:1243
virtual double lengthOfCurvedPath(const double &R)
Calculate the path length of radius R passing by the segment extremities.
Definition: 3d.cpp:1327
OPoint3D _ptA
Point A of the segment.
Definition: 3d.h:1201
virtual bool operator!=(const OSegment3D &other) const
operator!=
Definition: 3d.cpp:1228
virtual int projection(const OPoint3D &pt, OPoint3D &ptProj, double seuilConfondus) const
Return the projection of a point.
Definition: 3d.cpp:1258
virtual int intersects(const OSegment3D &seg, OPoint3D &pt, double seuilConfondus) const
Return the intersection point with another segment.
Definition: 3d.cpp:1267
virtual OSegment3D swap() const
Return the segment.
Definition: 3d.cpp:1336
virtual OSegment3D operator*(const OMatrix &matrix) const
Multiplication with a matrix.
Definition: 3d.cpp:1233
virtual bool operator==(const OSegment3D &other) const
operator==
Definition: 3d.cpp:1212
virtual OSegment3D & operator=(const OSegment3D &other)
operator=
Definition: 3d.cpp:1202
OPoint3D _ptB
Point B of the segment.
Definition: 3d.h:1203
The 3D vector class.
Definition: 3d.h:298
OVector3D operator*(const OVector3D &vector) const
Definition: 3d.cpp:171
double norme() const
Computes the length of this vector.
Definition: 3d.cpp:215
OVector3D getRotationOzBase2(double alpha)
Returns the vector after a rotation around z axis \ and gives back the coordinates of xprime or yprim...
Definition: 3d.cpp:280
void invert()
Inverts this vector.
Definition: 3d.cpp:236
OVector3D normal(const OVector3D &vector2, const OVector3D &vector3) const
Computes the normal with this vector and 2 others.
Definition: 3d.cpp:220
void balance(double c1, const OVector3D &vector2, double c2)
Balances this vector.
Definition: 3d.cpp:205
virtual ~OVector3D()
Destructor.
Definition: 3d.cpp:128
OVector3D operator-(const OVector3D &vector) const
Definition: 3d.cpp:162
OVector3D getRotationOzOy(double alpha, double theta)
Returns the vector after 2 rotations around z axis and y axis. It gives the coordinates of xsecond,...
Definition: 3d.cpp:306
bool operator!=(const OVector3D &vector) const
Definition: 3d.cpp:148
bool operator==(const OVector3D &vector) const
Definition: 3d.cpp:143
void normalize()
Normalizes this vector.
Definition: 3d.cpp:225
double scalar(const OVector3D &vector) const
Performs the scalar product between this object and another vector.
Definition: 3d.cpp:210
OVector3D cross(const OVector3D &vector) const
Cross product.
Definition: 3d.cpp:196
double angle(const OVector3D &vector) const
Computes the angle between this vector and another vector.
Definition: 3d.cpp:243
OVector3D()
Default constructor.
Definition: 3d.cpp:113
OVector3D operator+(const OVector3D &vector) const
Definition: 3d.cpp:153
OVector3D getRotationOz(double alpha)
Returns the vector after a rotation around z axis \ x -> xprime. Both of these vectors will be given ...
Definition: 3d.cpp:254
OVector3D & operator=(const OVector3D &vector)
operators
Definition: 3d.cpp:137
OVector3D getRotationOyBase2(double alpha)
Returns the vector after a rotation around y axis \ and gives back the coordinates of xprime or zprim...
Definition: 3d.cpp:293
OVector3D getRotationOy(double alpha)
Returns the vector after a rotation around z axis.
Definition: 3d.cpp:267
void reset()
Reset this vector.
Definition: 3d.cpp:130