00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 #endif
00028
00029 #include <Mod/Mesh/App/WildMagic4/Wm4IntrSegment3Plane3.h>
00030 #include <Mod/Mesh/App/WildMagic4/Wm4IntrSegment3Box3.h>
00031 #include <Mod/Mesh/App/WildMagic4/Wm4DistVector3Triangle3.h>
00032 #include <Mod/Mesh/App/WildMagic4/Wm4DistSegment3Triangle3.h>
00033
00034 #include "Elements.h"
00035 #include "Algorithm.h"
00036 #include "tritritest.h"
00037
00038 using namespace MeshCore;
00039 using namespace Wm4;
00040
00041 unsigned long MeshPointArray::Get (const MeshPoint &rclPoint)
00042 {
00043 iterator clIter;
00044
00045 clIter = std::find(begin(), end(), rclPoint);
00046 if (clIter != end())
00047 return clIter - begin();
00048 else
00049 return ULONG_MAX;
00050 }
00051
00052 unsigned long MeshPointArray::GetOrAddIndex (const MeshPoint &rclPoint)
00053 {
00054 unsigned long ulIndex;
00055
00056 if ((ulIndex = Get(rclPoint)) == ULONG_MAX)
00057 {
00058 push_back(rclPoint);
00059 return (unsigned long)(size() - 1);
00060 }
00061 else
00062 return ulIndex;
00063 }
00064
00065 void MeshPointArray::SetFlag (MeshPoint::TFlagType tF) const
00066 {
00067 for (MeshPointArray::_TConstIterator i = begin(); i < end(); i++) i->SetFlag(tF);
00068 }
00069
00070 void MeshPointArray::ResetFlag (MeshPoint::TFlagType tF) const
00071 {
00072 for (MeshPointArray::_TConstIterator i = begin(); i < end(); i++) i->ResetFlag(tF);
00073 }
00074
00075 void MeshPointArray::SetProperty (unsigned long ulVal) const
00076 {
00077 for (_TConstIterator pP = begin(); pP != end(); pP++) pP->SetProperty(ulVal);
00078 }
00079
00080 void MeshPointArray::ResetInvalid (void) const
00081 {
00082 for (_TConstIterator pP = begin(); pP != end(); pP++) pP->ResetInvalid();
00083 }
00084
00085 MeshPointArray& MeshPointArray::operator = (const MeshPointArray &rclPAry)
00086 {
00087
00088 TMeshPointArray::operator=(rclPAry);
00089
00090 return *this;
00091 }
00092
00093 void MeshFacetArray::Erase (_TIterator pIter)
00094 {
00095 unsigned long i, *pulN;
00096 _TIterator pPass, pEnd;
00097 unsigned long ulInd = pIter - begin();
00098 erase(pIter);
00099 pPass = begin();
00100 pEnd = end();
00101 while (pPass < pEnd)
00102 {
00103 for (i = 0; i < 3; i++)
00104 {
00105 pulN = &pPass->_aulNeighbours[i];
00106 if ((*pulN > ulInd) && (*pulN != ULONG_MAX))
00107 (*pulN)--;
00108 }
00109 pPass++;
00110 }
00111 }
00112
00113 void MeshFacetArray::TransposeIndices (unsigned long ulOrig, unsigned long ulNew)
00114 {
00115 _TIterator pIter = begin(), pEnd = end();
00116
00117 while (pIter < pEnd)
00118 {
00119 pIter->Transpose(ulOrig, ulNew);
00120 ++pIter;
00121 }
00122 }
00123
00124 void MeshFacetArray::DecrementIndices (unsigned long ulIndex)
00125 {
00126 _TIterator pIter = begin(), pEnd = end();
00127
00128 while (pIter < pEnd)
00129 {
00130 pIter->Decrement(ulIndex);
00131 ++pIter;
00132 }
00133 }
00134
00135 void MeshFacetArray::SetFlag (MeshFacet::TFlagType tF) const
00136 {
00137 for (MeshFacetArray::_TConstIterator i = begin(); i < end(); i++) i->SetFlag(tF);
00138 }
00139
00140 void MeshFacetArray::ResetFlag (MeshFacet::TFlagType tF) const
00141 {
00142 for (MeshFacetArray::_TConstIterator i = begin(); i < end(); i++) i->ResetFlag(tF);
00143 }
00144
00145 void MeshFacetArray::SetProperty (unsigned long ulVal) const
00146 {
00147 for (_TConstIterator pF = begin(); pF != end(); pF++) pF->SetProperty(ulVal);
00148 }
00149
00150 void MeshFacetArray::ResetInvalid (void) const
00151 {
00152 for (_TConstIterator pF = begin(); pF != end(); pF++) pF->ResetInvalid();
00153 }
00154
00155 MeshFacetArray& MeshFacetArray::operator = (const MeshFacetArray &rclFAry)
00156 {
00157 TMeshFacetArray::operator=(rclFAry);
00158 return *this;
00159 }
00160
00161
00162
00163 bool MeshGeomEdge::ContainedByOrIntersectBoundingBox ( const Base::BoundBox3f &rclBB ) const
00164 {
00165
00166 if ((GetBoundBox() && rclBB) == false)
00167 return false;
00168
00169
00170 if (rclBB.IsInBox(GetBoundBox()))
00171 return true;
00172
00173
00174 for (int i=0;i<2;i++)
00175 {
00176 if (rclBB.IsInBox(_aclPoints[i]))
00177 return true;
00178 }
00179
00180
00181 if (IntersectBoundingBox(rclBB))
00182 return true;
00183
00184 return false;
00185 }
00186
00187 Base::BoundBox3f MeshGeomEdge::GetBoundBox () const
00188 {
00189 return Base::BoundBox3f(_aclPoints,2);
00190 }
00191
00192 bool MeshGeomEdge::IntersectBoundingBox (const Base::BoundBox3f &rclBB) const
00193 {
00194 const Base::Vector3f& rclP0 = _aclPoints[0];
00195 const Base::Vector3f& rclP1 = _aclPoints[1];
00196
00197 Vector3<float> A(rclP0.x, rclP0.y, rclP0.z);
00198 Vector3<float> B(rclP1.x, rclP1.y, rclP1.z);
00199
00200 Vector3<float> n = B - A;
00201 float len = n.Length();
00202 n.Normalize();
00203 Vector3<float> p = 0.5f*(A + B);
00204
00205 Segment3<float> akSeg(p, n, 0.5f*len);
00206
00207 Base::Vector3f clCenter = rclBB.CalcCenter();
00208 Vector3<float> center(clCenter.x, clCenter.y, clCenter.z);
00209 Vector3<float> axis0(1.0f, 0.0f, 0.0f);
00210 Vector3<float> axis1(0.0f, 1.0f, 0.0f);
00211 Vector3<float> axis2(0.0f, 0.0f, 1.0f);
00212 float extent0 = 0.5f*rclBB.LengthX();
00213 float extent1 = 0.5f*rclBB.LengthY();
00214 float extent2 = 0.5f*rclBB.LengthZ();
00215
00216 Box3<float> kBox(center, axis0, axis1, axis2, extent0, extent1, extent2);
00217
00218 IntrSegment3Box3<float> intrsectbox(akSeg, kBox, false);
00219 return intrsectbox.Test();
00220 }
00221
00222
00223
00224 MeshGeomFacet::MeshGeomFacet (void)
00225 : _bNormalCalculated(false),
00226 _ucFlag(0), _ulProp(0)
00227 {
00228
00229 }
00230
00231
00232 MeshGeomFacet::MeshGeomFacet (const Base::Vector3f &v1,const Base::Vector3f &v2,const Base::Vector3f &v3)
00233 : _bNormalCalculated(false),
00234 _ucFlag(0),
00235 _ulProp(0)
00236 {
00237 _aclPoints[0] = v1;
00238 _aclPoints[1] = v2;
00239 _aclPoints[2] = v3;
00240 }
00241
00242
00243
00244 bool MeshGeomFacet::IsPointOf (const Base::Vector3f &rclPoint, float fDistance) const
00245 {
00246 if (DistancePlaneToPoint(rclPoint) > fDistance)
00247 return false;
00248
00249
00250 Base::Vector3f clNorm(GetNormal()), clProjPt(rclPoint), clEdge;
00251 Base::Vector3f clP0(_aclPoints[0]), clP1(_aclPoints[1]), clP2(_aclPoints[2]);
00252 float fLP, fLE;
00253
00254 clNorm.Normalize();
00255 clProjPt.ProjToPlane(_aclPoints[0], clNorm);
00256
00257
00258
00259 clEdge = clP1 - clP0;
00260 fLP = clProjPt.DistanceToLine(clP0, clEdge);
00261 if (fLP > 0.0f)
00262 {
00263 fLE = clP2.DistanceToLine(clP0, clEdge);
00264 if (fLP <= fLE)
00265 {
00266 if (clProjPt.DistanceToLine(clP2, clEdge) > fLE)
00267 return false;
00268 }
00269 else
00270 return false;
00271 }
00272
00273
00274 clEdge = clP2 - clP0;
00275 fLP = clProjPt.DistanceToLine(clP0, clEdge);
00276 if (fLP > 0.0f)
00277 {
00278 fLE = clP1.DistanceToLine(clP0, clEdge);
00279 if (fLP <= fLE)
00280 {
00281 if (clProjPt.DistanceToLine(clP1, clEdge) > fLE)
00282 return false;
00283 }
00284 else
00285 return false;
00286 }
00287
00288
00289 clEdge = clP2 - clP1;
00290 fLP = clProjPt.DistanceToLine(clP1, clEdge);
00291 if (fLP > 0.0f)
00292 {
00293 fLE = clP0.DistanceToLine(clP1, clEdge);
00294 if (fLP <= fLE)
00295 {
00296 if (clProjPt.DistanceToLine(clP0, clEdge) > fLE)
00297 return false;
00298 }
00299 else
00300 return false;
00301 }
00302
00303 return true;
00304 }
00305
00306 bool MeshGeomFacet::IsPointOfFace (const Base::Vector3f& rclP, float fDistance) const
00307 {
00308
00309
00310 Base::Vector3f a(_aclPoints[0].x, _aclPoints[0].y, _aclPoints[0].z);
00311 Base::Vector3f b(_aclPoints[1].x, _aclPoints[1].y, _aclPoints[1].z);
00312 Base::Vector3f c(_aclPoints[2].x, _aclPoints[2].y, _aclPoints[2].z);
00313 Base::Vector3f p(rclP);
00314
00315 Base::Vector3f n = (b - a) % (c - a);
00316 Base::Vector3f n1 = (a - p) % (b - p);
00317 Base::Vector3f n2 = (c - p) % (a - p);
00318 Base::Vector3f n3 = (b - p) % (c - p);
00319
00320 if (n * (p - a) > fDistance * n.Length())
00321 return false;
00322
00323 if (n * (a - p) > fDistance * n.Length())
00324 return false;
00325
00326 if (n * n1 <= 0.0f)
00327 return false;
00328
00329 if (n * n2 <= 0.0f)
00330 return false;
00331
00332 if (n * n3 <= 0.0f)
00333 return false;
00334
00335 return true;
00336 }
00337
00338 bool MeshGeomFacet::Weights(const Base::Vector3f& rclP, float& w0, float& w1, float& w2) const
00339 {
00340 float fAreaABC = Area();
00341 float fAreaPBC = MeshGeomFacet(rclP,_aclPoints[1],_aclPoints[2]).Area();
00342 float fAreaPCA = MeshGeomFacet(rclP,_aclPoints[2],_aclPoints[0]).Area();
00343 float fAreaPAB = MeshGeomFacet(rclP,_aclPoints[0],_aclPoints[1]).Area();
00344
00345 w0=fAreaPBC/fAreaABC;
00346 w1=fAreaPCA/fAreaABC;
00347 w2=fAreaPAB/fAreaABC;
00348
00349 return fabs(w0+w1+w2-1.0f)<0.001f;
00350 }
00351
00352 void MeshGeomFacet::ProjectPointToPlane (Base::Vector3f &rclPoint) const
00353 {
00354 rclPoint.ProjToPlane(_aclPoints[0], GetNormal());
00355 }
00356
00357 void MeshGeomFacet::ProjectFacetToPlane (MeshGeomFacet &rclFacet) const
00358 {
00359
00360 IntersectPlaneWithLine( rclFacet._aclPoints[0], GetNormal(), rclFacet._aclPoints[0] );
00361 IntersectPlaneWithLine( rclFacet._aclPoints[1], GetNormal(), rclFacet._aclPoints[1] );
00362 IntersectPlaneWithLine( rclFacet._aclPoints[2], GetNormal(), rclFacet._aclPoints[2] );
00363 }
00364
00365 void MeshGeomFacet::Enlarge (float fDist)
00366 {
00367 Base::Vector3f clM, clU, clV, clPNew[3];
00368 float fA, fD;
00369 unsigned long i, ulP1, ulP2, ulP3;
00370
00371 for (i = 0; i < 3; i++)
00372 {
00373 ulP1 = i;
00374 ulP2 = (i + 1) % 3;
00375 ulP3 = (i + 2) % 3;
00376 clU = _aclPoints[ulP2] - _aclPoints[ulP1];
00377 clV = _aclPoints[ulP3] - _aclPoints[ulP1];
00378 clM = -(clU + clV);
00379 fA = clM.GetAngle(-clU);
00380 fD = fDist / float(sin(fA));
00381 clM.Normalize();
00382 clM.Scale(fD, fD, fD);
00383 clPNew[ulP1] = _aclPoints[ulP1] + clM;
00384 }
00385
00386 _aclPoints[0] = clPNew[0];
00387 _aclPoints[1] = clPNew[1];
00388 _aclPoints[2] = clPNew[2];
00389 }
00390
00391 bool MeshGeomFacet::IsDegenerated() const
00392 {
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 Base::Vector3f u = _aclPoints[1] - _aclPoints[0];
00411 Base::Vector3f v = _aclPoints[2] - _aclPoints[0];
00412 float eps = MeshDefinitions::_fMinPointDistanceP2;
00413 float uu = u*u; if (uu < eps) return true;
00414 float vv = v*v; if (vv < eps) return true;
00415 float uv = u*v;
00416 if (uu*vv-uv*uv < eps*std::max<float>(uu,vv))
00417 return true;
00418 return false;
00419 }
00420
00421 bool MeshGeomFacet::IsDeformed() const
00422 {
00423 float fCosAngle;
00424 Base::Vector3f u,v;
00425
00426 for (int i=0; i<3; i++)
00427 {
00428 u = _aclPoints[(i+1)%3]-_aclPoints[i];
00429 v = _aclPoints[(i+2)%3]-_aclPoints[i];
00430 u.Normalize();
00431 v.Normalize();
00432
00433 fCosAngle = u * v;
00434
00435
00436 if (fCosAngle > 0.86f || fCosAngle < -0.5f)
00437 return true;
00438 }
00439
00440 return false;
00441 }
00442
00443 bool MeshGeomFacet::IntersectBoundingBox ( const Base::BoundBox3f &rclBB ) const
00444 {
00445
00446 const Base::Vector3f& v0 = _aclPoints[0];
00447 const Base::Vector3f& v1 = _aclPoints[1];
00448 const Base::Vector3f& v2 = _aclPoints[2];
00449
00450
00451 if ( rclBB.IsInBox( v0 ) || rclBB.IsInBox( v1 ) || rclBB.IsInBox( v2 ) )
00452 return true;
00453
00454
00455 float len0 = (v0-v1).Length();
00456 float len1 = (v1-v2).Length();
00457 float len2 = (v2-v0).Length();
00458
00459
00460 Vector3<float> p0(0.5f*(v0.x+v1.x), 0.5f*(v0.y+v1.y), 0.5f*(v0.z+v1.z));
00461 Vector3<float> p1(0.5f*(v1.x+v2.x), 0.5f*(v1.y+v2.y), 0.5f*(v1.z+v2.z));
00462 Vector3<float> p2(0.5f*(v2.x+v0.x), 0.5f*(v2.y+v0.y), 0.5f*(v2.z+v0.z));
00463
00464 Vector3<float> d0(v1.x - v0.x, v1.y - v0.y, v1.z - v0.z);
00465 d0.Normalize();
00466 Vector3<float> d1(v2.x - v1.x, v2.y - v1.y, v2.z - v1.z);
00467 d1.Normalize();
00468 Vector3<float> d2(v0.x - v2.x, v0.y - v2.y, v0.z - v2.z);
00469 d2.Normalize();
00470
00471 Segment3<float> akSeg0(p0, d0, len0/2.0f );
00472 Segment3<float> akSeg1(p1, d1, len1/2.0f);
00473 Segment3<float> akSeg2(p2, d2, len2/2.0f);
00474
00475
00476 Base::Vector3f clCenter = rclBB.CalcCenter();
00477 Vector3<float> center(clCenter.x, clCenter.y, clCenter.z);
00478 Vector3<float> axis0(1.0f, 0.0f, 0.0f);
00479 Vector3<float> axis1(0.0f, 1.0f, 0.0f);
00480 Vector3<float> axis2(0.0f, 0.0f, 1.0f);
00481 float extent0 = 0.5f*rclBB.LengthX();
00482 float extent1 = 0.5f*rclBB.LengthY();
00483 float extent2 = 0.5f*rclBB.LengthZ();
00484
00485 Box3<float> akBox(center, axis0, axis1, axis2, extent0, extent1, extent2);
00486
00487
00488 IntrSegment3Box3<float> akSec0(akSeg0, akBox, false);
00489 if ( akSec0.Test() )
00490 return true;
00491 IntrSegment3Box3<float> akSec1(akSeg1, akBox, false);
00492 if ( akSec1.Test() )
00493 return true;
00494 IntrSegment3Box3<float> akSec2(akSeg2, akBox, false);
00495 if ( akSec2.Test() )
00496 return true;
00497
00498
00499 return false;
00500 }
00501
00502 bool MeshGeomFacet::IntersectWithPlane (const Base::Vector3f &rclBase, const Base::Vector3f &rclNormal, Base::Vector3f &rclP1, Base::Vector3f &rclP2) const
00503 {
00504
00505 const Base::Vector3f& v0 = _aclPoints[0];
00506 const Base::Vector3f& v1 = _aclPoints[1];
00507 const Base::Vector3f& v2 = _aclPoints[2];
00508
00509
00510 float len0 = (v0-v1).Length();
00511 float len1 = (v1-v2).Length();
00512 float len2 = (v2-v0).Length();
00513
00514
00515 Vector3<float> p0(0.5f*(v0.x+v1.x), 0.5f*(v0.y+v1.y), 0.5f*(v0.z+v1.z));
00516 Vector3<float> p1(0.5f*(v1.x+v2.x), 0.5f*(v1.y+v2.y), 0.5f*(v1.z+v2.z));
00517 Vector3<float> p2(0.5f*(v2.x+v0.x), 0.5f*(v2.y+v0.y), 0.5f*(v2.z+v0.z));
00518
00519 Vector3<float> d0(v1.x - v0.x, v1.y - v0.y, v1.z - v0.z);
00520 d0.Normalize();
00521 Vector3<float> d1(v2.x - v1.x, v2.y - v1.y, v2.z - v1.z);
00522 d1.Normalize();
00523 Vector3<float> d2(v0.x - v2.x, v0.y - v2.y, v0.z - v2.z);
00524 d2.Normalize();
00525
00526 Segment3<float> akSeg0(p0, d0, len0/2.0f );
00527 Segment3<float> akSeg1(p1, d1, len1/2.0f);
00528 Segment3<float> akSeg2(p2, d2, len2/2.0f);
00529
00530
00531 Vector3<float> p(rclBase.x, rclBase.y, rclBase.z);
00532 Vector3<float> n(rclNormal.x, rclNormal.y, rclNormal.z);
00533 Plane3<float> akPln(n, p);
00534
00535
00536 IntrSegment3Plane3<float> test0(akSeg0, akPln);
00537 IntrSegment3Plane3<float> test1(akSeg1, akPln);
00538 IntrSegment3Plane3<float> test2(akSeg2, akPln);
00539
00540 Vector3<float> intr;
00541 if ( test0.Find() )
00542 {
00543 intr = p0 + test0.GetSegmentT() * d0;
00544 rclP1.Set( intr[0], intr[1], intr[2]);
00545
00546 if ( test1.Find() )
00547 {
00548 intr = p1 + test1.GetSegmentT() * d1;
00549 rclP2.Set( intr[0], intr[1], intr[2]);
00550 return true;
00551 }
00552 else if ( test2.Find() )
00553 {
00554 intr = p2 + test2.GetSegmentT() * d2;
00555 rclP2.Set( intr[0], intr[1], intr[2]);
00556 return true;
00557 }
00558 }
00559 else if ( test1.Find() )
00560 {
00561 intr = p1 + test1.GetSegmentT() * d1;
00562 rclP1.Set( intr[0], intr[1], intr[2]);
00563
00564 if ( test2.Find() )
00565 {
00566 intr = p2 + test2.GetSegmentT() * d2;
00567 rclP2.Set( intr[0], intr[1], intr[2]);
00568 return true;
00569 }
00570 }
00571
00572 return false;
00573 }
00574
00575 bool MeshGeomFacet::Foraminate (const Base::Vector3f &P, const Base::Vector3f &dir, Base::Vector3f &I, float fMaxAngle) const
00576 {
00577 const float eps = 1e-06f;
00578 Base::Vector3f n = this->GetNormal();
00579
00580
00581
00582 if (dir.GetAngle(n) > fMaxAngle)
00583 return false;
00584
00585 float nn = n * n;
00586 float nd = n * dir;
00587 float dd = dir * dir;
00588
00589
00590 if ((nd * nd) <= (eps * dd * nn))
00591 return false;
00592
00593 Base::Vector3f u = this->_aclPoints[1] - this->_aclPoints[0];
00594 Base::Vector3f v = this->_aclPoints[2] - this->_aclPoints[0];
00595
00596 Base::Vector3f w0 = P - this->_aclPoints[0];
00597 float r = -(n * w0) / nd;
00598 Base::Vector3f w = w0 + r * dir;
00599
00600 float uu = u * u;
00601 float uv = u * v;
00602 float vv = v * v;
00603 float wu = w * u;
00604 float wv = w * v;
00605 float det = float(fabs((uu * vv) - (uv * uv)));
00606
00607 float s = (vv * wu) - (uv * wv);
00608 float t = (uu * wv) - (uv * wu);
00609
00610
00611 if ((s >= 0.0f) && (t >= 0.0f) && ((s + t) <= det)) {
00612 I = w + this->_aclPoints[0];
00613 return true;
00614 }
00615
00616 return false;
00617 }
00618
00619 bool MeshGeomFacet::IntersectPlaneWithLine (const Base::Vector3f &rclPt, const Base::Vector3f &rclDir, Base::Vector3f &rclRes) const
00620 {
00621
00622 if ( fabs(rclDir * GetNormal()) < 1e-3f )
00623 return false;
00624
00625 float s = ( ( GetGravityPoint() - rclPt ) * GetNormal() )
00626 / ( rclDir * GetNormal() );
00627 rclRes = rclPt + s * rclDir;
00628
00629 return true;
00630 }
00631
00632 bool MeshGeomFacet::IntersectWithLine (const Base::Vector3f &rclPt, const Base::Vector3f &rclDir, Base::Vector3f &rclRes) const
00633 {
00634 if ( !IntersectPlaneWithLine( rclPt, rclDir, rclRes ) )
00635 return false;
00636
00637 return IsPointOfFace(rclRes, 1e-03f);
00638 }
00639
00640 float MeshGeomFacet::DistanceToLineSegment (const Base::Vector3f &rclP1, const Base::Vector3f &rclP2) const
00641 {
00642
00643 Vector3<float> A(rclP1.x, rclP1.y, rclP1.z);
00644 Vector3<float> B(rclP2.x, rclP2.y, rclP2.z);
00645
00646 Vector3<float> n = B - A;
00647 float len = n.Length();
00648 n.Normalize();
00649 Vector3<float> p = 0.5f*(A + B);
00650
00651 Segment3<float> akSeg(p, n, 0.5f*len);
00652
00653
00654 Vector3<float> akF0(_aclPoints[0].x, _aclPoints[0].y, _aclPoints[0].z);
00655 Vector3<float> akF1(_aclPoints[1].x, _aclPoints[1].y, _aclPoints[1].z);
00656 Vector3<float> akF2(_aclPoints[2].x, _aclPoints[2].y, _aclPoints[2].z);
00657
00658 Triangle3<float> akTria(akF0, akF1, akF2);
00659
00660 DistSegment3Triangle3<float> akDistSegTria(akSeg, akTria);
00661 return akDistSegTria.Get();
00662 }
00663
00664 float MeshGeomFacet::DistanceToPoint (const Base::Vector3f &rclPt, Base::Vector3f &rclNt) const
00665 {
00666 Vector3<float> akPt(rclPt.x, rclPt.y, rclPt.z);
00667 Vector3<float> akF0(_aclPoints[0].x, _aclPoints[0].y, _aclPoints[0].z);
00668 Vector3<float> akF1(_aclPoints[1].x, _aclPoints[1].y, _aclPoints[1].z);
00669 Vector3<float> akF2(_aclPoints[2].x, _aclPoints[2].y, _aclPoints[2].z);
00670
00671 Triangle3<float> akTria(akF0, akF1, akF2);
00672 DistVector3Triangle3<float> akDistPtTria(akPt, akTria);
00673
00674 float fDist = akDistPtTria.Get();
00675
00676
00677 Vector3<float> akNt = akDistPtTria.GetClosestPoint1();
00678 rclNt.Set(akNt.X(), akNt.Y(), akNt.Z());
00679
00680 return fDist;
00681 }
00682
00683 void MeshGeomFacet::SubSample (float fStep, std::vector<Base::Vector3f> &rclPoints) const
00684 {
00685 std::vector<Base::Vector3f> clPoints;
00686 Base::Vector3f A = _aclPoints[0];
00687 Base::Vector3f B = _aclPoints[1];
00688 Base::Vector3f C = _aclPoints[2];
00689 Base::Vector3f clVecAB(B - A);
00690 Base::Vector3f clVecAC(C - A);
00691 Base::Vector3f clVecBC(C - B);
00692
00693
00694 float fLenAB = clVecAB.Length();
00695 float fLenAC = clVecAC.Length();
00696 float fLenBC = clVecBC.Length();
00697
00698 if (fLenAC > fLenAB)
00699 {
00700 std::swap(B, C);
00701 std::swap(fLenAB, fLenAC);
00702 }
00703 if (fLenBC > fLenAB)
00704 {
00705 std::swap(A, C);
00706 std::swap(fLenBC, fLenAB);
00707 }
00708
00709 clVecAB = (B - A);
00710 clVecAC = (C - A);
00711 clVecBC = (C - B);
00712 Base::Vector3f clVecABNorm(clVecAB);
00713 Base::Vector3f clVecHNorm((clVecAB % clVecAC) % clVecAB);
00714 clVecABNorm.Normalize();
00715 clVecHNorm.Normalize();
00716
00717 float bx = fLenAB;
00718 float cy = float(sin(clVecAB.GetAngle(clVecAC)) * fLenAC);
00719 float cx = float(sqrt(fabs(fLenAC * fLenAC - cy * cy)));
00720
00721 float fDetABC = bx*cy;
00722
00723 for (float px = (fStep / 2.0f); px < fLenAB; px += fStep)
00724 {
00725 for (float py = (fStep / 2.0f); py < cy; py += fStep)
00726 {
00727 float u = (bx*cy + cx*py - px*cy - bx*py) / fDetABC;
00728 float v = (px*cy - cx*py) / fDetABC;
00729 float w = (bx*py) / fDetABC;
00730
00731 if ((u >= 0.0f) && (v >= 0.0f) && (w >= 0.0f) && ((u + v) < 1.0f))
00732 {
00733
00734 Base::Vector3f clV = A + (px * clVecABNorm) + (py * clVecHNorm);
00735 clPoints.push_back(clV);
00736
00737 }
00738 else
00739 break;
00740 }
00741 }
00742
00743
00744 if (clPoints.size() == 0)
00745 clPoints.push_back(this->GetGravityPoint());
00746
00747 rclPoints.insert(rclPoints.end(), clPoints.begin(), clPoints.end());
00748 }
00749
00755 bool MeshGeomFacet::IntersectWithFacet(const MeshGeomFacet &rclFacet) const
00756 {
00757 float V[3][3], U[3][3];
00758 for (int i = 0; i < 3; i++)
00759 {
00760 V[i][0] = _aclPoints[i].x;
00761 V[i][1] = _aclPoints[i].y;
00762 V[i][2] = _aclPoints[i].z;
00763 U[i][0] = rclFacet._aclPoints[i].x;
00764 U[i][1] = rclFacet._aclPoints[i].y;
00765 U[i][2] = rclFacet._aclPoints[i].z;
00766 }
00767
00768 if (tri_tri_intersect(V[0], V[1], V[2], U[0], U[1], U[2]) == 0)
00769 return false;
00770 return true;
00771 }
00772
00778 int MeshGeomFacet::IntersectWithFacet (const MeshGeomFacet& rclFacet,
00779 Base::Vector3f& rclPt0,
00780 Base::Vector3f& rclPt1) const
00781 {
00782 float V[3][3], U[3][3];
00783 int coplanar = 0;
00784 float isectpt1[3], isectpt2[3];
00785
00786 for (int i = 0; i < 3; i++)
00787 {
00788 V[i][0] = _aclPoints[i].x;
00789 V[i][1] = _aclPoints[i].y;
00790 V[i][2] = _aclPoints[i].z;
00791 U[i][0] = rclFacet._aclPoints[i].x;
00792 U[i][1] = rclFacet._aclPoints[i].y;
00793 U[i][2] = rclFacet._aclPoints[i].z;
00794 }
00795
00796 if (tri_tri_intersect_with_isectline(V[0], V[1], V[2], U[0], U[1], U[2],
00797 &coplanar, isectpt1, isectpt2) == 0)
00798 return 0;
00799
00800 rclPt0.x = isectpt1[0]; rclPt0.y = isectpt1[1]; rclPt0.z = isectpt1[2];
00801 rclPt1.x = isectpt2[0]; rclPt1.y = isectpt2[1]; rclPt1.z = isectpt2[2];
00802
00803
00804
00805
00806 float mult = (float)fabs(this->GetNormal() * rclFacet.GetNormal());
00807 if (rclPt0 == rclPt1) {
00808 if (mult < 0.995)
00809 return 1;
00810 if (this->IsPointOf(rclPt0) && rclFacet.IsPointOf(rclPt0))
00811 return 1;
00812 }
00813 else {
00814 if (mult < 0.995)
00815 return 2;
00816 if (this->IsPointOf(rclPt0) && rclFacet.IsPointOf(rclPt0) &&
00817 this->IsPointOf(rclPt1) && rclFacet.IsPointOf(rclPt1))
00818 return 2;
00819 }
00820
00821
00822 return 0;
00823 }
00824
00825 bool MeshGeomFacet::IsPointOf (const Base::Vector3f &P) const
00826 {
00827 Base::Vector3d p1(this->_aclPoints[0].x,this->_aclPoints[0].y,this->_aclPoints[0].z);
00828 Base::Vector3d p2(this->_aclPoints[1].x,this->_aclPoints[1].y,this->_aclPoints[1].z);
00829 Base::Vector3d p3(this->_aclPoints[2].x,this->_aclPoints[2].y,this->_aclPoints[2].z);
00830 Base::Vector3d p4(P.x,P.y,P.z);
00831
00832 Base::Vector3d u = p2 - p1;
00833 Base::Vector3d v = p3 - p1;
00834 Base::Vector3d w = p4 - p1;
00835
00836 double uu = u * u;
00837 double uv = u * v;
00838 double vv = v * v;
00839 double wu = w * u;
00840 double wv = w * v;
00841 double det = fabs((uu * vv) - (uv * uv));
00842
00843
00844
00845
00846
00847 const double eps=std::min<double>(1.0e-6, det*det);
00848
00849 double s = (vv * wu) - (uv * wv);
00850 double t = (uu * wv) - (uv * wu);
00851
00852
00853 if ((s >= -eps) && (t >= -eps) && ((s + t) <= det+eps)) {
00854 return true;
00855 }
00856
00857 return false;
00858 }
00859
00860 float MeshGeomFacet::CenterOfInscribedCircle(Base::Vector3f& rclCenter) const
00861 {
00862 const Base::Vector3f& p0 = _aclPoints[0];
00863 const Base::Vector3f& p1 = _aclPoints[1];
00864 const Base::Vector3f& p2 = _aclPoints[2];
00865
00866 float a = Base::Distance(p1,p2);
00867 float b = Base::Distance(p2,p0);
00868 float c = Base::Distance(p0,p1);
00869
00870
00871 float fRadius = Area();
00872 fRadius *= 2.0f/(a + b + c);
00873
00874
00875 float w = a + b + c;
00876 rclCenter.x = (a*p0.x + b*p1.x + c*p2.x)/w;
00877 rclCenter.y = (a*p0.y + b*p1.y + c*p2.y)/w;
00878 rclCenter.z = (a*p0.z + b*p1.z + c*p2.z)/w;
00879
00880 return fRadius;
00881 }
00882
00883 float MeshGeomFacet::CenterOfCircumCircle(Base::Vector3f& rclCenter) const
00884 {
00885 const Base::Vector3f& p0 = _aclPoints[0];
00886 const Base::Vector3f& p1 = _aclPoints[1];
00887 const Base::Vector3f& p2 = _aclPoints[2];
00888
00889 Base::Vector3f u = (p1-p0);
00890 Base::Vector3f v = (p2-p1);
00891 Base::Vector3f w = (p0-p2);
00892
00893 float uu = (u * u);
00894 float vv = (v * v);
00895 float ww = (w * w);
00896 float uv = - (u * v);
00897 float vw = - (v * w);
00898 float uw = - (w * u);
00899
00900 float w0 = (float)(2 * sqrt(uu * ww - uw * uw) * uw / (uu * ww));
00901 float w1 = (float)(2 * sqrt(uu * vv - uv * uv) * uv / (uu * vv));
00902 float w2 = (float)(2 * sqrt(vv * ww - vw * vw) * vw / (vv * ww));
00903
00904
00905 float wx = w0 + w1 + w2;
00906 rclCenter.x = (w0*p0.x + w1*p1.x + w2*p2.x)/wx;
00907 rclCenter.y = (w0*p0.y + w1*p1.y + w2*p2.y)/wx;
00908 rclCenter.z = (w0*p0.z + w1*p1.z + w2*p2.z)/wx;
00909
00910
00911 float fRadius = (float)(sqrt(uu * vv * ww) / (4 * Area()));
00912
00913 return fRadius;
00914 }
00915
00916 unsigned short MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt) const
00917 {
00918 unsigned short usSide;
00919
00920 const Base::Vector3f& rcP1 = _aclPoints[0];
00921 const Base::Vector3f& rcP2 = _aclPoints[1];
00922 const Base::Vector3f& rcP3 = _aclPoints[2];
00923
00924 float fD1 = FLOAT_MAX;
00925 float fD2 = FLOAT_MAX;
00926 float fD3 = FLOAT_MAX;
00927
00928
00929 Base::Vector3f clDir = rcP2 - rcP1;
00930 float fLen = Base::Distance(rcP2, rcP1);
00931 float t = ( ( rclPt - rcP1 ) * clDir ) / ( fLen * fLen );
00932 if ( t < 0.0f )
00933 fD1 = Base::Distance(rclPt, rcP1);
00934 else if ( t > 1.0f )
00935 fD1 = Base::Distance(rclPt, rcP2);
00936 else
00937 fD1 = ( ( ( rclPt - rcP1 ) % clDir).Length() ) / fLen;
00938
00939
00940 clDir = rcP3 - rcP2;
00941 fLen = Base::Distance(rcP3, rcP2);
00942 t = ( ( rclPt - rcP2 ) * clDir ) / ( fLen * fLen );
00943 if ( t < 0.0f )
00944 fD2 = Base::Distance(rclPt, rcP2);
00945 else if ( t > 1.0f )
00946 fD2 = Base::Distance(rclPt, rcP3);
00947 else
00948 fD2 = ( ( ( rclPt - rcP2 ) % clDir).Length() ) / fLen;
00949
00950
00951 clDir = rcP1 - rcP3;
00952 fLen = Base::Distance(rcP1, rcP3);
00953 t = ( ( rclPt - rcP3 ) * clDir ) / ( fLen * fLen );
00954 if ( t < 0.0f )
00955 fD3 = Base::Distance(rclPt, rcP3);
00956 else if ( t > 1.0f )
00957 fD3 = Base::Distance(rclPt, rcP1);
00958 else
00959 fD3 = ( ( ( rclPt - rcP3 ) % clDir).Length() ) / fLen;
00960
00961 if ( fD1 < fD2 )
00962 {
00963 if ( fD1 < fD3 )
00964 {
00965 usSide = 0;
00966 }
00967 else
00968 {
00969 usSide = 2;
00970 }
00971 }
00972 else
00973 {
00974 if ( fD2 < fD3 )
00975 {
00976 usSide = 1;
00977 }
00978 else
00979 {
00980 usSide = 2;
00981 }
00982 }
00983
00984 return usSide;
00985 }
00986
00987 void MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt, float& fDistance, unsigned short& usSide) const
00988 {
00989 const Base::Vector3f& rcP1 = _aclPoints[0];
00990 const Base::Vector3f& rcP2 = _aclPoints[1];
00991 const Base::Vector3f& rcP3 = _aclPoints[2];
00992
00993 float fD1 = FLOAT_MAX;
00994 float fD2 = FLOAT_MAX;
00995 float fD3 = FLOAT_MAX;
00996
00997
00998 Base::Vector3f clDir = rcP2 - rcP1;
00999 float fLen = Base::Distance(rcP2, rcP1);
01000 float t = ( ( rclPt - rcP1 ) * clDir ) / ( fLen * fLen );
01001 if ( t < 0.0f )
01002 fD1 = Base::Distance(rclPt, rcP1);
01003 else if ( t > 1.0f )
01004 fD1 = Base::Distance(rclPt, rcP2);
01005 else
01006 fD1 = ( ( ( rclPt - rcP1 ) % clDir).Length() ) / fLen;
01007
01008
01009 clDir = rcP3 - rcP2;
01010 fLen = Base::Distance(rcP3, rcP2);
01011 t = ( ( rclPt - rcP2 ) * clDir ) / ( fLen * fLen );
01012 if ( t < 0.0f )
01013 fD2 = Base::Distance(rclPt, rcP2);
01014 else if ( t > 1.0f )
01015 fD2 = Base::Distance(rclPt, rcP3);
01016 else
01017 fD2 = ( ( ( rclPt - rcP2 ) % clDir).Length() ) / fLen;
01018
01019
01020 clDir = rcP1 - rcP3;
01021 fLen = Base::Distance(rcP1, rcP3);
01022 t = ( ( rclPt - rcP3 ) * clDir ) / ( fLen * fLen );
01023 if ( t < 0.0f )
01024 fD3 = Base::Distance(rclPt, rcP3);
01025 else if ( t > 1.0f )
01026 fD3 = Base::Distance(rclPt, rcP1);
01027 else
01028 fD3 = ( ( ( rclPt - rcP3 ) % clDir).Length() ) / fLen;
01029
01030 if ( fD1 < fD2 )
01031 {
01032 if ( fD1 < fD3 )
01033 {
01034 usSide = 0;
01035 fDistance = fD1;
01036 }
01037 else
01038 {
01039 usSide = 2;
01040 fDistance = fD3;
01041 }
01042 }
01043 else
01044 {
01045 if ( fD2 < fD3 )
01046 {
01047 usSide = 1;
01048 fDistance = fD2;
01049 }
01050 else
01051 {
01052 usSide = 2;
01053 fDistance = fD3;
01054 }
01055 }
01056 }
01057
01058 float MeshGeomFacet::VolumeOfPrism (const MeshGeomFacet& rclF1) const
01059 {
01060 Base::Vector3f P1 = this->_aclPoints[0];
01061 Base::Vector3f P2 = this->_aclPoints[1];
01062 Base::Vector3f P3 = this->_aclPoints[2];
01063 Base::Vector3f Q1 = rclF1._aclPoints[0];
01064 Base::Vector3f Q2 = rclF1._aclPoints[1];
01065 Base::Vector3f Q3 = rclF1._aclPoints[2];
01066
01067 if ((P1-Q2).Length() < (P1-Q1).Length())
01068 {
01069 Base::Vector3f tmp = Q1;
01070 Q1 = Q2;
01071 Q2 = tmp;
01072 }
01073 if ((P1-Q3).Length() < (P1-Q1).Length())
01074 {
01075 Base::Vector3f tmp = Q1;
01076 Q1 = Q3;
01077 Q3 = tmp;
01078 }
01079 if ((P2-Q3).Length() < (P2-Q2).Length())
01080 {
01081 Base::Vector3f tmp = Q2;
01082 Q2 = Q3;
01083 Q3 = tmp;
01084 }
01085
01086 Base::Vector3f N1 = (P2-P1) % (P3-P1);
01087 Base::Vector3f N2 = (P2-P1) % (Q2-P1);
01088 Base::Vector3f N3 = (Q2-P1) % (Q1-P1);
01089
01090 float fVol=0.0f;
01091 fVol += float(fabs((Q3-P1) * N1));
01092 fVol += float(fabs((Q3-P1) * N2));
01093 fVol += float(fabs((Q3-P1) * N3));
01094
01095 fVol /= 6.0f;
01096
01097 return fVol;;
01098 }
01099
01100 float MeshGeomFacet::MaximumAngle () const
01101 {
01102 float fMaxAngle = 0.0f;
01103
01104 for ( int i=0; i<3; i++ ) {
01105 Base::Vector3f dir1(_aclPoints[(i+1)%3]-_aclPoints[i]);
01106 Base::Vector3f dir2(_aclPoints[(i+2)%3]-_aclPoints[i]);
01107 float fAngle = dir1.GetAngle(dir2);
01108 if (fAngle > fMaxAngle)
01109 fMaxAngle = fAngle;
01110 }
01111
01112 return fMaxAngle;
01113 }
01114
01115 bool MeshGeomFacet::IsPointOfSphere(const Base::Vector3f& rP) const
01116 {
01117 float radius;
01118 Base::Vector3f center;
01119 radius = CenterOfCircumCircle(center);
01120 radius *= radius;
01121
01122 float dist = Base::DistanceP2(rP, center);
01123 return dist < radius;
01124 }
01125
01126 bool MeshGeomFacet::IsPointOfSphere(const MeshGeomFacet& rFacet) const
01127 {
01128 float radius;
01129 Base::Vector3f center;
01130 radius = CenterOfCircumCircle(center);
01131 radius *= radius;
01132
01133 for (int i=0; i<3; i++) {
01134 float dist = Base::DistanceP2(rFacet._aclPoints[i], center);
01135 if (dist < radius)
01136 return true;
01137 }
01138
01139 return false;
01140 }
01141