00001
00015 #ifndef MDS_DELAUNAYTETRA_H
00016 #define MDS_DELAUNAYTETRA_H
00017
00018 #include "mdsTetraData.h"
00019
00020
00021 #include <MDSTk/Base/mdsGlobalLog.h>
00022 #include <MDSTk/Base/mdsSharedPtr.h>
00023 #include <MDSTk/Math/mdsRandom.h>
00024 #include <MDSTk/Module/mdsSerialization.h>
00025
00026
00027 #include <VectorEntity/mctetras.h>
00028
00029
00030 #include <vector>
00031
00032
00033 namespace mds
00034 {
00035 namespace seg
00036 {
00037
00038
00039
00040
00041
00042
00044
00045
00046
00047
00049
00050
00051
00052
00054 #ifndef MDS_CHECK_MIN_EDGE_LENGTH
00055 # define MDS_CHECK_MIN_EDGE_LENGTH
00056 #endif
00057
00058
00059
00063 class CDelaunayTetra : public mds::base::CObject, public mds::mod::CSerializable
00064 {
00065 public:
00068 MDS_SHAREDPTR(CDelaunayTetra);
00069
00071 MDS_ENTITY_NAME("DelaunayTetra");
00072
00074 MDS_ENTITY_COMPRESSION(mds::mod::CC_RAW);
00075
00077 MDS_ENTITY_BLOCK_SIZE(4096);
00078
00080 static const mds::tSize DEFAULT_NUMBER_OF_NODES;
00081
00083 static const double DEFAULT_MIN_EDGE_LENGTH;
00084
00086 static const double DEFAULT_MIN_DIHEDRAL_ANGLE;
00087
00089 static const double MAX_MOVEMENT;
00090
00092 enum
00093 {
00094 XMIN_BOUNDARY = 1 << 4,
00095 YMIN_BOUNDARY = 1 << 5,
00096 ZMIN_BOUNDARY = 1 << 6,
00097 XMAX_BOUNDARY = 1 << 7,
00098 YMAX_BOUNDARY = 1 << 8,
00099 ZMAX_BOUNDARY = 1 << 9,
00100 BOUNDARY_FLAGS = XMIN_BOUNDARY | YMIN_BOUNDARY | ZMIN_BOUNDARY
00101 | XMAX_BOUNDARY | YMAX_BOUNDARY | ZMAX_BOUNDARY,
00102 };
00103
00105 typedef void (*tTetrahedronFunc)(vctl::MCTetra *pTetrahedron, CDelaunayTetra *pMesh);
00106
00108 typedef bool (*tMinEdgeLengthFunc)(vctl::MCPoint3D *p1, vctl::MCPoint3D *p2, CDelaunayTetra *pMesh);
00109
00111 typedef bool (*tConstraintFunc)(vctl::MCPoint3D *p1, vctl::MCPoint3D *p2, vctl::MCPoint3D *p3, CDelaunayTetra *pMesh);
00112
00113 public:
00115 CDelaunayTetra();
00116
00118 virtual ~CDelaunayTetra() { clear(); }
00119
00121 double getMinEdgeLength() { return m_dMinEdgeLength; }
00122
00124 void setMinEdgeLength(double dValue = DEFAULT_MIN_EDGE_LENGTH)
00125 {
00126 MDS_CHECK(dValue > 0.0, return);
00127
00128 m_dMinEdgeLength = dValue;
00129 }
00130
00132 double getMinDihedralAngle() { return m_dMinDihedralAngle; }
00133
00135 void setMinDihedralAngle(double dValue = DEFAULT_MIN_DIHEDRAL_ANGLE)
00136 {
00137 MDS_CHECK(dValue > 0.0, return);
00138
00139 m_dMinDihedralAngle = dValue;
00140 }
00141
00143 void setMinEdgeLengthFunc(tMinEdgeLengthFunc MinEdgeLengthFunc)
00144 {
00145 MDS_CHECK(MinEdgeLengthFunc, return);
00146
00147 m_MinEdgeLengthFunc = MinEdgeLengthFunc;
00148 }
00149
00151 void setDefaultMinEdgeLengthFunc() { m_MinEdgeLengthFunc = checkMinEdgeLengthFunc; }
00152
00153
00155 void setConstraintFunc(tConstraintFunc ConstraintFunc)
00156 {
00157 MDS_CHECK(ConstraintFunc, return);
00158
00159 m_ConstraintFunc = ConstraintFunc;
00160 }
00161
00163 void setDefaultConstraintFunc() { m_ConstraintFunc = checkConstraintFunc; }
00164
00165
00167 virtual bool attractVertex(vctl::MCPoint3D *pPoint);
00168
00170 vctl::MCVertex *newVertex(vctl::MCPoint3D *pPoint, int iFlags = 0)
00171 {
00172 vctl::MCVertex *pVertex = m_pVertices->New(pPoint->GetX(),
00173 pPoint->GetY(),
00174 pPoint->GetZ()
00175 );
00176 pVertex->SetFlag(iFlags);
00177 return pVertex;
00178 }
00179
00181 vctl::MCVertex *newVertex(double x, double y, double z, int iFlags = 0)
00182 {
00183 vctl::MCVertex *pVertex = m_pVertices->New(x, y, z);
00184 pVertex->SetFlag(iFlags);
00185 return pVertex;
00186 }
00187
00189 vctl::MCVertex *randomVertex(vctl::MCPoint3D *pPoint, double dMax = MAX_MOVEMENT)
00190 {
00191 return randomVertex(pPoint->GetX(), pPoint->GetY(), pPoint->GetZ(), dMax);
00192 }
00193
00195 vctl::MCVertex *randomVertex(double x, double y, double z, double dMax = MAX_MOVEMENT);
00196
00197
00199 vctl::MCVerticeS *getVertices() { return m_pVertices; }
00200
00202 int getNumOfVertices() { return m_pVertices->GetNumber(); }
00203
00206 vctl::MCVertex *getFirstVertex() { return (vctl::MCVertex *)m_pVertices->GetFirst(); }
00207
00209 vctl::MCTetraS *getTetrahedra() { return &m_Tetrahedra; }
00210
00212 int getNumOfTetrahedra() { return m_Tetrahedra.GetNumber(); }
00213
00216 vctl::MCTetra *getFirstTetrahedron() { return (vctl::MCTetra *)m_Tetrahedra.GetFirst(); }
00217
00218
00220 template <class Function>
00221 inline Function forEachVertex(Function Func)
00222 {
00223 vctl::MCVertex *pVertex = getFirstVertex();
00224 while( pVertex )
00225 {
00226 Func(*pVertex);
00227 pVertex = pVertex->GetNext();
00228 }
00229 return Func;
00230 }
00231
00233 template <class Function>
00234 inline Function forEachTetrahedron(Function Func)
00235 {
00236 vctl::MCTetra *pTetrahedron = getFirstTetrahedron();
00237 while( pTetrahedron )
00238 {
00239 Func(*pTetrahedron);
00240 pTetrahedron = pTetrahedron->GetNext();
00241 }
00242 return Func;
00243 }
00244
00245
00250 bool init(vctl::MCPoint3D *pMin,
00251 vctl::MCPoint3D *pMax,
00252 mds::tSize NumOfNodes = DEFAULT_NUMBER_OF_NODES
00253 );
00254
00259 bool construct();
00260
00265 bool addVertex(vctl::MCVertex *pVertex,
00266 int iBoundaryVertex = 0,
00267 tTetrahedronFunc InsertFunc = NULL,
00268 tTetrahedronFunc RemoveFunc = NULL
00269 );
00270
00274 bool optimizeByVertexAdding(double dMinQuality, bool bRandomPosition = true);
00275
00277 void clear();
00278
00279
00281 bool getMinCoordinates(double& dX, double& dY, double& dZ);
00282
00284 bool getMaxCoordinates(double& dX, double& dY, double& dZ);
00285
00286
00288 template <class S>
00289 void serialize(mds::mod::CChannelSerializer<S>& Writer)
00290 {
00291
00292
00293
00294
00295 m_Tetrahedra.serialize(Writer);
00296 }
00297
00299 template <class S>
00300 void deserialize(mds::mod::CChannelSerializer<S>& Reader)
00301 {
00302
00303 clear();
00304
00305
00306 m_Tetrahedra.deserialize(Reader);
00307
00308
00309 vctl::MCTetra *pTetra = getFirstTetrahedron();
00310 for( ; pTetra; pTetra = pTetra->GetNext() )
00311 {
00312
00313 STetrahedronInfo *pInfo = new STetrahedronInfo;
00314 pTetra->SetValuePtr(pInfo);
00315
00316
00317 vctl::MCVertex *pVertices[4];
00318 pTetra->GetVerticeS(pVertices);
00319
00320
00321 try {
00322 pInfo->Circumsphere.MakeSphereTetra(pVertices[0], pVertices[1], pVertices[2], pVertices[3]);
00323 }
00324 catch( ... )
00325 {
00326
00327 MDS_LOG_NOTE("CDelaunayTetra::deserialize(): Failed to compute tetrahedron circumsphere!");
00328 continue;
00329 }
00330 }
00331
00332
00333 getMinCoordinates(m_dMinX, m_dMinY, m_dMinZ);
00334 getMaxCoordinates(m_dMaxX, m_dMaxY, m_dMaxZ);
00335 }
00336
00337 protected:
00339 typedef std::vector<vctl::MCTetra *> tTetrahedra;
00340
00342 typedef std::vector<vctl::MCVertex *> tVertices;
00343
00344 protected:
00346 vctl::MCTetraS m_Tetrahedra;
00347
00350 vctl::MCVerticeS *m_pVertices;
00351
00353 mds::math::CUniformPRNG m_Random;
00354
00356 double m_dMinX, m_dMinY, m_dMinZ;
00357
00359 double m_dMaxX, m_dMaxY, m_dMaxZ;
00360
00362 double m_dMinEdgeLength;
00363
00365 double m_dMinDihedralAngle;
00366
00368 tMinEdgeLengthFunc m_MinEdgeLengthFunc;
00369
00371 tConstraintFunc m_ConstraintFunc;
00372
00373 protected:
00378 vctl::MCTetra *addTetrahedron(vctl::MCVertex *pV0,
00379 vctl::MCVertex *pV1,
00380 vctl::MCVertex *pV2,
00381 vctl::MCVertex *pV3
00382 );
00383
00385 void removeTetrahedron(vctl::MCTetra *pTetrahedron, bool bEraseVertices = false);
00386
00389 bool checkFlatness(vctl::MCVertex *pV0,
00390 vctl::MCVertex *pV1,
00391 vctl::MCVertex *pV2,
00392 vctl::MCVertex *pV3
00393 );
00394
00397 bool checkTetrahedron(vctl::MCTetra *pTetrahedron);
00398
00402 int checkBoundary(vctl::MCPoint3D *pPoint);
00403
00407 vctl::MCTetra *findBaseTetrahedron(vctl::MCPoint3D *pPoint);
00408
00415 bool findCavity(vctl::MCPoint3D *pPoint, tTetrahedra& Cavity);
00416
00422 bool findCavityEnvelope(const tTetrahedra& Cavity, tVertices& Envelope);
00423
00425 void clearFlags();
00426
00428 void clearFlags(const tTetrahedra& Tetrahedra);
00429
00433 static double getTetrahedronQuality(vctl::MCTetra *pTetrahedron);
00434
00437 vctl::MCVertex *findNearestVertex(vctl::MCPoint3D *pPoint, bool bStartFromPrevious = false);
00438
00439 private:
00441 vctl::MCTetra *findBaseTetrahedron(vctl::MCPoint3D *pPoint,
00442 vctl::MCTetra *pTetrahedron
00443 );
00444
00447 vctl::MCTetra *findBaseTetrahedronBruteForce(vctl::MCPoint3D *pPoint);
00448
00452 bool findCavity(vctl::MCPoint3D *pPoint,
00453 tTetrahedra& Cavity,
00454 vctl::MCTetra *pTetrahedron
00455 );
00456
00459 bool findBase(vctl::MCPoint3D *pPoint,
00460 tTetrahedra& Base,
00461 vctl::MCTetra *pTetrahedron
00462 );
00463
00468 bool findCavityFromBase(vctl::MCPoint3D *pPoint,
00469 tTetrahedra& Cavity,
00470 const tTetrahedra& Base
00471 );
00472
00473 private:
00475 static void normInsertFunc(vctl::MCTetra *pTetrahedron, CDelaunayTetra* pMesh);
00476
00478 static void normRemoveFunc(vctl::MCTetra *pTetrahedron, CDelaunayTetra* pMesh);
00479
00482 static bool checkMinEdgeLengthFunc(vctl::MCPoint3D *p1,
00483 vctl::MCPoint3D *p2,
00484 CDelaunayTetra* pMesh
00485 );
00486
00488 static bool checkConstraintFunc(vctl::MCPoint3D *p1,
00489 vctl::MCPoint3D *p2,
00490 vctl::MCPoint3D *p3,
00491 CDelaunayTetra* pMesh
00492 );
00493 };
00494
00495
00496
00497
00498
00499
00500
00501
00503 typedef CDelaunayTetra::tSmartPtr CDelaunayTetraPtr;
00504
00505
00506 }
00507 }
00508
00509 #endif // MDS_DELAUNAYTETRA_H
00510