00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #define GEO_ALGORITHMS_C
00053
00054
00055
00056 #include "Algorithms.hh"
00057 #include "../Utils/NumLimitsT.hh"
00058 #include <math.h>
00059
00060 #ifdef max
00061 # undef max
00062 #endif
00063
00064 #ifdef min
00065 # undef min
00066 #endif
00067
00068
00069
00070
00071
00072 namespace ACG {
00073 namespace Geometry {
00074
00075
00076
00077
00078
00079
00080
00081
00082 template<typename Scalar>
00083 bool
00084 baryCoord( const VectorT<Scalar,3> & _p,
00085 const VectorT<Scalar,3> & _u,
00086 const VectorT<Scalar,3> & _v,
00087 const VectorT<Scalar,3> & _w,
00088 VectorT<Scalar,3> & _result )
00089 {
00090 VectorT<Scalar,3> vu = _v - _u,
00091 wu = _w - _u,
00092 pu = _p - _u;
00093
00094
00095
00096 Scalar nx = vu[1]*wu[2] - vu[2]*wu[1],
00097 ny = vu[2]*wu[0] - vu[0]*wu[2],
00098 nz = vu[0]*wu[1] - vu[1]*wu[0],
00099 ax = fabs(nx),
00100 ay = fabs(ny),
00101 az = fabs(nz);
00102
00103
00104 unsigned char max_coord;
00105
00106 if ( ax > ay ) {
00107 if ( ax > az ) {
00108 max_coord = 0;
00109 }
00110 else {
00111 max_coord = 2;
00112 }
00113 }
00114 else {
00115 if ( ay > az ) {
00116 max_coord = 1;
00117 }
00118 else {
00119 max_coord = 2;
00120 }
00121 }
00122
00123
00124
00125 switch (max_coord) {
00126
00127 case 0:
00128 {
00129 if (1.0+ax == 1.0) return false;
00130 _result[1] = 1.0 + (pu[1]*wu[2]-pu[2]*wu[1])/nx - 1.0;
00131 _result[2] = 1.0 + (vu[1]*pu[2]-vu[2]*pu[1])/nx - 1.0;
00132 _result[0] = 1.0 - _result[1] - _result[2];
00133 }
00134 break;
00135
00136 case 1:
00137 {
00138 if (1.0+ay == 1.0) return false;
00139 _result[1] = 1.0 + (pu[2]*wu[0]-pu[0]*wu[2])/ny - 1.0;
00140 _result[2] = 1.0 + (vu[2]*pu[0]-vu[0]*pu[2])/ny - 1.0;
00141 _result[0] = 1.0 - _result[1] - _result[2];
00142 }
00143 break;
00144
00145 case 2:
00146 {
00147 if (1.0+az == 1.0) return false;
00148 _result[1] = 1.0 + (pu[0]*wu[1]-pu[1]*wu[0])/nz - 1.0;
00149 _result[2] = 1.0 + (vu[0]*pu[1]-vu[1]*pu[0])/nz - 1.0;
00150 _result[0] = 1.0 - _result[1] - _result[2];
00151 }
00152 break;
00153 }
00154
00155 return true;
00156 }
00157
00158
00159
00160
00161
00162 template <class Vec>
00163 typename Vec::value_type
00164 triangleAreaSquared( const Vec& _v0,
00165 const Vec& _v1,
00166 const Vec& _v2 )
00167 {
00168 return 0.25 * ((_v1-_v0)%(_v2-_v0)).sqrnorm();
00169 }
00170
00171
00172
00173
00174
00175 template<class Vec>
00176 typename Vec::value_type
00177 distPointLineSquared( const Vec& _p,
00178 const Vec& _v0,
00179 const Vec& _v1,
00180 Vec* _min_v )
00181 {
00182 Vec d1(_p-_v0), d2(_v1-_v0), min_v(_v0);
00183 typename Vec::value_type t = (d1|d2)/(d2|d2);
00184
00185 if (t > 1.0) d1 = _p - (min_v = _v1);
00186 else if (t > 0.0) d1 = _p - (min_v = _v0 + d2*t);
00187
00188 if (_min_v) *_min_v = min_v;
00189 return d1.sqrnorm();
00190 }
00191
00192
00193
00194
00195
00196 template <class Vec>
00197 typename Vec::value_type
00198 distPointTriangleSquared( const Vec& _p,
00199 const Vec& _v0,
00200 const Vec& _v1,
00201 const Vec& _v2,
00202 Vec& _nearestPoint )
00203 {
00204 Vec v0v1 = _v1 - _v0;
00205 Vec v0v2 = _v2 - _v0;
00206 Vec n = v0v1 % v0v2;
00207 double d = n.sqrnorm();
00208
00209
00210
00211 if (d < FLT_MIN && d > -FLT_MIN) {
00212 std::cerr << "distPointTriangleSquared: Degenerated triangle !\n";
00213 return -1.0;
00214 }
00215 double invD = 1.0 / d;
00216
00217
00218
00219
00220 Vec v1v2 = _v2 - _v1;
00221 double inv_v0v2_2 = 1.0 / v0v2.sqrnorm();
00222 double inv_v0v1_2 = 1.0 / v0v1.sqrnorm();
00223 double inv_v1v2_2 = 1.0 / v1v2.sqrnorm();
00224
00225
00226 Vec v0p = _p - _v0;
00227 Vec t = v0p % n;
00228 double s01, s02, s12;
00229 double a = (t | v0v2) * -invD;
00230 double b = (t | v0v1) * invD;
00231
00232
00233 if (a < 0)
00234 {
00235
00236 s02 = ( v0v2 | v0p ) * inv_v0v2_2;
00237 if (s02 < 0.0)
00238 {
00239 s01 = ( v0v1 | v0p ) * inv_v0v1_2;
00240 if (s01 <= 0.0) {
00241 v0p = _v0;
00242 } else if (s01 >= 1.0) {
00243 v0p = _v1;
00244 } else {
00245 v0p = _v0 + v0v1 * s01;
00246 }
00247 } else if (s02 > 1.0) {
00248 s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2;
00249 if (s12 >= 1.0) {
00250 v0p = _v2;
00251 } else if (s12 <= 0.0) {
00252 v0p = _v1;
00253 } else {
00254 v0p = _v1 + v1v2 * s12;
00255 }
00256 } else {
00257 v0p = _v0 + v0v2 * s02;
00258 }
00259 } else if (b < 0.0) {
00260
00261 s01 = ( v0v1 | v0p ) * inv_v0v1_2;
00262 if (s01 < 0.0)
00263 {
00264 s02 = ( v0v2 | v0p ) * inv_v0v2_2;
00265 if (s02 <= 0.0) {
00266 v0p = _v0;
00267 } else if (s02 >= 1.0) {
00268 v0p = _v2;
00269 } else {
00270 v0p = _v0 + v0v2 * s02;
00271 }
00272 } else if (s01 > 1.0) {
00273 s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2;
00274 if (s12 >= 1.0) {
00275 v0p = _v2;
00276 } else if (s12 <= 0.0) {
00277 v0p = _v1;
00278 } else {
00279 v0p = _v1 + v1v2 * s12;
00280 }
00281 } else {
00282 v0p = _v0 + v0v1 * s01;
00283 }
00284 } else if (a+b > 1.0) {
00285
00286 s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2;
00287 if (s12 >= 1.0) {
00288 s02 = ( v0v2 | v0p ) * inv_v0v2_2;
00289 if (s02 <= 0.0) {
00290 v0p = _v0;
00291 } else if (s02 >= 1.0) {
00292 v0p = _v2;
00293 } else {
00294 v0p = _v0 + v0v2*s02;
00295 }
00296 } else if (s12 <= 0.0) {
00297 s01 = ( v0v1 | v0p ) * inv_v0v1_2;
00298 if (s01 <= 0.0) {
00299 v0p = _v0;
00300 } else if (s01 >= 1.0) {
00301 v0p = _v1;
00302 } else {
00303 v0p = _v0 + v0v1 * s01;
00304 }
00305 } else {
00306 v0p = _v1 + v1v2 * s12;
00307 }
00308 } else {
00309
00310 _nearestPoint = _p - n*((n|v0p) * invD);
00311 return (_nearestPoint - _p).sqrnorm();
00312 }
00313
00314 _nearestPoint = v0p;
00315
00316 return (_nearestPoint - _p).sqrnorm();
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 template<typename Scalar>
00328 Scalar
00329 distLineLineSquared( const VectorT<Scalar,3>& _v00,
00330 const VectorT<Scalar,3>& _v01,
00331 const VectorT<Scalar,3>& _v10,
00332 const VectorT<Scalar,3>& _v11,
00333 VectorT<Scalar,3>* _min_v0,
00334 VectorT<Scalar,3>* _min_v1,
00335 bool _fastApprox )
00336 {
00337 VectorT<Scalar,3> kDiff = _v00 - _v10;
00338 VectorT<Scalar,3> d0 = _v01-_v00;
00339 VectorT<Scalar,3> d1 = _v11-_v10;
00340
00341 Scalar fA00 = d0.sqrnorm();
00342 Scalar fA01 = -(d0|d1);
00343 Scalar fA11 = d1.sqrnorm();
00344 Scalar fB0 = (kDiff|d0);
00345 Scalar fC = kDiff.sqrnorm();
00346 Scalar fDet = fabs(fA00*fA11-fA01*fA01);
00347 Scalar fB1, fS, fT, fSqrDist, fTmp;
00348
00349
00350 if ( fDet >= FLT_MIN )
00351 {
00352
00353 fB1 = -(kDiff|d1);
00354 fS = fA01*fB1-fA11*fB0;
00355 fT = fA01*fB0-fA00*fB1;
00356
00357
00358
00359 if (_fastApprox)
00360 {
00361 if ( fS < 0.0 ) fS = 0.0;
00362 else if ( fS > fDet ) fS = fDet;
00363 if ( fT < 0.0 ) fT = 0.0;
00364 else if ( fT > fDet ) fT = fDet;
00365 }
00366
00367
00368 if ( fS >= 0.0 )
00369 {
00370 if ( fS <= fDet )
00371 {
00372 if ( fT >= 0.0 )
00373 {
00374 if ( fT <= fDet )
00375 {
00376
00377 Scalar fInvDet = 1.0/fDet;
00378 fS *= fInvDet;
00379 fT *= fInvDet;
00380 fSqrDist = fS*(fA00*fS+fA01*fT+2.0*fB0) +
00381 fT*(fA01*fS+fA11*fT+2.0*fB1)+fC;
00382 }
00383 else
00384 {
00385 fT = 1.0;
00386 fTmp = fA01+fB0;
00387 if ( fTmp >= 0.0 )
00388 {
00389 fS = 0.0;
00390 fSqrDist = fA11+2.0*fB1+fC;
00391 }
00392 else if ( -fTmp >= fA00 )
00393 {
00394 fS = 1.0;
00395 fSqrDist = fA00+fA11+fC+2.0*(fB1+fTmp);
00396 }
00397 else
00398 {
00399 fS = -fTmp/fA00;
00400 fSqrDist = fTmp*fS+fA11+2.0*fB1+fC;
00401 }
00402 }
00403 }
00404 else
00405 {
00406 fT = 0.0;
00407 if ( fB0 >= 0.0 )
00408 {
00409 fS = 0.0;
00410 fSqrDist = fC;
00411 }
00412 else if ( -fB0 >= fA00 )
00413 {
00414 fS = 1.0;
00415 fSqrDist = fA00+2.0*fB0+fC;
00416 }
00417 else
00418 {
00419 fS = -fB0/fA00;
00420 fSqrDist = fB0*fS+fC;
00421 }
00422 }
00423 }
00424 else
00425 {
00426 if ( fT >= 0.0 )
00427 {
00428 if ( fT <= fDet )
00429 {
00430 fS = 1.0;
00431 fTmp = fA01+fB1;
00432 if ( fTmp >= 0.0 )
00433 {
00434 fT = 0.0;
00435 fSqrDist = fA00+2.0*fB0+fC;
00436 }
00437 else if ( -fTmp >= fA11 )
00438 {
00439 fT = 1.0;
00440 fSqrDist = fA00+fA11+fC+2.0*(fB0+fTmp);
00441 }
00442 else
00443 {
00444 fT = -fTmp/fA11;
00445 fSqrDist = fTmp*fT+fA00+2.0*fB0+fC;
00446 }
00447 }
00448 else
00449 {
00450 fTmp = fA01+fB0;
00451 if ( -fTmp <= fA00 )
00452 {
00453 fT = 1.0;
00454 if ( fTmp >= 0.0 )
00455 {
00456 fS = 0.0;
00457 fSqrDist = fA11+2.0*fB1+fC;
00458 }
00459 else
00460 {
00461 fS = -fTmp/fA00;
00462 fSqrDist = fTmp*fS+fA11+2.0*fB1+fC;
00463 }
00464 }
00465 else
00466 {
00467 fS = 1.0;
00468 fTmp = fA01+fB1;
00469 if ( fTmp >= 0.0 )
00470 {
00471 fT = 0.0;
00472 fSqrDist = fA00+2.0*fB0+fC;
00473 }
00474 else if ( -fTmp >= fA11 )
00475 {
00476 fT = 1.0;
00477 fSqrDist = fA00+fA11+fC+2.0*(fB0+fTmp);
00478 }
00479 else
00480 {
00481 fT = -fTmp/fA11;
00482 fSqrDist = fTmp*fT+fA00+2.0*fB0+fC;
00483 }
00484 }
00485 }
00486 }
00487 else
00488 {
00489 if ( -fB0 < fA00 )
00490 {
00491 fT = 0.0;
00492 if ( fB0 >= 0.0 )
00493 {
00494 fS = 0.0;
00495 fSqrDist = fC;
00496 }
00497 else
00498 {
00499 fS = -fB0/fA00;
00500 fSqrDist = fB0*fS+fC;
00501 }
00502 }
00503 else
00504 {
00505 fS = 1.0;
00506 fTmp = fA01+fB1;
00507 if ( fTmp >= 0.0 )
00508 {
00509 fT = 0.0;
00510 fSqrDist = fA00+2.0*fB0+fC;
00511 }
00512 else if ( -fTmp >= fA11 )
00513 {
00514 fT = 1.0;
00515 fSqrDist = fA00+fA11+fC+2.0*(fB0+fTmp);
00516 }
00517 else
00518 {
00519 fT = -fTmp/fA11;
00520 fSqrDist = fTmp*fT+fA00+2.0*fB0+fC;
00521 }
00522 }
00523 }
00524 }
00525 }
00526 else
00527 {
00528 if ( fT >= 0.0 )
00529 {
00530 if ( fT <= fDet )
00531 {
00532 fS = 0.0;
00533 if ( fB1 >= 0.0 )
00534 {
00535 fT = 0.0;
00536 fSqrDist = fC;
00537 }
00538 else if ( -fB1 >= fA11 )
00539 {
00540 fT = 1.0;
00541 fSqrDist = fA11+2.0*fB1+fC;
00542 }
00543 else
00544 {
00545 fT = -fB1/fA11;
00546 fSqrDist = fB1*fT+fC;
00547 }
00548 }
00549 else
00550 {
00551 fTmp = fA01+fB0;
00552 if ( fTmp < 0.0 )
00553 {
00554 fT = 1.0;
00555 if ( -fTmp >= fA00 )
00556 {
00557 fS = 1.0;
00558 fSqrDist = fA00+fA11+fC+2.0*(fB1+fTmp);
00559 }
00560 else
00561 {
00562 fS = -fTmp/fA00;
00563 fSqrDist = fTmp*fS+fA11+2.0*fB1+fC;
00564 }
00565 }
00566 else
00567 {
00568 fS = 0.0;
00569 if ( fB1 >= 0.0 )
00570 {
00571 fT = 0.0;
00572 fSqrDist = fC;
00573 }
00574 else if ( -fB1 >= fA11 )
00575 {
00576 fT = 1.0;
00577 fSqrDist = fA11+2.0*fB1+fC;
00578 }
00579 else
00580 {
00581 fT = -fB1/fA11;
00582 fSqrDist = fB1*fT+fC;
00583 }
00584 }
00585 }
00586 }
00587 else
00588 {
00589 if ( fB0 < 0.0 )
00590 {
00591 fT = 0.0;
00592 if ( -fB0 >= fA00 )
00593 {
00594 fS = 1.0;
00595 fSqrDist = fA00+2.0*fB0+fC;
00596 }
00597 else
00598 {
00599 fS = -fB0/fA00;
00600 fSqrDist = fB0*fS+fC;
00601 }
00602 }
00603 else
00604 {
00605 fS = 0.0;
00606 if ( fB1 >= 0.0 )
00607 {
00608 fT = 0.0;
00609 fSqrDist = fC;
00610 }
00611 else if ( -fB1 >= fA11 )
00612 {
00613 fT = 1.0;
00614 fSqrDist = fA11+2.0*fB1+fC;
00615 }
00616 else
00617 {
00618 fT = -fB1/fA11;
00619 fSqrDist = fB1*fT+fC;
00620 }
00621 }
00622 }
00623 }
00624 }
00625 else
00626 {
00627
00628 if ( fA01 > 0.0 )
00629 {
00630
00631 if ( fB0 >= 0.0 )
00632 {
00633 fS = 0.0;
00634 fT = 0.0;
00635 fSqrDist = fC;
00636 }
00637 else if ( -fB0 <= fA00 )
00638 {
00639 fS = -fB0/fA00;
00640 fT = 0.0;
00641 fSqrDist = fB0*fS+fC;
00642 }
00643 else
00644 {
00645 fB1 = -(kDiff|d1);
00646 fS = 1.0;
00647 fTmp = fA00+fB0;
00648 if ( -fTmp >= fA01 )
00649 {
00650 fT = 1.0;
00651 fSqrDist = fA00+fA11+fC+2.0*(fA01+fB0+fB1);
00652 }
00653 else
00654 {
00655 fT = -fTmp/fA01;
00656 fSqrDist = fA00+2.0*fB0+fC+fT*(fA11*fT+2.0*(fA01+fB1));
00657 }
00658 }
00659 }
00660 else
00661 {
00662
00663 if ( -fB0 >= fA00 )
00664 {
00665 fS = 1.0;
00666 fT = 0.0;
00667 fSqrDist = fA00+2.0*fB0+fC;
00668 }
00669 else if ( fB0 <= 0.0 )
00670 {
00671 fS = -fB0/fA00;
00672 fT = 0.0;
00673 fSqrDist = fB0*fS+fC;
00674 }
00675 else
00676 {
00677 fB1 = -(kDiff|d1);
00678 fS = 0.0;
00679 if ( fB0 >= -fA01 )
00680 {
00681 fT = 1.0;
00682 fSqrDist = fA11+2.0*fB1+fC;
00683 }
00684 else
00685 {
00686 fT = -fB0/fA01;
00687 fSqrDist = fC+fT*(2.0*fB1+fA11*fT);
00688 }
00689 }
00690 }
00691 }
00692
00693
00694 if (_min_v0) *_min_v0 = _v00 + fS*d0;
00695 if (_min_v1) *_min_v1 = _v10 + fT*d1;
00696
00697 return fabs(fSqrDist);
00698 }
00699
00700
00701
00702
00703
00704 template<typename Scalar>
00705 bool
00706 circumCenter( const VectorT<Scalar,3>& _v0,
00707 const VectorT<Scalar,3>& _v1,
00708 const VectorT<Scalar,3>& _v2,
00709 VectorT<Scalar,3>& _result )
00710 {
00711 VectorT<Scalar,3> a(_v1-_v2),
00712 b(_v2-_v0),
00713 c(_v0-_v1),
00714 G((_v0+_v1+_v2)/3.0);
00715
00716 Scalar d0 = -(b|c),
00717 d1 = -(c|a),
00718 d2 = -(a|b),
00719 e0 = d1*d2,
00720 e1 = d2*d0,
00721 e2 = d0*d1,
00722 e = e0+e1+e2;
00723
00724 if (e <= NumLimitsT<Scalar>::min()) return false;
00725
00726 VectorT<Scalar,3> H((e0*_v0 + e1*_v1 + e2*_v2)/e);
00727
00728 _result = (Scalar)0.5 * ((Scalar)3.0*G - H);
00729
00730 return true;
00731 }
00732
00733
00734
00735
00736
00737
00738 template<typename Scalar>
00739 Scalar
00740 circumRadiusSquared( const VectorT<Scalar,3>& _v0,
00741 const VectorT<Scalar,3>& _v1,
00742 const VectorT<Scalar,3>& _v2 )
00743 {
00744 VectorT<Scalar,3> v0v1(_v1-_v0),
00745 v0v2(_v2-_v0),
00746 v1v2(_v2-_v1);
00747
00748 Scalar denom = 4.0*((v0v1%v0v2).sqrnorm());
00749 if (denom < NumLimitsT<Scalar>::min() &&
00750 denom > -NumLimitsT<Scalar>::min())
00751 return NumLimitsT<Scalar>::max();
00752
00753 return ( v0v1.sqrnorm() *
00754 v0v2.sqrnorm() *
00755 v1v2.sqrnorm() /
00756 denom );
00757 }
00758
00759
00760
00761
00762
00763 template<typename Scalar>
00764 bool
00765 minSphere(const VectorT<Scalar,3>& _v0,
00766 const VectorT<Scalar,3>& _v1,
00767 const VectorT<Scalar,3>& _v2,
00768 VectorT<Scalar,3>& _center,
00769 Scalar& _radius)
00770 {
00771 VectorT<Scalar,3> a(_v1-_v2),
00772 b(_v2-_v0),
00773 c(_v0-_v1);
00774
00775 Scalar d0 = -(b|c),
00776 d1 = -(c|a),
00777 d2 = -(a|b);
00778
00779
00780
00781 if (d2 < NumLimitsT<Scalar>::min())
00782 {
00783 _center = (_v0+_v1)*0.5;
00784 _radius = 0.5 * c.norm();
00785 return true;
00786 }
00787 if (d0 < NumLimitsT<Scalar>::min())
00788 {
00789 _center = (_v1+_v2)*0.5;
00790 _radius = 0.5 * a.norm();
00791 return true;
00792 }
00793 if (d1 < NumLimitsT<Scalar>::min())
00794 {
00795 _center = (_v2+_v0)*0.5;
00796 _radius = 0.5 * b.norm();
00797 return true;
00798 }
00799
00800
00801
00802 VectorT<Scalar,3> G((_v0+_v1+_v2)/3.0);
00803
00804 Scalar e0 = d1*d2,
00805 e1 = d2*d0,
00806 e2 = d0*d1,
00807 e = e0+e1+e2;
00808
00809 if ( e <= NumLimitsT<Scalar>::min() ) return false;
00810
00811 VectorT<Scalar,3> H((e0*_v0 + e1*_v1 + e2*_v2)/e);
00812
00813 _center = (Scalar)0.5 * ((Scalar)3.0*G - H);
00814 _radius = (_center-_v0).norm();
00815
00816 return true;
00817 }
00818
00819
00820
00821
00822
00823 template<typename Scalar>
00824 Scalar
00825 minRadiusSquared( const VectorT<Scalar,3>& _v0,
00826 const VectorT<Scalar,3>& _v1,
00827 const VectorT<Scalar,3>& _v2 )
00828 {
00829 VectorT<Scalar,3> v0v1(_v1-_v0),
00830 v0v2(_v2-_v0),
00831 v1v2(_v2-_v1);
00832
00833 Scalar denom = 4.0*((v0v1%v0v2).sqrnorm());
00834 if (denom < NumLimitsT<Scalar>::min() &&
00835 denom > -NumLimitsT<Scalar>::min())
00836 return NumLimitsT<Scalar>::max();
00837
00838 Scalar l0 = v0v1.sqrnorm(),
00839 l1 = v0v2.sqrnorm(),
00840 l2 = v1v2.sqrnorm(),
00841 l3 = l0*l1*l2/denom;
00842
00843 return std::max(std::max(l0, l1), std::max(l2, l3));
00844 }
00845
00846
00847
00848
00849
00850 template<typename Scalar>
00851 bool
00852 circumCenter( const VectorT<Scalar,3>& _v0,
00853 const VectorT<Scalar,3>& _v1,
00854 const VectorT<Scalar,3>& _v2,
00855 const VectorT<Scalar,3>& _v3,
00856 VectorT<Scalar,3>& _result )
00857 {
00858 VectorT<Scalar,3>
00859 v0v1(_v1-_v0),
00860 v0v2(_v2-_v0),
00861 v0v3(_v3-_v0);
00862
00863 Scalar denom = ((v0v1[0]*v0v2[1]*v0v3[2] +
00864 v0v1[1]*v0v2[2]*v0v3[0] +
00865 v0v1[2]*v0v2[0]*v0v3[1]) -
00866 (v0v1[0]*v0v2[2]*v0v3[1] +
00867 v0v1[1]*v0v2[0]*v0v3[2] +
00868 v0v1[2]*v0v2[1]*v0v3[0])) * 2.0;
00869
00870 if (denom < NumLimitsT<Scalar>::min() &&
00871 denom > -NumLimitsT<Scalar>::min()) return false;
00872
00873
00874 _result = _v0 + (( v0v3.sqrnorm()*(v0v1%v0v2) +
00875 v0v2.sqrnorm()*(v0v3%v0v1) +
00876 v0v1.sqrnorm()*(v0v2%v0v3) ) / denom);
00877
00878 return true;
00879 }
00880
00881
00882
00883
00884
00885 template <typename Scalar>
00886 VectorT<Scalar,3>
00887 perpendicular( const VectorT<Scalar,3>& v )
00888 {
00889 if (fabs(v[0]) < fabs(v[1]))
00890 {
00891 if (fabs(v[0]) < fabs(v[2]))
00892 return VectorT<Scalar,3>( Scalar(1.0) - v[0]*v[0], -v[0]*v[1], -v[0]*v[2]).normalize();
00893 }
00894 else
00895 {
00896 if (fabs(v[1]) < fabs(v[2]))
00897 return VectorT<Scalar,3>(-v[1]*v[0], Scalar(1.0) - v[1]*v[1], -v[1]*v[2]).normalize();
00898 }
00899
00900 return VectorT<Scalar,3>(-v[2]*v[0], -v[2]*v[1], Scalar(1.0) - v[2]*v[2]).normalize();
00901 }
00902
00903
00904
00905
00906
00907
00908
00909 template<typename Scalar>
00910 bool
00911 baryCoord( const VectorT<Scalar,2> & _p,
00912 const VectorT<Scalar,2> & _u,
00913 const VectorT<Scalar,2> & _v,
00914 const VectorT<Scalar,2> & _w,
00915 VectorT<Scalar,3> & _result )
00916 {
00917 Scalar v0(_v[0]-_u[0]), v1(_v[1]-_u[1]),
00918 w0(_w[0]-_u[0]), w1(_w[1]-_u[1]),
00919 p0(_p[0]-_u[0]), p1(_p[1]-_u[1]),
00920 denom = v0*w1-v1*w0;
00921
00922 if (1.0+fabs(denom) == 1.0) {
00923 std::cerr << "degen tri: ("
00924 << _u << "), ("
00925 << _v << "), ("
00926 << _w << ")\n";
00927 return false;
00928 }
00929
00930 _result[1] = 1.0 + ((p0*w1-p1*w0)/denom) - 1.0;
00931 _result[2] = 1.0 + ((v0*p1-v1*p0)/denom) - 1.0;
00932 _result[0] = 1.0 - _result[1] - _result[2];
00933
00934 return true;
00935 }
00936
00937
00938
00939
00940
00941 template<typename Scalar>
00942 bool
00943 lineIntersection( const VectorT<Scalar,2>& _v0,
00944 const VectorT<Scalar,2>& _v1,
00945 const VectorT<Scalar,2>& _v2,
00946 const VectorT<Scalar,2>& _v3,
00947 Scalar& _t1,
00948 Scalar& _t2 )
00949 {
00950 _t1 = ((_v0[1]-_v2[1])*(_v3[0]-_v2[0])-(_v0[0]-_v2[0])*(_v3[1]-_v2[1])) /
00951 ((_v1[0]-_v0[0])*(_v3[1]-_v2[1])-(_v1[1]-_v0[1])*(_v3[0]-_v2[0]));
00952
00953 _t2 = ((_v0[1]-_v2[1])*(_v1[0]-_v0[0])-(_v0[0]-_v2[0])*(_v1[1]-_v0[1])) /
00954 ((_v1[0]-_v0[0])*(_v3[1]-_v2[1])-(_v1[1]-_v0[1])*(_v3[0]-_v2[0]));
00955
00956 return ((_t1>0.0) && (_t1<1.0) && (_t2>0.0) && (_t2<1.0));
00957 }
00958
00959
00960
00961
00962 template<typename Scalar>
00963 bool
00964 circumCenter( const VectorT<Scalar,2>& _v0,
00965 const VectorT<Scalar,2>& _v1,
00966 const VectorT<Scalar,2>& _v2,
00967 VectorT<Scalar,2>& _result )
00968 {
00969 Scalar x0(_v0[0]), y0(_v0[1]), xy0(x0*x0+y0*y0),
00970 x1(_v1[0]), y1(_v1[1]), xy1(x1*x1+y1*y1),
00971 x2(_v2[0]), y2(_v2[1]), xy2(x2*x2+y2*y2),
00972 a(x0*y1 - x0*y2 - x1*y0 + x1*y2 + x2*y0 - x2*y1),
00973 b(xy0*y1 - xy0*y2 - xy1*y0 + xy1*y2 + xy2*y0 - xy2*y1),
00974 c(xy0*x1 - xy0*x2 - xy1*x0 + xy1*x2 + xy2*x0 - xy2*x1);
00975
00976 if (Scalar(1.0)+a == Scalar(1.0)) {
00977 std::cerr << "circumcircle: colinear points\n";
00978 return false;
00979 }
00980
00981 _result[0] = 0.5*b/a;
00982 _result[1] = -0.5*c/a;
00983
00984 return true;
00985 }
00986
00987
00988
00989
00990
00991
00992 template <typename Scalar, int N>
00993 Scalar
00994 aspectRatio( const VectorT<Scalar, N>& _v0,
00995 const VectorT<Scalar, N>& _v1,
00996 const VectorT<Scalar, N>& _v2 )
00997 {
00998 Scalar d0 = (_v0-_v1).sqrnorm(),
00999 d1 = (_v1-_v2).sqrnorm(),
01000 d2 = (_v2-_v0).sqrnorm();
01001
01002 if (d0 < d1) {
01003 if (d0 < d2) {
01004 if (d1 < d2) return sqrt(d2/d0);
01005 else return sqrt(d1/d0);
01006 }
01007 else return sqrt(d1/d2);
01008 }
01009 else {
01010 if (d1 < d2) {
01011 if (d0 < d2) return sqrt(d2/d1);
01012 else return sqrt(d0/d1);
01013 }
01014 else return sqrt(d0/d2);
01015 }
01016 }
01017
01018
01019
01020
01021
01022 template <typename Scalar, int N>
01023 Scalar
01024 roundness( const VectorT<Scalar, N>& _v0,
01025 const VectorT<Scalar, N>& _v1,
01026 const VectorT<Scalar, N>& _v2 )
01027 {
01028 const double FOUR_ROOT3 = 6.928203230275509;
01029
01030 double area = 0.5*((_v1-_v0)%(_v2-_v0)).norm();
01031
01032 return (Scalar) (FOUR_ROOT3 * area / ((_v0-_v1).sqrnorm() +
01033 (_v1-_v2).sqrnorm() +
01034 (_v2-_v0).sqrnorm() ));
01035 }
01036
01037
01038
01039 }
01040 }
01041