00001
00002
00003
00004
00005
00006
00007 #ifndef BALL_MATHS_ANALYTICALGEOMETRY_H
00008 #define BALL_MATHS_ANALYTICALGEOMETRY_H
00009
00010 #ifndef BALL_COMMON_EXCEPTION_H
00011 # include <BALL/COMMON/exception.h>
00012 #endif
00013
00014 #ifndef BALL_MATHS_ANGLE_H
00015 # include <BALL/MATHS/angle.h>
00016 #endif
00017
00018 #ifndef BALL_MATHS_CIRCLE3_H
00019 # include <BALL/MATHS/circle3.h>
00020 #endif
00021
00022 #ifndef BALL_MATHS_LINE3_H
00023 # include <BALL/MATHS/line3.h>
00024 #endif
00025
00026 #ifndef BALL_MATHS_PLANE3_H
00027 # include <BALL/MATHS/plane3.h>
00028 #endif
00029
00030 #ifndef BALL_MATHS_SPHERE3_H
00031 # include <BALL/MATHS/sphere3.h>
00032 #endif
00033
00034 #ifndef BALL_MATHS_VECTOR3_H
00035 # include <BALL/MATHS/vector3.h>
00036 #endif
00037
00038 #define BALL_MATRIX_CELL(m, dim, row, col) *((m) + (row) * (dim) + (col))
00039 #define BALL_CELL(x, y) *((m) + (y) * (dim) + (x))
00040
00041 namespace BALL
00042 {
00043
00050
00057 template <typename T>
00058 BALL_INLINE
00059 T getDeterminant_(const T* m, Size dim)
00060 {
00061 T determinant = 0;
00062 Index dim1 = dim - 1;
00063
00064 if (dim > 1)
00065 {
00066 T* submatrix = new T[dim1 * dim1];
00067
00068 for (Index i = 0; i < (Index)dim; ++i)
00069 {
00070 for (Index j = 0; j < dim1; ++j)
00071 {
00072 for (Index k = 0; k < dim1; ++k)
00073 {
00074 *(submatrix + j * dim1 + k) = *(m + (j + 1) * dim + (k < i ? k : k + 1));
00075 }
00076 }
00077 determinant += *(m + i) * (i / 2.0 == i / 2 ? 1 : -1) * getDeterminant_(submatrix, dim1);
00078 }
00079
00080 delete [] submatrix;
00081 }
00082 else
00083 {
00084 determinant = *m;
00085 }
00086
00087 return determinant;
00088 }
00089
00094 template <typename T>
00095 T getDeterminant(const T* m, Size dim)
00096 {
00097 if (dim == 2)
00098 {
00099 return (BALL_CELL(0,0) * BALL_CELL(1,1) - BALL_CELL(0,1) * BALL_CELL(1,0));
00100 }
00101 else if (dim == 3)
00102 {
00103 return ( BALL_CELL(0,0) * BALL_CELL(1,1) * BALL_CELL(2,2)
00104 + BALL_CELL(0,1) * BALL_CELL(1,2) * BALL_CELL(2,0)
00105 + BALL_CELL(0,2) * BALL_CELL(1,0) * BALL_CELL(2,1)
00106 - BALL_CELL(0,2) * BALL_CELL(1,1) * BALL_CELL(2,0)
00107 - BALL_CELL(0,0) * BALL_CELL(1,2) * BALL_CELL(2,1)
00108 - BALL_CELL(0,1) * BALL_CELL(1,0) * BALL_CELL(2,2));
00109 }
00110 else
00111 {
00112 return getDeterminant_(m, dim);
00113 }
00114 }
00115
00119 template <typename T>
00120 BALL_INLINE
00121 T getDeterminant2(const T* m)
00122 {
00123 Size dim = 2;
00124 return (BALL_CELL(0,0) * BALL_CELL(1,1) - BALL_CELL(0,1) * BALL_CELL(1,0));
00125 }
00126
00133 template <typename T>
00134 BALL_INLINE
00135 T getDeterminant2(const T& m00, const T& m01, const T& m10, const T& m11)
00136 {
00137 return (m00 * m11 - m01 * m10);
00138 }
00139
00143 template <typename T>
00144 BALL_INLINE
00145 T getDeterminant3(const T *m)
00146 {
00147 Size dim = 3;
00148 return ( BALL_CELL(0,0) * BALL_CELL(1,1) * BALL_CELL(2,2)
00149 + BALL_CELL(0,1) * BALL_CELL(1,2) * BALL_CELL(2,0)
00150 + BALL_CELL(0,2) * BALL_CELL(1,0) * BALL_CELL(2,1)
00151 - BALL_CELL(0,2) * BALL_CELL(1,1) * BALL_CELL(2,0)
00152 - BALL_CELL(0,0) * BALL_CELL(1,2) * BALL_CELL(2,1)
00153 - BALL_CELL(0,1) * BALL_CELL(1,0) * BALL_CELL(2,2));
00154 }
00155
00159 template <typename T>
00160 BALL_INLINE T
00161 getDeterminant3(const T& m00, const T& m01, const T& m02, const T& m10, const T& m11, const T& m12, const T& m20, const T& m21, const T& m22)
00162 {
00163 return ( m00 * m11 * m22 + m01 * m12 * m20 + m02 * m10 * m21 - m02 * m11 * m20 - m00 * m12 * m21 - m01 * m10 * m22);
00164 }
00165
00192 template <typename T>
00193 bool SolveSystem(const T* m, T* x, const Size dim)
00194 {
00195 T pivot;
00196 Index i, j, k, p;
00197
00198 const Size col_dim = dim + 1;
00199 T* matrix = new T[dim * (dim + 1)];
00200 const T* source = m;
00201 T* target = (T*)matrix;
00202 T* end = (T*)&BALL_MATRIX_CELL(matrix, col_dim, dim - 1, dim);
00203
00204 while (target <= end)
00205 {
00206 *target++ = *source++;
00207 }
00208
00209 for (i = 0; i < (Index)dim; ++i)
00210 {
00211 pivot = BALL_MATRIX_CELL(matrix, col_dim, i, i);
00212 p = i;
00213 for (j = i + 1; j < (Index)dim; ++j)
00214 {
00215 if (Maths::isLess(pivot, BALL_MATRIX_CELL(matrix, col_dim, j, i)))
00216 {
00217 pivot = BALL_MATRIX_CELL(matrix, col_dim, j, i);
00218 p = j;
00219 }
00220 }
00221
00222 if (p != i)
00223 {
00224 T tmp;
00225
00226 for (k = i; k < (Index)dim + 1; ++k)
00227 {
00228 tmp = BALL_MATRIX_CELL(matrix, dim, i, k);
00229 BALL_MATRIX_CELL(matrix, col_dim, i, k) = BALL_MATRIX_CELL(matrix, col_dim, p, k);
00230 BALL_MATRIX_CELL(matrix, col_dim, p, k) = tmp;
00231 }
00232 }
00233 else if (Maths::isZero(pivot) || Maths::isNan(pivot))
00234 {
00235
00236 delete [] matrix;
00237
00238 return false;
00239 }
00240
00241 for (j = dim; j >= i; --j)
00242 {
00243 BALL_MATRIX_CELL(matrix, col_dim, i, j) /= pivot;
00244 }
00245
00246 for (j = i + 1; j < (Index)dim; ++j)
00247 {
00248 pivot = BALL_MATRIX_CELL(matrix, col_dim, j, i);
00249
00250 for (k = dim; k>= i; --k)
00251 {
00252 BALL_MATRIX_CELL(matrix, col_dim, j, k) -= pivot * BALL_MATRIX_CELL(matrix, col_dim, i, k);
00253 }
00254 }
00255 }
00256
00257 x[dim - 1] = BALL_MATRIX_CELL(matrix, col_dim, dim - 1, dim);
00258
00259 for (i = dim - 2; i >= 0; --i)
00260 {
00261 x[i] = BALL_MATRIX_CELL(matrix, col_dim, i, dim);
00262
00263 for (j = i + 1; j < (Index)dim; ++j)
00264 {
00265 x[i] -= BALL_MATRIX_CELL(matrix, col_dim, i, j) * x[j];
00266 }
00267 }
00268
00269 delete [] matrix;
00270
00271 return true;
00272 }
00273
00274 #undef BALL_CELL
00275 #undef BALL_MATRIX_CELL
00276
00285 template <typename T>
00286 BALL_INLINE
00287 bool SolveSystem2(const T& a1, const T& b1, const T& c1, const T& a2, const T& b2, const T& c2, T& x1, T& x2)
00288 {
00289 T quot = (a1 * b2 - a2 * b1);
00290
00291 if (Maths::isZero(quot))
00292 {
00293 return false;
00294 }
00295
00296 x1 = (c1 * b2 - c2 * b1) / quot;
00297 x2 = (a1 * c2 - a2 * c1) / quot;
00298
00299 return true;
00300 }
00301
00311 template <typename T>
00312 short SolveQuadraticEquation(const T& a, const T& b, const T &c, T &x1, T &x2)
00313 {
00314 if (a == 0)
00315 {
00316 if (b == 0)
00317 {
00318 return 0;
00319 }
00320 x1 = x2 = c / b;
00321 return 1;
00322 }
00323 T discriminant = b * b - 4 * a * c;
00324
00325 if (Maths::isLess(discriminant, 0))
00326 {
00327 return 0;
00328 }
00329
00330 T sqrt_discriminant = sqrt(discriminant);
00331 if (Maths::isZero(sqrt_discriminant))
00332 {
00333 x1 = x2 = -b / (2 * a);
00334
00335 return 1;
00336 }
00337 else
00338 {
00339 x1 = (-b + sqrt_discriminant) / (2 * a);
00340 x2 = (-b - sqrt_discriminant) / (2 * a);
00341
00342 return 2;
00343 }
00344 }
00345
00351 template <typename T>
00352 BALL_INLINE
00353 TVector3<T> GetPartition(const TVector3<T>& a, const TVector3<T>& b)
00354 {
00355 return TVector3<T>((b.x + a.x) / 2, (b.y + a.y) / 2, (b.z + a.z) / 2);
00356 }
00357
00366 template <typename T>
00367 BALL_INLINE
00368 TVector3<T> GetPartition(const TVector3<T>& a, const TVector3<T>& b, const T& r, const T& s)
00369 throw(Exception::DivisionByZero)
00370 {
00371 T sum = r + s;
00372 if (sum == (T)0)
00373 {
00374 throw Exception::DivisionByZero(__FILE__, __LINE__);
00375 }
00376 return TVector3<T>
00377 ((s * a.x + r * b.x) / sum,
00378 (s * a.y + r * b.y) / sum,
00379 (s * a.z + r * b.z) / sum);
00380 }
00381
00387 template <typename T>
00388 BALL_INLINE
00389 T GetDistance(const TVector3<T>& a, const TVector3<T>& b)
00390 {
00391 T dx = a.x - b.x;
00392 T dy = a.y - b.y;
00393 T dz = a.z - b.z;
00394
00395 return sqrt(dx * dx + dy * dy + dz * dz);
00396 }
00397
00403 template <typename T>
00404 BALL_INLINE
00405 T GetDistance(const TLine3<T>& line, const TVector3<T>& point)
00406 throw(Exception::DivisionByZero)
00407 {
00408 if (line.d.getLength() == (T)0)
00409 {
00410 throw Exception::DivisionByZero(__FILE__, __LINE__);
00411 }
00412 return ((line.d % (point - line.p)).getLength() / line.d.getLength());
00413 }
00414
00420 template <typename T>
00421 BALL_INLINE
00422 T GetDistance(const TVector3<T>& point, const TLine3<T>& line)
00423 throw(Exception::DivisionByZero)
00424 {
00425 return GetDistance(line, point);
00426 }
00427
00433 template <typename T>
00434 T GetDistance(const TLine3<T>& a, const TLine3<T>& b)
00435 throw(Exception::DivisionByZero)
00436 {
00437 T cross_product_length = (a.d % b.d).getLength();
00438
00439 if (Maths::isZero(cross_product_length))
00440 {
00441 if (a.d.getLength() == (T)0)
00442 {
00443 throw Exception::DivisionByZero(__FILE__, __LINE__);
00444 }
00445 return ((a.d % (b.p - a.p)).getLength() / a.d.getLength());
00446 }
00447 else
00448 {
00449 T spat_product = TVector3<T>::getTripleProduct(a.d, b.d, b.p - a.p);
00450
00451 if (Maths::isNotZero(spat_product))
00452 {
00453
00454 return (Maths::abs(spat_product) / cross_product_length);
00455 }
00456 else
00457 {
00458
00459 return 0;
00460 }
00461 }
00462 }
00463
00469 template <typename T>
00470 BALL_INLINE
00471 T GetDistance(const TVector3<T>& point, const TPlane3<T>& plane)
00472 throw(Exception::DivisionByZero)
00473 {
00474 T length = plane.n.getLength();
00475
00476 if (length == (T)0)
00477 {
00478 throw Exception::DivisionByZero(__FILE__, __LINE__);
00479 }
00480 return (Maths::abs(plane.n * (point - plane.p)) / length);
00481 }
00482
00488 template <typename T>
00489 BALL_INLINE
00490 T GetDistance(const TPlane3<T>& plane, const TVector3<T>& point)
00491 throw(Exception::DivisionByZero)
00492 {
00493 return GetDistance(point, plane);
00494 }
00495
00501 template <typename T>
00502 BALL_INLINE
00503 T GetDistance(const TLine3<T>& line, const TPlane3<T>& plane)
00504 throw(Exception::DivisionByZero)
00505 {
00506 T length = plane.n.getLength();
00507 if (length == (T)0)
00508 {
00509 throw Exception::DivisionByZero(__FILE__, __LINE__);
00510 }
00511 return (Maths::abs(plane.n * (line.p - plane.p)) / length);
00512 }
00513
00519 template <typename T>
00520 BALL_INLINE
00521 T GetDistance(const TPlane3<T>& plane, const TLine3<T>& line)
00522 throw(Exception::DivisionByZero)
00523 {
00524 return GetDistance(line, plane);
00525 }
00526
00532 template <typename T>
00533 BALL_INLINE
00534 T GetDistance(const TPlane3<T>& a, const TPlane3<T>& b)
00535 throw(Exception::DivisionByZero)
00536 {
00537 T length = a.n.getLength();
00538 if (length == (T)0)
00539 {
00540 throw Exception::DivisionByZero(__FILE__, __LINE__);
00541 }
00542 return (Maths::abs(a.n * (a.p - b.p)) / length);
00543 }
00544
00551 template <typename T>
00552 BALL_INLINE
00553 bool GetAngle(const TVector3<T>& a, const TVector3<T>& b, TAngle<T> &intersection_angle)
00554 {
00555 T length_product = a.getSquareLength() * b.getSquareLength();
00556 if(Maths::isZero(length_product))
00557 {
00558 return false;
00559 }
00560 intersection_angle = a.getAngle(b);
00561 return true;
00562 }
00563
00570 template <typename T>
00571 BALL_INLINE
00572 bool GetAngle(const TLine3<T>& a, const TLine3<T>& b, TAngle<T>& intersection_angle)
00573 {
00574 T length_product = a.d.getSquareLength() * b.d.getSquareLength();
00575
00576 if(Maths::isZero(length_product))
00577 {
00578 return false;
00579 }
00580 intersection_angle = acos(Maths::abs(a.d * b.d) / sqrt(length_product));
00581 return true;
00582 }
00583
00590 template <typename T>
00591 BALL_INLINE
00592 bool GetAngle(const TPlane3<T>& plane, const TVector3<T>& vector, TAngle<T>& intersection_angle)
00593 {
00594 T length_product = plane.n.getSquareLength() * vector.getSquareLength();
00595
00596 if (Maths::isZero(length_product))
00597 {
00598 return false;
00599 }
00600 else
00601 {
00602 intersection_angle = asin(Maths::abs(plane.n * vector) / sqrt(length_product));
00603 return true;
00604 }
00605 }
00606
00613 template <typename T>
00614 BALL_INLINE
00615 bool GetAngle(const TVector3<T>& vector ,const TPlane3<T>& plane, TAngle<T> &intersection_angle)
00616 {
00617 return GetAngle(plane, vector, intersection_angle);
00618 }
00619
00626 template <typename T>
00627 BALL_INLINE
00628 bool GetAngle(const TPlane3<T>& plane,const TLine3<T>& line, TAngle<T>& intersection_angle)
00629 {
00630 T length_product = plane.n.getSquareLength() * line.d.getSquareLength();
00631
00632 if (Maths::isZero(length_product))
00633 {
00634 return false;
00635 }
00636
00637 intersection_angle = asin(Maths::abs(plane.n * line.d) / sqrt(length_product));
00638 return true;
00639 }
00640
00647 template <typename T>
00648 BALL_INLINE
00649 bool GetAngle(const TLine3<T>& line, const TPlane3<T>& plane, TAngle<T>& intersection_angle)
00650 {
00651 return GetAngle(plane, line, intersection_angle);
00652 }
00653
00654
00661 template <typename T>
00662 BALL_INLINE
00663 bool GetAngle(const TPlane3<T>& a, const TPlane3<T>& b, TAngle<T>& intersection_angle)
00664 {
00665 T length_product = a.n.getSquareLength() * b.n.getSquareLength();
00666
00667 if(Maths::isZero(length_product))
00668 {
00669 return false;
00670 }
00671
00672 intersection_angle = acos(Maths::abs(a.n * b.n) / sqrt(length_product));
00673 return true;
00674 }
00675
00682 template <typename T>
00683 bool GetIntersection(const TLine3<T>& a, const TLine3<T>& b, TVector3<T>& point)
00684 {
00685 T c1, c2;
00686 if ((SolveSystem2(a.d.x, -b.d.x, b.p.x - a.p.x, a.d.y, -b.d.y, b.p.y - a.p.y, c1, c2) == true && Maths::isEqual(a.p.z + a.d.z * c1, b.p.z + b.d.z * c2)) || (SolveSystem2(a.d.x, -b.d.x, b.p.x - a.p.x, a.d.z, -b.d.z, b.p.z - a.p.z, c1, c2) == true && Maths::isEqual(a.p.y + a.d.y * c1, b.p.y + b.d.y * c2)) || (SolveSystem2(a.d.y, -b.d.y, b.p.y - a.p.y, a.d.z, -b.d.z, b.p.z - a.p.z, c1, c2) == true && Maths::isEqual(a.p.x + a.d.x * c1, b.p.x + b.d.x * c2)))
00687 {
00688 point.set(a.p.x + a.d.x * c1, a.p.y + a.d.y * c1, a.p.z + a.d.z * c1);
00689 return true;
00690 }
00691
00692 return false;
00693 }
00694
00701 template <typename T>
00702 BALL_INLINE
00703 bool GetIntersection(const TPlane3<T>& plane, const TLine3<T>& line, TVector3<T>& intersection_point)
00704 {
00705 T dot_product = plane.n * line.d;
00706 if (Maths::isZero(dot_product))
00707 {
00708 return false;
00709 }
00710 intersection_point.set(line.p + (plane.n * (plane.p - line.p)) * line.d / dot_product);
00711 return true;
00712 }
00713
00720 template <typename T>
00721 BALL_INLINE
00722 bool GetIntersection(const TLine3<T>& line, const TPlane3<T>& plane, TVector3<T>& intersection_point)
00723 {
00724 return GetIntersection(plane, line, intersection_point);
00725 }
00726
00733 template <typename T>
00734 bool GetIntersection(const TPlane3<T>& plane1, const TPlane3<T>& plane2, TLine3<T>& line)
00735 {
00736 T u = plane1.p*plane1.n;
00737 T v = plane2.p*plane2.n;
00738 T det = plane1.n.x*plane2.n.y-plane1.n.y*plane2.n.x;
00739 if (Maths::isZero(det))
00740 {
00741 det = plane1.n.x*plane2.n.z-plane1.n.z*plane2.n.x;
00742 if (Maths::isZero(det))
00743 {
00744 det = plane1.n.y*plane2.n.z-plane1.n.z*plane2.n.y;
00745 if (Maths::isZero(det))
00746 {
00747 return false;
00748 }
00749 else
00750 {
00751 T a = plane2.n.z/det;
00752 T b = -plane1.n.z/det;
00753 T c = -plane2.n.y/det;
00754 T d = plane1.n.y/det;
00755 line.p.x = 0;
00756 line.p.y = a*u+b*v;
00757 line.p.z = c*u+d*v;
00758 line.d.x = -1;
00759 line.d.y = a*plane1.n.x+b*plane2.n.x;
00760 line.d.z = c*plane1.n.x+d*plane2.n.x;
00761 }
00762 }
00763 else
00764 {
00765 T a = plane2.n.z/det;
00766 T b = -plane1.n.z/det;
00767 T c = -plane2.n.x/det;
00768 T d = plane1.n.x/det;
00769 line.p.x = a*u+b*v;
00770 line.p.y = 0;
00771 line.p.z = c*u+d*v;
00772 line.d.x = a*plane1.n.y+b*plane2.n.y;
00773 line.d.y = -1;
00774 line.d.z = c*plane1.n.y+d*plane2.n.y;
00775 }
00776 }
00777 else
00778 {
00779 T a = plane2.n.y/det;
00780 T b = -plane1.n.y/det;
00781 T c = -plane2.n.x/det;
00782 T d = plane1.n.x/det;
00783 line.p.x = a*u+b*v;
00784 line.p.y = c*u+d*v;
00785 line.p.z = 0;
00786 line.d.x = a*plane1.n.z+b*plane2.n.z;
00787 line.d.y = c*plane1.n.z+d*plane2.n.z;
00788 line.d.z = -1;
00789 }
00790 return true;
00791 }
00792
00800 template <typename T>
00801 bool GetIntersection(const TSphere3<T>& sphere, const TLine3<T>& line, TVector3<T>& intersection_point1, TVector3<T>& intersection_point2)
00802 {
00803 T x1, x2;
00804 short number_of_solutions = SolveQuadraticEquation (line.d * line.d, (line.p - sphere.p) * line.d * 2, (line.p - sphere.p) * (line.p - sphere.p) - sphere.radius * sphere.radius, x1, x2);
00805
00806 if (number_of_solutions == 0)
00807 {
00808 return false;
00809 }
00810
00811 intersection_point1 = line.p + x1 * line.d;
00812 intersection_point2 = line.p + x2 * line.d;
00813
00814 return true;
00815 }
00816
00824 template <typename T>
00825 BALL_INLINE
00826 bool GetIntersection(const TLine3<T>& line, const TSphere3<T>& sphere, TVector3<T>& intersection_point1, TVector3<T>& intersection_point2)
00827 {
00828 return GetIntersection(sphere, line, intersection_point1, intersection_point2);
00829 }
00830
00837 template <typename T>
00838 bool GetIntersection(const TSphere3<T>& sphere, const TPlane3<T>& plane, TCircle3<T>& intersection_circle)
00839 {
00840 T distance = GetDistance(sphere.p, plane);
00841
00842 if (Maths::isGreater(distance, sphere.radius))
00843 {
00844 return false;
00845 }
00846
00847 TVector3<T> Vector3(plane.n);
00848 Vector3.normalize();
00849
00850 if (Maths::isEqual(distance, sphere.radius))
00851 {
00852 intersection_circle.set(sphere.p + sphere.radius * Vector3, plane.n, 0);
00853 }
00854 else
00855 {
00856 intersection_circle.set
00857 (sphere.p + distance * Vector3, plane.n,
00858 sqrt(sphere.radius * sphere.radius - distance * distance));
00859 }
00860
00861 return true;
00862 }
00863
00870 template <typename T>
00871 BALL_INLINE bool
00872 GetIntersection(const TPlane3<T>& plane, const TSphere3<T>& sphere, TCircle3<T>& intersection_circle)
00873 {
00874 return GetIntersection(sphere, plane, intersection_circle);
00875 }
00876
00885 template <typename T>
00886 bool GetIntersection(const TSphere3<T>& a, const TSphere3<T>& b, TCircle3<T>& intersection_circle)
00887 {
00888 TVector3<T> norm = b.p - a.p;
00889 T square_dist = norm * norm;
00890 if (Maths::isZero(square_dist))
00891 {
00892 return false;
00893 }
00894 T dist = sqrt(square_dist);
00895 if (Maths::isLess(a.radius + b.radius, dist))
00896 {
00897 return false;
00898 }
00899 if (Maths::isGreaterOrEqual(Maths::abs(a.radius - b.radius), dist))
00900 {
00901 return false;
00902 }
00903
00904 T radius1_square = a.radius * a.radius;
00905 T radius2_square = b.radius * b.radius;
00906 T u = radius1_square - radius2_square + square_dist;
00907 T length = u / (2 * square_dist);
00908 T square_radius = radius1_square - u * length / 2;
00909 if (square_radius < 0)
00910 {
00911 return false;
00912 }
00913
00914 intersection_circle.p = a.p + (norm * length);
00915 intersection_circle.radius = sqrt(square_radius);
00916 intersection_circle.n = norm / dist;
00917
00918 return true;
00919 }
00920
00930 template <class T>
00931 bool GetIntersection(const TSphere3<T>& s1, const TSphere3<T>& s2, const TSphere3<T>& s3, TVector3<T>& p1, TVector3<T>& p2, bool test = true)
00932 {
00933 T r1_square = s1.radius*s1.radius;
00934 T r2_square = s2.radius*s2.radius;
00935 T r3_square = s3.radius*s3.radius;
00936 T p1_square_length = s1.p*s1.p;
00937 T p2_square_length = s2.p*s2.p;
00938 T p3_square_length = s3.p*s3.p;
00939 T u = (r2_square-r1_square-p2_square_length+p1_square_length)/2;
00940 T v = (r3_square-r1_square-p3_square_length+p1_square_length)/2;
00941 TPlane3<T> plane1;
00942 TPlane3<T> plane2;
00943 try
00944 {
00945 plane1 = TPlane3<T>(s2.p.x-s1.p.x,s2.p.y-s1.p.y,s2.p.z-s1.p.z,u);
00946 plane2 = TPlane3<T>(s3.p.x-s1.p.x,s3.p.y-s1.p.y,s3.p.z-s1.p.z,v);
00947 }
00948 catch (Exception::DivisionByZero&)
00949 {
00950 return false;
00951 }
00952 TLine3<T> line;
00953 if (GetIntersection(plane1,plane2,line))
00954 {
00955 TVector3<T> diff(s1.p-line.p);
00956 T x1, x2;
00957 if (SolveQuadraticEquation(line.d*line.d, -diff*line.d*2, diff*diff-r1_square, x1,x2) > 0)
00958 {
00959 p1 = line.p+x1*line.d;
00960 p2 = line.p+x2*line.d;
00961 if (test)
00962 {
00963 TVector3<T> test = s1.p-p1;
00964 if (Maths::isNotEqual(test*test,r1_square))
00965 {
00966 return false;
00967 }
00968 test = s1.p-p2;
00969 if (Maths::isNotEqual(test*test,r1_square))
00970 {
00971 return false;
00972 }
00973 test = s2.p-p1;
00974 if (Maths::isNotEqual(test*test,r2_square))
00975 {
00976 return false;
00977 }
00978 test = s2.p-p2;
00979 if (Maths::isNotEqual(test*test,r2_square))
00980 {
00981 return false;
00982 }
00983 test = s3.p-p1;
00984 if (Maths::isNotEqual(test*test,r3_square))
00985 {
00986 return false;
00987 }
00988 test = s3.p-p2;
00989 if (Maths::isNotEqual(test*test,r3_square))
00990 {
00991 return false;
00992 }
00993 }
00994 return true;
00995 }
00996 }
00997 return false;
00998 }
00999
01000
01006 template <typename T>
01007 BALL_INLINE
01008 bool isCollinear(const TVector3<T>& a, const TVector3<T>& b)
01009 {
01010 return (a % b).isZero();
01011 }
01012
01019 template <typename T>
01020 BALL_INLINE
01021 bool isComplanar(const TVector3<T>& a, const TVector3<T>& b, const TVector3<T>& c)
01022 {
01023 return Maths::isZero(TVector3<T>::getTripleProduct(a, b, c));
01024 }
01025
01033 template <typename T>
01034 BALL_INLINE
01035 bool isComplanar(const TVector3<T>& a, const TVector3<T>& b, const TVector3<T>& c, const TVector3<T>& d)
01036 {
01037 return isComplanar(a - b, a - c, a - d);
01038 }
01039
01045 template <typename T>
01046 BALL_INLINE
01047 bool isOrthogonal(const TVector3<T>& a, const TVector3<T>& b)
01048 {
01049 return Maths::isZero(a * b);
01050 }
01051
01057 template <typename T>
01058 BALL_INLINE
01059 bool isOrthogonal(const TVector3<T>& vector, const TLine3<T>& line)
01060 {
01061 return Maths::isZero(vector * line.d);
01062 }
01063
01069 template <typename T>
01070 BALL_INLINE
01071 bool isOrthogonal(const TLine3<T>& line, const TVector3<T>& vector)
01072 {
01073 return isOrthogonal(vector, line);
01074 }
01075
01081 template <typename T>
01082 BALL_INLINE
01083 bool isOrthogonal(const TLine3<T>& a, const TLine3<T>& b)
01084 {
01085 return Maths::isZero(a.d * b.d);
01086 }
01087
01093 template <typename T>
01094 BALL_INLINE
01095 bool isOrthogonal(const TVector3<T>& vector, const TPlane3<T>& plane)
01096 {
01097 return isCollinear(vector, plane.n);
01098 }
01099
01105 template <typename T>
01106 BALL_INLINE
01107 bool isOrthogonal(const TPlane3<T>& plane, const TVector3<T>& vector)
01108 {
01109 return isOrthogonal(vector, plane);
01110 }
01111
01117 template <typename T>
01118 BALL_INLINE
01119 bool isOrthogonal(const TPlane3<T>& a, const TPlane3<T>& b)
01120 {
01121 return Maths::isZero(a.n * b.n);
01122 }
01123
01129 template <typename T>
01130 BALL_INLINE
01131 bool isIntersecting(const TVector3<T>& point, const TLine3<T>& line)
01132 {
01133 return Maths::isZero(GetDistance(point, line));
01134 }
01135
01141 template <typename T>
01142 BALL_INLINE
01143 bool isIntersecting(const TLine3<T>& line, const TVector3<T>& point)
01144 {
01145 return isIntersecting(point, line);
01146 }
01147
01153 template <typename T>
01154 BALL_INLINE
01155 bool isIntersecting(const TLine3<T>& a, const TLine3<T>& b)
01156 {
01157 return Maths::isZero(GetDistance(a, b));
01158 }
01159
01165 template <typename T>
01166 BALL_INLINE
01167 bool isIntersecting(const TVector3<T>& point, const TPlane3<T>& plane)
01168 {
01169 return Maths::isZero(GetDistance(point, plane));
01170 }
01171
01177 template <typename T>
01178 BALL_INLINE
01179 bool isIntersecting(const TPlane3<T>& plane, const TVector3<T>& point)
01180 {
01181 return isIntersecting(point, plane);
01182 }
01183
01189 template <typename T>
01190 BALL_INLINE
01191 bool isIntersecting(const TLine3<T>& line, const TPlane3<T>& plane)
01192 {
01193 return Maths::isZero(GetDistance(line, plane));
01194 }
01195
01201 template <typename T>
01202 BALL_INLINE
01203 bool isIntersecting(const TPlane3<T>& plane, const TLine3<T>& line)
01204 {
01205 return isIntersecting(line, plane);
01206 }
01207
01213 template <typename T>
01214 BALL_INLINE
01215 bool isIntersecting(const TPlane3<T>& a, const TPlane3<T>& b)
01216 {
01217 return Maths::isZero(GetDistance(a, b));
01218 }
01219
01225 template <typename T>
01226 BALL_INLINE
01227 bool isParallel(const TLine3<T>& line, const TPlane3<T>& plane)
01228 {
01229 return isOrthogonal(line.d, plane.n);
01230 }
01231
01237 template <typename T>
01238 BALL_INLINE
01239 bool isParallel(const TPlane3<T>& plane, const TLine3<T>& line)
01240 {
01241 return isParallel(line, plane);
01242 }
01243
01249 template <typename T>
01250 BALL_INLINE
01251 bool isParallel(const TPlane3<T>& a, const TPlane3<T>& b)
01252 {
01253 return isCollinear(a.n, b.n);
01254 }
01255
01258 template <typename T>
01259 TAngle<T> getOrientedAngle
01260 (const T& ax, const T& ay, const T& az,
01261 const T& bx, const T& by, const T& bz,
01262 const T& nx, const T& ny, const T& nz)
01263 throw(Exception::DivisionByZero)
01264 {
01265
01266 T bl = (T) sqrt((double)ax * ax + ay * ay + az * az);
01267 T el = (T) sqrt((double)bx * bx + by * by + bz * bz);
01268 T bel = (T) (ax * bx + ay * by + az * bz);
01269
01270
01271 if (bl * el == 0)
01272 {
01273 throw Exception::DivisionByZero(__FILE__, __LINE__);
01274 }
01275 bel /= (bl * el);
01276 if (bel > 1.0)
01277 {
01278 bel = 1;
01279 }
01280 else if (bel < -1.0)
01281 {
01282 bel = -1;
01283 }
01284
01285 T acosbel = (T) acos(bel);
01286
01287 if (( nx * (az * by - ay * bz)
01288 + ny * (ax * bz - az * bx)
01289 + nz * (ay * bx - ax * by)) > 0)
01290 {
01291 acosbel = Constants::PI+Constants::PI-acosbel;
01292 }
01293
01294 return TAngle<T>(acosbel);
01295 }
01296
01299 template <typename T>
01300 BALL_INLINE
01301 TAngle<T>getOrientedAngle(const TVector3<T>& a, const TVector3<T>& b, const TVector3<T>& normal)
01302 throw(Exception::DivisionByZero)
01303 {
01304 return getOrientedAngle(a.x, a.y, a.z, b.x, b.y, b.z, normal.x, normal.y, normal.z);
01305 }
01306
01322 template <typename T>
01323 TAngle<T> getTorsionAngle
01324 (const T& ax, const T& ay, const T& az,
01325 const T& bx, const T& by, const T& bz,
01326 const T& cx, const T& cy, const T& cz,
01327 const T& dx, const T& dy, const T& dz)
01328 throw(Exception::DivisionByZero)
01329 {
01330 T abx = ax - bx;
01331 T aby = ay - by;
01332 T abz = az - bz;
01333
01334 T cbx = cx - bx;
01335 T cby = cy - by;
01336 T cbz = cz - bz;
01337
01338 T cdx = cx - dx;
01339 T cdy = cy - dy;
01340 T cdz = cz - dz;
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353 T ndax = aby * cbz - abz * cby;
01354 T nday = abz * cbx - abx * cbz;
01355 T ndaz = abx * cby - aby * cbx;
01356
01357
01358 T neax = cbz * cdy - cby * cdz;
01359 T neay = cbx * cdz - cbz * cdx;
01360 T neaz = cby * cdx - cbx * cdy;
01361
01362
01363 T bl = (T) sqrt((double)ndax * ndax + nday * nday + ndaz * ndaz);
01364 T el = (T) sqrt((double)neax * neax + neay * neay + neaz * neaz);
01365 T bel = (T) (ndax * neax + nday * neay + ndaz * neaz);
01366
01367
01368 if (bl * el == 0)
01369 {
01370 throw Exception::DivisionByZero(__FILE__, __LINE__);
01371 }
01372 bel /= (bl * el);
01373 if (bel > 1.0)
01374 {
01375 bel = 1;
01376 }
01377 else if (bel < -1.0)
01378 {
01379 bel = -1;
01380 }
01381
01382 T acosbel = (T) acos(bel);
01383
01384 if ((cbx * (ndaz * neay - nday * neaz)
01385 + cby * (ndax * neaz - ndaz * neax)
01386 + cbz * (nday * neax - ndax * neay))
01387 < 0)
01388 {
01389 acosbel = -acosbel;
01390 }
01391
01392 acosbel = (acosbel > 0.0)
01393 ? Constants::PI - acosbel
01394 : -(Constants::PI + acosbel);
01395
01396 return TAngle<T>(acosbel);
01397 }
01399 }
01400
01401
01402 #endif // BALL_MATHS_ANALYTICALGEOMETRY_H