00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "Wm4FoundationPCH.h"
00018 #include "Wm4Delaunay3.h"
00019 #include "Wm4DelPolyhedronFace.h"
00020 #include "Wm4Mapper3.h"
00021 #include "Wm4ETManifoldMesh.h"
00022 #include "Wm4Delaunay2.h"
00023 #include "Wm4Query3Filtered.h"
00024 #include "Wm4Query3Int64.h"
00025 #include "Wm4Query3TInteger.h"
00026 #include "Wm4Query3TRational.h"
00027
00028
00029
00030
00031
00032
00033 static const int gs_aaiIndex[4][3] = { {1,2,3}, {0,3,2}, {0,1,3}, {0,2,1} };
00034
00035 namespace Wm4
00036 {
00037
00038 template <class Real>
00039 Delaunay3<Real>::Delaunay3 (int iVertexQuantity, Vector3<Real>* akVertex,
00040 Real fEpsilon, bool bOwner, Query::Type eQueryType)
00041 :
00042 Delaunay<Real>(iVertexQuantity,fEpsilon,bOwner,eQueryType),
00043 m_kLineOrigin(Vector3<Real>::ZERO),
00044 m_kLineDirection(Vector3<Real>::ZERO),
00045 m_kPlaneOrigin(Vector3<Real>::ZERO)
00046 {
00047 assert(akVertex);
00048 m_akVertex = akVertex;
00049 m_iUniqueVertexQuantity = 0;
00050 m_akPlaneDirection[0] = Vector3<Real>::ZERO;
00051 m_akPlaneDirection[1] = Vector3<Real>::ZERO;
00052 m_akSVertex = 0;
00053 m_pkQuery = 0;
00054 m_iPathLast = -1;
00055 m_aiPath = 0;
00056 m_iLastFaceV0 = -1;
00057 m_iLastFaceV1 = -1;
00058 m_iLastFaceV2 = -1;
00059 m_iLastFaceOpposite = -1;
00060 m_iLastFaceOppositeIndex = -1;
00061
00062 Mapper3<Real> kMapper(m_iVertexQuantity,m_akVertex,m_fEpsilon);
00063 if (kMapper.GetDimension() == 0)
00064 {
00065
00066
00067 return;
00068 }
00069
00070 int i;
00071 if (kMapper.GetDimension() == 1)
00072 {
00073
00074
00075 m_iDimension = 1;
00076 m_kLineOrigin = kMapper.GetOrigin();
00077 m_kLineDirection = kMapper.GetDirection(0);
00078 return;
00079 }
00080
00081 if (kMapper.GetDimension() == 2)
00082 {
00083
00084
00085 m_iDimension = 2;
00086 m_kPlaneOrigin = kMapper.GetOrigin();
00087 m_akPlaneDirection[0] = kMapper.GetDirection(0);
00088 m_akPlaneDirection[1] = kMapper.GetDirection(1);
00089 return;
00090 }
00091
00092 m_iDimension = 3;
00093
00094
00095
00096 m_akSVertex = WM4_NEW Vector3<Real>[m_iVertexQuantity+4];
00097
00098 if (eQueryType != Query::QT_RATIONAL && eQueryType != Query::QT_FILTERED)
00099 {
00100
00101 m_kMin = kMapper.GetMin();
00102 m_fScale = ((Real)1.0)/kMapper.GetMaxRange();
00103 for (i = 0; i < m_iVertexQuantity; i++)
00104 {
00105 m_akSVertex[i] = (m_akVertex[i] - m_kMin)*m_fScale;
00106 }
00107
00108
00109 m_aiSV[0] = m_iVertexQuantity++;
00110 m_aiSV[1] = m_iVertexQuantity++;
00111 m_aiSV[2] = m_iVertexQuantity++;
00112 m_aiSV[3] = m_iVertexQuantity++;
00113 m_akSVertex[m_aiSV[0]] = Vector3<Real>((Real)-1.0,(Real)-1.0,
00114 (Real)-1.0);
00115 m_akSVertex[m_aiSV[1]] = Vector3<Real>((Real)+6.0,(Real)-1.0,
00116 (Real)-1.0);
00117 m_akSVertex[m_aiSV[2]] = Vector3<Real>((Real)-1.0,(Real)+6.0,
00118 (Real)-1.0);
00119 m_akSVertex[m_aiSV[3]] = Vector3<Real>((Real)-1.0,(Real)-1.0,
00120 (Real)+6.0);
00121
00122 Real fExpand;
00123 if (eQueryType == Query::QT_INT64)
00124 {
00125
00126
00127 fExpand = (Real)(1 << 10);
00128 m_pkQuery = WM4_NEW Query3Int64<Real>(m_iVertexQuantity,
00129 m_akSVertex);
00130 }
00131 else if (eQueryType == Query::QT_INTEGER)
00132 {
00133
00134
00135
00136 fExpand = (Real)(1 << 20);
00137 m_pkQuery = WM4_NEW Query3TInteger<Real>(m_iVertexQuantity,
00138 m_akSVertex);
00139 }
00140 else
00141 {
00142
00143 fExpand = (Real)1.0;
00144 m_pkQuery = WM4_NEW Query3<Real>(m_iVertexQuantity,m_akSVertex);
00145 }
00146
00147 m_fScale *= fExpand;
00148 for (i = 0; i < m_iVertexQuantity; i++)
00149 {
00150 m_akSVertex[i] *= fExpand;
00151 }
00152 }
00153 else
00154 {
00155
00156 m_kMin = Vector3<Real>::ZERO;
00157 m_fScale = (Real)1.0;
00158 size_t uiSize = m_iVertexQuantity*sizeof(Vector3<Real>);
00159 System::Memcpy(m_akSVertex,uiSize,m_akVertex,uiSize);
00160
00161
00162 Vector3<Real> kMin = kMapper.GetMin();
00163 Vector3<Real> kMax = kMapper.GetMax();
00164 Vector3<Real> kDelta = kMax - kMin;
00165 Vector3<Real> kSMin = kMin - kDelta;
00166 Vector3<Real> kSMax = kMax + ((Real)5.0)*kDelta;
00167 m_aiSV[0] = m_iVertexQuantity++;
00168 m_aiSV[1] = m_iVertexQuantity++;
00169 m_aiSV[2] = m_iVertexQuantity++;
00170 m_aiSV[3] = m_iVertexQuantity++;
00171 m_akSVertex[m_aiSV[0]] = kSMin;
00172 m_akSVertex[m_aiSV[1]] = Vector3<Real>(kSMax[0],kSMin[1],kSMin[2]);
00173 m_akSVertex[m_aiSV[2]] = Vector3<Real>(kSMin[0],kSMax[1],kSMin[2]);
00174 m_akSVertex[m_aiSV[3]] = Vector3<Real>(kSMin[0],kSMin[1],kSMax[2]);
00175
00176 if (eQueryType == Query::QT_RATIONAL)
00177 {
00178 m_pkQuery = WM4_NEW Query3TRational<Real>(m_iVertexQuantity,
00179 m_akSVertex);
00180 }
00181 else
00182 {
00183 m_pkQuery = WM4_NEW Query3Filtered<Real>(m_iVertexQuantity,
00184 m_akSVertex,fEpsilon);
00185 }
00186 }
00187
00188 DelTetrahedron<Real>* pkTetra = WM4_NEW DelTetrahedron<Real>(m_aiSV[0],
00189 m_aiSV[1],m_aiSV[2],m_aiSV[3]);
00190 m_kTetrahedron.insert(pkTetra);
00191
00192
00193
00194
00195 std::set<Vector3<Real> > kProcessed;
00196 for (i = 0; i < m_iVertexQuantity-4; i++)
00197 {
00198 if (kProcessed.find(m_akSVertex[i]) == kProcessed.end())
00199 {
00200 Update(i);
00201 kProcessed.insert(m_akSVertex[i]);
00202 }
00203 }
00204 m_iUniqueVertexQuantity = (int)kProcessed.size();
00205
00206
00207 RemoveTetrahedra();
00208
00209
00210 std::map<DelTetrahedron<Real>*,int> kPermute;
00211 typename std::set<DelTetrahedron<Real>*>::iterator pkTIter =
00212 m_kTetrahedron.begin();
00213 for (i = 0; pkTIter != m_kTetrahedron.end(); pkTIter++)
00214 {
00215 pkTetra = *pkTIter;
00216 kPermute[pkTetra] = i++;
00217 }
00218 kPermute[0] = -1;
00219
00220
00221 m_iSimplexQuantity = (int)m_kTetrahedron.size();
00222 if (m_iSimplexQuantity > 0)
00223 {
00224 m_aiIndex = WM4_NEW int[4*m_iSimplexQuantity];
00225 m_aiAdjacent = WM4_NEW int[4*m_iSimplexQuantity];
00226 i = 0;
00227 pkTIter = m_kTetrahedron.begin();
00228 for (; pkTIter != m_kTetrahedron.end(); pkTIter++)
00229 {
00230 pkTetra = *pkTIter;
00231 m_aiIndex[i] = pkTetra->V[0];
00232 m_aiAdjacent[i++] = kPermute[pkTetra->A[0]];
00233 m_aiIndex[i] = pkTetra->V[1];
00234 m_aiAdjacent[i++] = kPermute[pkTetra->A[1]];
00235 m_aiIndex[i] = pkTetra->V[2];
00236 m_aiAdjacent[i++] = kPermute[pkTetra->A[2]];
00237 m_aiIndex[i] = pkTetra->V[3];
00238 m_aiAdjacent[i++] = kPermute[pkTetra->A[3]];
00239 }
00240 assert(i == 4*m_iSimplexQuantity);
00241
00242 m_iPathLast = -1;
00243 m_aiPath = WM4_NEW int[m_iSimplexQuantity+1];
00244 }
00245
00246
00247
00248 m_iVertexQuantity -= 4;
00249
00250 pkTIter = m_kTetrahedron.begin();
00251 for (; pkTIter != m_kTetrahedron.end(); ++pkTIter)
00252 {
00253 WM4_DELETE *pkTIter;
00254 }
00255 }
00256
00257 template <class Real>
00258 Delaunay3<Real>::~Delaunay3 ()
00259 {
00260 WM4_DELETE m_pkQuery;
00261 WM4_DELETE[] m_akSVertex;
00262 WM4_DELETE[] m_aiPath;
00263 if (m_bOwner)
00264 {
00265 WM4_DELETE[] m_akVertex;
00266 }
00267 }
00268
00269 template <class Real>
00270 const Vector3<Real>* Delaunay3<Real>::GetVertices () const
00271 {
00272 return m_akVertex;
00273 }
00274
00275 template <class Real>
00276 int Delaunay3<Real>::GetUniqueVertexQuantity () const
00277 {
00278 return m_iUniqueVertexQuantity;
00279 }
00280
00281 template <class Real>
00282 const Vector3<Real>& Delaunay3<Real>::GetLineOrigin () const
00283 {
00284 return m_kLineOrigin;
00285 }
00286
00287 template <class Real>
00288 const Vector3<Real>& Delaunay3<Real>::GetLineDirection () const
00289 {
00290 return m_kLineDirection;
00291 }
00292
00293 template <class Real>
00294 Delaunay1<Real>* Delaunay3<Real>::GetDelaunay1 () const
00295 {
00296 assert(m_iDimension == 1);
00297 if (m_iDimension != 1)
00298 {
00299 return 0;
00300 }
00301
00302 Real* afProjection = WM4_NEW Real[m_iVertexQuantity];
00303 for (int i = 0; i < m_iVertexQuantity; i++)
00304 {
00305 Vector3<Real> kDiff = m_akVertex[i] - m_kLineOrigin;
00306 afProjection[i] = m_kLineDirection.Dot(kDiff);
00307 }
00308
00309 return WM4_NEW Delaunay1<Real>(m_iVertexQuantity,afProjection,m_fEpsilon,
00310 true,m_eQueryType);
00311 }
00312
00313 template <class Real>
00314 const Vector3<Real>& Delaunay3<Real>::GetPlaneOrigin () const
00315 {
00316 return m_kPlaneOrigin;
00317 }
00318
00319 template <class Real>
00320 const Vector3<Real>& Delaunay3<Real>::GetPlaneDirection (int i) const
00321 {
00322 assert(0 <= i && i < 2);
00323 return m_akPlaneDirection[i];
00324 }
00325
00326 template <class Real>
00327 Delaunay2<Real>* Delaunay3<Real>::GetDelaunay2 () const
00328 {
00329 assert(m_iDimension == 2);
00330 if (m_iDimension != 2)
00331 {
00332 return 0;
00333 }
00334
00335 Vector2<Real>* akProjection = WM4_NEW Vector2<Real>[m_iVertexQuantity];
00336 for (int i = 0; i < m_iVertexQuantity; i++)
00337 {
00338 Vector3<Real> kDiff = m_akVertex[i] - m_kPlaneOrigin;
00339 akProjection[i][0] = m_akPlaneDirection[0].Dot(kDiff);
00340 akProjection[i][1] = m_akPlaneDirection[1].Dot(kDiff);
00341 }
00342
00343 return WM4_NEW Delaunay2<Real>(m_iVertexQuantity,akProjection,m_fEpsilon,
00344 true,m_eQueryType);
00345 }
00346
00347 template <class Real>
00348 bool Delaunay3<Real>::GetHull (int& riTQuantity, int*& raiIndex) const
00349 {
00350 assert(m_iDimension == 3);
00351 if (m_iDimension != 3)
00352 {
00353 return false;
00354 }
00355
00356 riTQuantity = 0;
00357 raiIndex = 0;
00358
00359
00360 int i, iAdjQuantity = 4*m_iSimplexQuantity;
00361 for (i = 0; i < iAdjQuantity; i++)
00362 {
00363 if (m_aiAdjacent[i] == -1)
00364 {
00365 riTQuantity++;
00366 }
00367 }
00368 assert(riTQuantity > 0);
00369 if (riTQuantity == 0)
00370 {
00371 return false;
00372 }
00373
00374
00375 raiIndex = WM4_NEW int[3*riTQuantity];
00376 int* piIndex = raiIndex;
00377 for (i = 0; i < iAdjQuantity; i++)
00378 {
00379 if (m_aiAdjacent[i] == -1)
00380 {
00381 int iTetra = i/4, iFace = i%4;
00382 for (int j = 0; j < 4; j++)
00383 {
00384 if (j != iFace)
00385 {
00386 *piIndex++ = m_aiIndex[4*iTetra+j];
00387 }
00388 }
00389 if ((iFace % 2) == 0)
00390 {
00391 int iSave = *(piIndex-1);
00392 *(piIndex-1) = *(piIndex-2);
00393 *(piIndex-2) = iSave;
00394 }
00395 }
00396 }
00397
00398 return true;
00399 }
00400
00401 template <class Real>
00402 int Delaunay3<Real>::GetContainingTetrahedron (const Vector3<Real>& rkP)
00403 const
00404 {
00405 assert(m_iDimension == 3);
00406 if (m_iDimension != 3)
00407 {
00408 return -1;
00409 }
00410
00411
00412 Vector3<Real> kXFrmP = (rkP - m_kMin)*m_fScale;
00413
00414
00415 int iIndex = (m_iPathLast >= 0 ? m_aiPath[m_iPathLast] : 0);
00416 m_iPathLast = -1;
00417 m_iLastFaceV0 = -1;
00418 m_iLastFaceV1 = -1;
00419 m_iLastFaceV2 = -1;
00420 m_iLastFaceOpposite = -1;
00421 m_iLastFaceOppositeIndex = -1;
00422
00423
00424 for (int i = 0; i < m_iSimplexQuantity; i++)
00425 {
00426 m_aiPath[++m_iPathLast] = iIndex;
00427
00428 int* aiV = &m_aiIndex[4*iIndex];
00429
00430
00431 if (m_pkQuery->ToPlane(kXFrmP,aiV[1],aiV[2],aiV[3]) > 0)
00432 {
00433 iIndex = m_aiAdjacent[4*iIndex];
00434 if (iIndex == -1)
00435 {
00436 m_iLastFaceV0 = aiV[1];
00437 m_iLastFaceV1 = aiV[2];
00438 m_iLastFaceV2 = aiV[3];
00439 m_iLastFaceOpposite = aiV[0];
00440 m_iLastFaceOppositeIndex = 0;
00441 return -1;
00442 }
00443 continue;
00444 }
00445
00446
00447 if (m_pkQuery->ToPlane(kXFrmP,aiV[0],aiV[2],aiV[3]) < 0)
00448 {
00449 iIndex = m_aiAdjacent[4*iIndex+1];
00450 if (iIndex == -1)
00451 {
00452 m_iLastFaceV0 = aiV[0];
00453 m_iLastFaceV1 = aiV[2];
00454 m_iLastFaceV2 = aiV[3];
00455 m_iLastFaceOpposite = aiV[1];
00456 m_iLastFaceOppositeIndex = 1;
00457 return -1;
00458 }
00459 continue;
00460 }
00461
00462
00463 if (m_pkQuery->ToPlane(kXFrmP,aiV[0],aiV[1],aiV[3]) > 0)
00464 {
00465 iIndex = m_aiAdjacent[4*iIndex+2];
00466 if (iIndex == -1)
00467 {
00468 m_iLastFaceV0 = aiV[0];
00469 m_iLastFaceV1 = aiV[1];
00470 m_iLastFaceV2 = aiV[3];
00471 m_iLastFaceOpposite = aiV[2];
00472 m_iLastFaceOppositeIndex = 2;
00473 return -1;
00474 }
00475 continue;
00476 }
00477
00478
00479 if (m_pkQuery->ToPlane(kXFrmP,aiV[0],aiV[1],aiV[2]) < 0)
00480 {
00481 iIndex = m_aiAdjacent[4*iIndex+3];
00482 if (iIndex == -1)
00483 {
00484 m_iLastFaceV0 = aiV[0];
00485 m_iLastFaceV1 = aiV[1];
00486 m_iLastFaceV2 = aiV[2];
00487 m_iLastFaceOpposite = aiV[3];
00488 m_iLastFaceOppositeIndex = 3;
00489 return -1;
00490 }
00491 continue;
00492 }
00493
00494 m_iLastFaceV0 = -1;
00495 m_iLastFaceV1 = -1;
00496 m_iLastFaceV2 = -1;
00497 m_iLastFaceOppositeIndex = -1;
00498 return iIndex;
00499 }
00500
00501 return -1;
00502 }
00503
00504 template <class Real>
00505 int Delaunay3<Real>::GetPathLast () const
00506 {
00507 return m_iPathLast;
00508 }
00509
00510 template <class Real>
00511 const int* Delaunay3<Real>::GetPath () const
00512 {
00513 return m_aiPath;
00514 }
00515
00516 template <class Real>
00517 int Delaunay3<Real>::GetLastFace (int& riV0, int& riV1, int& riV2,
00518 int& riV3) const
00519 {
00520 riV0 = m_iLastFaceV0;
00521 riV1 = m_iLastFaceV1;
00522 riV2 = m_iLastFaceV2;
00523 riV3 = m_iLastFaceOpposite;
00524 return m_iLastFaceOppositeIndex;
00525 }
00526
00527 template <class Real>
00528 bool Delaunay3<Real>::GetVertexSet (int i, Vector3<Real> akV[4]) const
00529 {
00530 assert(m_iDimension == 3);
00531 if (m_iDimension != 3)
00532 {
00533 return false;
00534 }
00535
00536 if (0 <= i && i < m_iSimplexQuantity)
00537 {
00538 akV[0] = m_akVertex[m_aiIndex[4*i ]];
00539 akV[1] = m_akVertex[m_aiIndex[4*i+1]];
00540 akV[2] = m_akVertex[m_aiIndex[4*i+2]];
00541 akV[3] = m_akVertex[m_aiIndex[4*i+3]];
00542 return true;
00543 }
00544
00545 return false;
00546 }
00547
00548 template <class Real>
00549 bool Delaunay3<Real>::GetIndexSet (int i, int aiIndex[4]) const
00550 {
00551 assert(m_iDimension == 3);
00552 if (m_iDimension != 3)
00553 {
00554 return false;
00555 }
00556
00557 if (0 <= i && i < m_iSimplexQuantity)
00558 {
00559 aiIndex[0] = m_aiIndex[4*i ];
00560 aiIndex[1] = m_aiIndex[4*i+1];
00561 aiIndex[2] = m_aiIndex[4*i+2];
00562 aiIndex[3] = m_aiIndex[4*i+3];
00563 return true;
00564 }
00565
00566 return false;
00567 }
00568
00569 template <class Real>
00570 bool Delaunay3<Real>::GetAdjacentSet (int i, int aiAdjacent[4]) const
00571 {
00572 assert(m_iDimension == 3);
00573 if (m_iDimension != 3)
00574 {
00575 return false;
00576 }
00577
00578 if (0 <= i && i < m_iSimplexQuantity)
00579 {
00580 aiAdjacent[0] = m_aiAdjacent[4*i ];
00581 aiAdjacent[1] = m_aiAdjacent[4*i+1];
00582 aiAdjacent[2] = m_aiAdjacent[4*i+2];
00583 aiAdjacent[3] = m_aiAdjacent[4*i+3];
00584 return true;
00585 }
00586
00587 return false;
00588 }
00589
00590 template <class Real>
00591 bool Delaunay3<Real>::GetBarycentricSet (int i, const Vector3<Real>& rkP,
00592 Real afBary[4]) const
00593 {
00594 assert(m_iDimension == 3);
00595 if (m_iDimension != 3)
00596 {
00597 return false;
00598 }
00599
00600 if (0 <= i && i < m_iSimplexQuantity)
00601 {
00602 Vector3<Real> kV0 = m_akVertex[m_aiIndex[4*i ]];
00603 Vector3<Real> kV1 = m_akVertex[m_aiIndex[4*i+1]];
00604 Vector3<Real> kV2 = m_akVertex[m_aiIndex[4*i+2]];
00605 Vector3<Real> kV3 = m_akVertex[m_aiIndex[4*i+3]];
00606 rkP.GetBarycentrics(kV0,kV1,kV2,kV3,afBary);
00607 return true;
00608 }
00609
00610 return false;
00611 }
00612
00613 template <class Real>
00614 void Delaunay3<Real>::Update (int i)
00615 {
00616
00617 DelTetrahedron<Real>* pkTetra = GetContainingTetrahedron(i);
00618
00619
00620 std::stack<DelTetrahedron<Real>*> kStack;
00621 ETManifoldMesh kPolyhedron(0,DelPolyhedronFace<Real>::TCreator);
00622 kStack.push(pkTetra);
00623 pkTetra->OnStack = true;
00624 int j, iV0, iV1, iV2;
00625 DelPolyhedronFace<Real>* pkFace;
00626 while (!kStack.empty())
00627 {
00628 pkTetra = kStack.top();
00629 kStack.pop();
00630 pkTetra->OnStack = false;
00631 for (j = 0; j < 4; j++)
00632 {
00633 DelTetrahedron<Real>* pkAdj = pkTetra->A[j];
00634 if (pkAdj)
00635 {
00636
00637
00638 int iNullIndex = pkTetra->DetachFrom(j,pkAdj);
00639
00640 if (pkAdj->IsInsertionComponent(i,pkTetra,m_pkQuery,m_aiSV))
00641 {
00642 if (!pkAdj->OnStack)
00643 {
00644
00645 kStack.push(pkAdj);
00646 pkAdj->OnStack = true;
00647 }
00648 }
00649 else
00650 {
00651
00652 iV0 = pkTetra->V[gs_aaiIndex[j][0]];
00653 iV1 = pkTetra->V[gs_aaiIndex[j][1]];
00654 iV2 = pkTetra->V[gs_aaiIndex[j][2]];
00655 pkFace = (DelPolyhedronFace<Real>*)
00656 kPolyhedron.InsertTriangle(iV0,iV1,iV2);
00657 pkFace->NullIndex = iNullIndex;
00658 pkFace->Tetra = pkAdj;
00659 }
00660 }
00661 else
00662 {
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 iV0 = pkTetra->V[gs_aaiIndex[j][0]];
00673 if (IsSupervertex(iV0))
00674 {
00675 iV1 = pkTetra->V[gs_aaiIndex[j][1]];
00676 if (IsSupervertex(iV1))
00677 {
00678 iV2 = pkTetra->V[gs_aaiIndex[j][2]];
00679 if (IsSupervertex(iV2))
00680 {
00681 pkFace = (DelPolyhedronFace<Real>*)
00682 kPolyhedron.InsertTriangle(iV0,iV1,iV2);
00683 pkFace->NullIndex = -1;
00684 pkFace->Tetra = 0;
00685 }
00686 }
00687 }
00688 }
00689 }
00690 m_kTetrahedron.erase(pkTetra);
00691 WM4_DELETE pkTetra;
00692 }
00693
00694
00695
00696 const ETManifoldMesh::TMap& rkTMap = kPolyhedron.GetTriangles();
00697 assert(rkTMap.size() >= 4 && kPolyhedron.IsClosed());
00698 typename ETManifoldMesh::TMapCIterator pkTIter;
00699 for (pkTIter = rkTMap.begin(); pkTIter != rkTMap.end(); pkTIter++)
00700 {
00701 pkFace = (DelPolyhedronFace<Real>*)pkTIter->second;
00702
00703
00704 pkTetra = WM4_NEW DelTetrahedron<Real>(i,pkFace->V[0],pkFace->V[1],
00705 pkFace->V[2]);
00706 m_kTetrahedron.insert(pkTetra);
00707
00708
00709 pkTetra->A[0] = pkFace->Tetra;
00710 if (pkFace->Tetra)
00711 {
00712 pkFace->Tetra->A[pkFace->NullIndex] = pkTetra;
00713 }
00714
00715
00716
00717
00718 pkFace->Tetra = pkTetra;
00719 }
00720
00721
00722 DelPolyhedronFace<Real>* pkAdjFace;
00723 for (pkTIter = rkTMap.begin(); pkTIter != rkTMap.end(); pkTIter++)
00724 {
00725 pkFace = (DelPolyhedronFace<Real>*)pkTIter->second;
00726
00727 pkAdjFace = (DelPolyhedronFace<Real>*)pkFace->T[0];
00728 pkFace->Tetra->A[3] = pkAdjFace->Tetra;
00729 assert(SharesFace(3,pkFace->Tetra,pkAdjFace->Tetra));
00730
00731 pkAdjFace = (DelPolyhedronFace<Real>*)pkFace->T[1];
00732 pkFace->Tetra->A[1] = pkAdjFace->Tetra;
00733 assert(SharesFace(1,pkFace->Tetra,pkAdjFace->Tetra));
00734
00735 pkAdjFace = (DelPolyhedronFace<Real>*)pkFace->T[2];
00736 pkFace->Tetra->A[2] = pkAdjFace->Tetra;
00737 assert(SharesFace(2,pkFace->Tetra,pkAdjFace->Tetra));
00738 }
00739 }
00740
00741 template <class Real>
00742 DelTetrahedron<Real>* Delaunay3<Real>::GetContainingTetrahedron (int i) const
00743 {
00744
00745
00746
00747
00748 DelTetrahedron<Real>* pkTetra = *m_kTetrahedron.begin();
00749 int iTQuantity = (int)m_kTetrahedron.size();
00750 for (int iT = 0; iT < iTQuantity; iT++)
00751 {
00752 int* aiV = pkTetra->V;
00753
00754
00755 if (m_pkQuery->ToPlane(i,aiV[1],aiV[2],aiV[3]) > 0)
00756 {
00757 pkTetra = pkTetra->A[0];
00758 if (!pkTetra)
00759 {
00760 break;
00761 }
00762 continue;
00763 }
00764
00765
00766 if (m_pkQuery->ToPlane(i,aiV[0],aiV[2],aiV[3]) < 0)
00767 {
00768 pkTetra = pkTetra->A[1];
00769 if (!pkTetra)
00770 {
00771 break;
00772 }
00773 continue;
00774 }
00775
00776
00777 if (m_pkQuery->ToPlane(i,aiV[0],aiV[1],aiV[3]) > 0)
00778 {
00779 pkTetra = pkTetra->A[2];
00780 if (!pkTetra)
00781 {
00782 break;
00783 }
00784 continue;
00785 }
00786
00787
00788 if (m_pkQuery->ToPlane(i,aiV[0],aiV[1],aiV[2]) < 0)
00789 {
00790 pkTetra = pkTetra->A[3];
00791 if (!pkTetra)
00792 {
00793 break;
00794 }
00795 continue;
00796 }
00797
00798 return pkTetra;
00799 }
00800
00801 assert(false);
00802 return 0;
00803 }
00804
00805 template <class Real>
00806 void Delaunay3<Real>::RemoveTetrahedra ()
00807 {
00808
00809 std::set<DelTetrahedron<Real>*> kRemoveTetra;
00810 DelTetrahedron<Real>* pkTetra;
00811 typename std::set<DelTetrahedron<Real>*>::iterator pkTIter =
00812 m_kTetrahedron.begin();
00813 for (; pkTIter != m_kTetrahedron.end(); pkTIter++)
00814 {
00815 pkTetra = *pkTIter;
00816 for (int j = 0; j < 4; j++)
00817 {
00818 if (IsSupervertex(pkTetra->V[j]))
00819 {
00820 kRemoveTetra.insert(pkTetra);
00821 break;
00822 }
00823 }
00824 }
00825
00826
00827 pkTIter = kRemoveTetra.begin();
00828 for (; pkTIter != kRemoveTetra.end(); pkTIter++)
00829 {
00830 pkTetra = *pkTIter;
00831 for (int j = 0; j < 4; j++)
00832 {
00833
00834 DelTetrahedron<Real>* pkAdj = pkTetra->A[j];
00835 if (pkAdj)
00836 {
00837 for (int k = 0; k < 4; k++)
00838 {
00839 if (pkAdj->A[k] == pkTetra)
00840 {
00841 pkAdj->A[k] = 0;
00842 break;
00843 }
00844 }
00845 }
00846 }
00847 m_kTetrahedron.erase(pkTetra);
00848 WM4_DELETE pkTetra;
00849 }
00850 }
00851
00852 template <class Real>
00853 bool Delaunay3<Real>::IsSupervertex (int i) const
00854 {
00855 for (int j = 0; j < 4; j++)
00856 {
00857 if (i == m_aiSV[j])
00858 {
00859 return true;
00860 }
00861 }
00862 return false;
00863 }
00864
00865 template <class Real>
00866 bool Delaunay3<Real>::SharesFace (int i, DelTetrahedron<Real>* pkFace,
00867 DelTetrahedron<Real>* pkAdj)
00868 {
00869 int aiF[3], iCount = 0, j;
00870 for (j = 0; j < 4; j++)
00871 {
00872 if (j != i)
00873 {
00874 aiF[iCount++] = pkFace->V[j];
00875 }
00876 }
00877
00878 for (i = 0; i < 4; i++)
00879 {
00880 if (pkAdj->V[i] != aiF[0] &&
00881 pkAdj->V[i] != aiF[1] &&
00882 pkAdj->V[i] != aiF[2])
00883 {
00884 break;
00885 }
00886 }
00887 if (i == 4)
00888 {
00889 return false;
00890 }
00891
00892 int aiA[3];
00893 for (j = 0, iCount = 0; j < 4; j++)
00894 {
00895 if (j != i)
00896 {
00897 aiA[iCount++] = pkAdj->V[j];
00898 }
00899 }
00900
00901 if (aiF[0] > aiF[1])
00902 {
00903 j = aiF[0];
00904 aiF[0] = aiF[1];
00905 aiF[1] = j;
00906 }
00907 if (aiF[1] > aiF[2])
00908 {
00909 j = aiF[1];
00910 aiF[1] = aiF[2];
00911 aiF[2] = j;
00912 }
00913 if (aiF[0] > aiF[1])
00914 {
00915 j = aiF[0];
00916 aiF[0] = aiF[1];
00917 aiF[1] = j;
00918 }
00919
00920 if (aiA[0] > aiA[1])
00921 {
00922 j = aiA[0];
00923 aiA[0] = aiA[1];
00924 aiA[1] = j;
00925 }
00926 if (aiA[1] > aiA[2])
00927 {
00928 j = aiA[1];
00929 aiA[1] = aiA[2];
00930 aiA[2] = j;
00931 }
00932 if (aiA[0] > aiA[1])
00933 {
00934 j = aiA[0];
00935 aiA[0] = aiA[1];
00936 aiA[1] = j;
00937 }
00938
00939 if (aiA[0] != aiF[0] || aiA[1] != aiF[1] || aiA[2] != aiF[2])
00940 {
00941 return false;
00942 }
00943
00944 return true;
00945 }
00946
00947 template <class Real>
00948 Delaunay3<Real>::Delaunay3 (const char* acFilename)
00949 :
00950 Delaunay<Real>(0,(Real)0.0,false,Query::QT_REAL)
00951 {
00952 m_akVertex = 0;
00953 m_akSVertex = 0;
00954 m_pkQuery = 0;
00955 m_aiPath = 0;
00956 bool bLoaded = Load(acFilename);
00957 assert(bLoaded);
00958 (void)bLoaded;
00959 }
00960
00961 template <class Real>
00962 bool Delaunay3<Real>::Load (const char* acFilename)
00963 {
00964 FILE* pkIFile = System::Fopen(acFilename,"rb");
00965 if (!pkIFile)
00966 {
00967 return false;
00968 }
00969
00970 Delaunay<Real>::Load(pkIFile);
00971
00972 WM4_DELETE m_pkQuery;
00973 WM4_DELETE[] m_akSVertex;
00974 WM4_DELETE[] m_aiPath;
00975 if (m_bOwner)
00976 {
00977 WM4_DELETE[] m_akVertex;
00978 }
00979
00980 m_bOwner = true;
00981 m_akVertex = WM4_NEW Vector3<Real>[m_iVertexQuantity];
00982 m_akSVertex = WM4_NEW Vector3<Real>[m_iVertexQuantity+4];
00983 m_aiPath = WM4_NEW int[m_iSimplexQuantity+1];
00984
00985 System::Read4le(pkIFile,1,&m_iUniqueVertexQuantity);
00986 System::Read4le(pkIFile,4,m_aiSV);
00987 System::Read4le(pkIFile,1,&m_iPathLast);
00988 System::Read4le(pkIFile,1,&m_iLastFaceV0);
00989 System::Read4le(pkIFile,1,&m_iLastFaceV1);
00990 System::Read4le(pkIFile,1,&m_iLastFaceV2);
00991 System::Read4le(pkIFile,1,&m_iLastFaceOpposite);
00992 System::Read4le(pkIFile,1,&m_iLastFaceOppositeIndex);
00993 System::Read4le(pkIFile,m_iSimplexQuantity+1,m_aiPath);
00994
00995 size_t uiSize = sizeof(Real);
00996 int iVQ = 3*m_iVertexQuantity, iSVQ = 3*(m_iVertexQuantity + 4);
00997 if (uiSize == 4)
00998 {
00999 System::Read4le(pkIFile,iVQ,m_akVertex);
01000 System::Read4le(pkIFile,iSVQ,m_akSVertex);
01001 System::Read4le(pkIFile,3,(Real*)m_kMin);
01002 System::Read4le(pkIFile,1,&m_fScale);
01003 System::Read4le(pkIFile,3,(Real*)m_kLineOrigin);
01004 System::Read4le(pkIFile,3,(Real*)m_kLineDirection);
01005 System::Read4le(pkIFile,3,(Real*)m_kPlaneOrigin);
01006 System::Read4le(pkIFile,3,(Real*)m_akPlaneDirection[0]);
01007 System::Read4le(pkIFile,3,(Real*)m_akPlaneDirection[1]);
01008 }
01009 else
01010 {
01011 System::Read8le(pkIFile,iVQ,m_akVertex);
01012 System::Read8le(pkIFile,iSVQ,m_akSVertex);
01013 System::Read8le(pkIFile,3,(Real*)m_kMin);
01014 System::Read8le(pkIFile,1,&m_fScale);
01015 System::Read8le(pkIFile,3,(Real*)m_kLineOrigin);
01016 System::Read8le(pkIFile,3,(Real*)m_kLineDirection);
01017 System::Read8le(pkIFile,3,(Real*)m_kPlaneOrigin);
01018 System::Read8le(pkIFile,3,(Real*)m_akPlaneDirection[0]);
01019 System::Read8le(pkIFile,3,(Real*)m_akPlaneDirection[1]);
01020 }
01021
01022 System::Fclose(pkIFile);
01023
01024 switch (m_eQueryType)
01025 {
01026 case Query::QT_INT64:
01027 m_pkQuery = WM4_NEW Query3Int64<Real>(m_iVertexQuantity,m_akSVertex);
01028 break;
01029 case Query::QT_INTEGER:
01030 m_pkQuery = WM4_NEW Query3TInteger<Real>(m_iVertexQuantity,
01031 m_akSVertex);
01032 break;
01033 case Query::QT_RATIONAL:
01034 m_pkQuery = WM4_NEW Query3TRational<Real>(m_iVertexQuantity,
01035 m_akSVertex);
01036 break;
01037 case Query::QT_REAL:
01038 m_pkQuery = WM4_NEW Query3<Real>(m_iVertexQuantity,m_akSVertex);
01039 break;
01040 case Query::QT_FILTERED:
01041 m_pkQuery = WM4_NEW Query3Filtered<Real>(m_iVertexQuantity,
01042 m_akSVertex,m_fEpsilon);
01043 break;
01044 }
01045
01046 return true;
01047 }
01048
01049 template <class Real>
01050 bool Delaunay3<Real>::Save (const char* acFilename) const
01051 {
01052 FILE* pkOFile = System::Fopen(acFilename,"wb");
01053 if (!pkOFile)
01054 {
01055 return false;
01056 }
01057
01058 Delaunay<Real>::Save(pkOFile);
01059
01060 System::Write4le(pkOFile,1,&m_iUniqueVertexQuantity);
01061 System::Write4le(pkOFile,4,m_aiSV);
01062 System::Write4le(pkOFile,1,&m_iPathLast);
01063 System::Write4le(pkOFile,1,&m_iLastFaceV0);
01064 System::Write4le(pkOFile,1,&m_iLastFaceV1);
01065 System::Write4le(pkOFile,1,&m_iLastFaceV2);
01066 System::Write4le(pkOFile,1,&m_iLastFaceOpposite);
01067 System::Write4le(pkOFile,1,&m_iLastFaceOppositeIndex);
01068 System::Write4le(pkOFile,m_iSimplexQuantity+1,m_aiPath);
01069
01070 size_t uiSize = sizeof(Real);
01071 int iVQ = 3*m_iVertexQuantity, iSVQ = 3*(m_iVertexQuantity + 4);
01072 if (uiSize == 4)
01073 {
01074 System::Write4le(pkOFile,iVQ,m_akVertex);
01075 System::Write4le(pkOFile,iSVQ,m_akSVertex);
01076 System::Write4le(pkOFile,3,(const Real*)m_kMin);
01077 System::Write4le(pkOFile,1,&m_fScale);
01078 System::Write4le(pkOFile,3,(const Real*)m_kLineOrigin);
01079 System::Write4le(pkOFile,3,(const Real*)m_kLineDirection);
01080 System::Write4le(pkOFile,3,(const Real*)m_kPlaneOrigin);
01081 System::Write4le(pkOFile,3,(const Real*)m_akPlaneDirection[0]);
01082 System::Write4le(pkOFile,3,(const Real*)m_akPlaneDirection[1]);
01083 }
01084 else
01085 {
01086 System::Write8le(pkOFile,iVQ,m_akVertex);
01087 System::Write8le(pkOFile,iSVQ,m_akSVertex);
01088 System::Write8le(pkOFile,3,(const Real*)m_kMin);
01089 System::Write8le(pkOFile,1,&m_fScale);
01090 System::Write8le(pkOFile,3,(const Real*)m_kLineOrigin);
01091 System::Write8le(pkOFile,3,(const Real*)m_kLineDirection);
01092 System::Write8le(pkOFile,3,(const Real*)m_kPlaneOrigin);
01093 System::Write8le(pkOFile,3,(const Real*)m_akPlaneDirection[0]);
01094 System::Write8le(pkOFile,3,(const Real*)m_akPlaneDirection[1]);
01095 }
01096
01097 System::Fclose(pkOFile);
01098 return true;
01099 }
01100
01101
01102
01103
01104
01105 template WM4_FOUNDATION_ITEM
01106 class Delaunay3<float>;
01107
01108 template WM4_FOUNDATION_ITEM
01109 class Delaunay3<double>;
01110
01111 }