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 # include <algorithm>
00028 # include <utility>
00029 # include <queue>
00030 #endif
00031
00032 #include <Mod/Mesh/App/WildMagic4/Wm4MeshCurvature.h>
00033 #include <Mod/Mesh/App/WildMagic4/Wm4Vector3.h>
00034
00035 #include "TopoAlgorithm.h"
00036 #include "Iterator.h"
00037 #include "MeshKernel.h"
00038 #include "Algorithm.h"
00039 #include "Evaluation.h"
00040 #include "Triangulation.h"
00041 #include <Base/Console.h>
00042
00043 using namespace MeshCore;
00044
00045 MeshTopoAlgorithm::MeshTopoAlgorithm (MeshKernel &rclM)
00046 : _rclMesh(rclM), _needsCleanup(false), _cache(0)
00047 {
00048 }
00049
00050 MeshTopoAlgorithm::~MeshTopoAlgorithm (void)
00051 {
00052 if ( _needsCleanup )
00053 Cleanup();
00054 EndCache();
00055 }
00056
00057 bool MeshTopoAlgorithm::InsertVertex(unsigned long ulFacetPos, const Base::Vector3f& rclPoint)
00058 {
00059 MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];
00060 MeshFacet clNewFacet1, clNewFacet2;
00061
00062
00063 unsigned long ulPtCnt = _rclMesh._aclPointArray.size();
00064 unsigned long ulPtInd = this->GetOrAddIndex(rclPoint);
00065 unsigned long ulSize = _rclMesh._aclFacetArray.size();
00066
00067 if ( ulPtInd < ulPtCnt )
00068 return false;
00069
00070
00071
00072
00073 clNewFacet1._aulPoints[0] = rclF._aulPoints[1];
00074 clNewFacet1._aulPoints[1] = rclF._aulPoints[2];
00075 clNewFacet1._aulPoints[2] = ulPtInd;
00076 clNewFacet1._aulNeighbours[0] = rclF._aulNeighbours[1];
00077 clNewFacet1._aulNeighbours[1] = ulSize+1;
00078 clNewFacet1._aulNeighbours[2] = ulFacetPos;
00079
00080 clNewFacet2._aulPoints[0] = rclF._aulPoints[2];
00081 clNewFacet2._aulPoints[1] = rclF._aulPoints[0];
00082 clNewFacet2._aulPoints[2] = ulPtInd;
00083 clNewFacet2._aulNeighbours[0] = rclF._aulNeighbours[2];
00084 clNewFacet2._aulNeighbours[1] = ulFacetPos;
00085 clNewFacet2._aulNeighbours[2] = ulSize;
00086
00087 if (rclF._aulNeighbours[1] != ULONG_MAX)
00088 _rclMesh._aclFacetArray[rclF._aulNeighbours[1]].ReplaceNeighbour(ulFacetPos, ulSize);
00089 if (rclF._aulNeighbours[2] != ULONG_MAX)
00090 _rclMesh._aclFacetArray[rclF._aulNeighbours[2]].ReplaceNeighbour(ulFacetPos, ulSize+1);
00091
00092 rclF._aulPoints[2] = ulPtInd;
00093 rclF._aulNeighbours[1] = ulSize;
00094 rclF._aulNeighbours[2] = ulSize+1;
00095
00096
00097 _rclMesh._aclFacetArray.push_back(clNewFacet1);
00098 _rclMesh._aclFacetArray.push_back(clNewFacet2);
00099
00100 return true;
00101 }
00102
00103 bool MeshTopoAlgorithm::SnapVertex(unsigned long ulFacetPos, const Base::Vector3f& rP)
00104 {
00105 MeshFacet& rFace = _rclMesh._aclFacetArray[ulFacetPos];
00106 if (!rFace.HasOpenEdge())
00107 return false;
00108 Base::Vector3f cNo1 = _rclMesh.GetNormal(rFace);
00109 for (short i=0; i<3; i++)
00110 {
00111 if (rFace._aulNeighbours[i]==ULONG_MAX)
00112 {
00113 const Base::Vector3f& rPt1 = _rclMesh._aclPointArray[rFace._aulPoints[i]];
00114 const Base::Vector3f& rPt2 = _rclMesh._aclPointArray[rFace._aulPoints[(i+1)%3]];
00115 Base::Vector3f cNo2 = (rPt2 - rPt1) % cNo1;
00116 Base::Vector3f cNo3 = (rP - rPt1) % (rPt2 - rPt1);
00117 float fD2 = Base::DistanceP2(rPt1, rPt2);
00118 float fTV = (rP-rPt1) * (rPt2-rPt1);
00119
00120
00121 if ( cNo3.Length() < FLOAT_EPS )
00122 {
00123 unsigned long uCt = _rclMesh.CountFacets();
00124 SplitOpenEdge(ulFacetPos, i, rP);
00125 return uCt < _rclMesh.CountFacets();
00126 }
00127 else if ( (rP - rPt1)*cNo2 > 0.0f && fD2 >= fTV && fTV >= 0.0f )
00128 {
00129 MeshFacet cTria;
00130 cTria._aulPoints[0] = this->GetOrAddIndex(rP);
00131 cTria._aulPoints[1] = rFace._aulPoints[(i+1)%3];
00132 cTria._aulPoints[2] = rFace._aulPoints[i];
00133 cTria._aulNeighbours[1] = ulFacetPos;
00134 rFace._aulNeighbours[i] = _rclMesh.CountFacets();
00135 _rclMesh._aclFacetArray.push_back(cTria);
00136 return true;
00137 }
00138 }
00139 }
00140
00141 return false;
00142 }
00143
00144 void MeshTopoAlgorithm::OptimizeTopology(float fMaxAngle)
00145 {
00146
00147
00148 std::map<std::pair<unsigned long, unsigned long>, std::vector<unsigned long> > aEdge2Face;
00149 for (MeshFacetArray::_TIterator pI = _rclMesh._aclFacetArray.begin(); pI != _rclMesh._aclFacetArray.end(); pI++)
00150 {
00151 for (int i = 0; i < 3; i++)
00152 {
00153
00154 if ( pI->_aulNeighbours[i] != ULONG_MAX ) {
00155 unsigned long ulPt0 = std::min<unsigned long>(pI->_aulPoints[i], pI->_aulPoints[(i+1)%3]);
00156 unsigned long ulPt1 = std::max<unsigned long>(pI->_aulPoints[i], pI->_aulPoints[(i+1)%3]);
00157 aEdge2Face[std::pair<unsigned long, unsigned long>(ulPt0, ulPt1)].push_back(pI - _rclMesh._aclFacetArray.begin());
00158 }
00159 }
00160 }
00161
00162
00163 std::list<std::pair<unsigned long, unsigned long> > aEdgeList;
00164 std::map<std::pair<unsigned long, unsigned long>, std::vector<unsigned long> >::iterator pE;
00165 for (pE = aEdge2Face.begin(); pE != aEdge2Face.end(); ++pE) {
00166 if (pE->second.size() == 2)
00167 aEdgeList.push_back(pE->first);
00168 }
00169
00170
00171 unsigned long uMaxIter = 5 * aEdge2Face.size();
00172
00173
00174 while ( !aEdgeList.empty() && uMaxIter > 0 ) {
00175
00176 std::pair<unsigned long, unsigned long> aEdge = aEdgeList.front();
00177 aEdgeList.pop_front();
00178 uMaxIter--;
00179
00180
00181 pE = aEdge2Face.find( aEdge );
00182
00183
00184 if ( pE == aEdge2Face.end() )
00185 continue;
00186
00187
00188 if ( !ShouldSwapEdge(pE->second[0], pE->second[1], fMaxAngle) )
00189 continue;
00190
00191
00192 if ( true ) {
00193
00194 SwapEdge(pE->second[0], pE->second[1]);
00195
00196 MeshFacet& rF1 = _rclMesh._aclFacetArray[pE->second[0]];
00197 MeshFacet& rF2 = _rclMesh._aclFacetArray[pE->second[1]];
00198 unsigned short side1 = rF1.Side(aEdge.first, aEdge.second);
00199 unsigned short side2 = rF2.Side(aEdge.first, aEdge.second);
00200
00201
00202 for ( int i=0; i<3; i++ ) {
00203 std::map<std::pair<unsigned long, unsigned long>, std::vector<unsigned long> >::iterator it;
00204
00205 unsigned long ulPt0 = std::min<unsigned long>(rF1._aulPoints[i], rF1._aulPoints[(i+1)%3]);
00206 unsigned long ulPt1 = std::max<unsigned long>(rF1._aulPoints[i], rF1._aulPoints[(i+1)%3]);
00207 it = aEdge2Face.find( std::make_pair(ulPt0, ulPt1) );
00208 if ( it != aEdge2Face.end() ) {
00209 if ( it->second[0] == pE->second[1] )
00210 it->second[0] = pE->second[0];
00211 else if ( it->second[1] == pE->second[1] )
00212 it->second[1] = pE->second[0];
00213 aEdgeList.push_back( it->first );
00214 }
00215
00216
00217 ulPt0 = std::min<unsigned long>(rF2._aulPoints[i], rF2._aulPoints[(i+1)%3]);
00218 ulPt1 = std::max<unsigned long>(rF2._aulPoints[i], rF2._aulPoints[(i+1)%3]);
00219 it = aEdge2Face.find( std::make_pair(ulPt0, ulPt1) );
00220 if ( it != aEdge2Face.end() ) {
00221 if ( it->second[0] == pE->second[0] )
00222 it->second[0] = pE->second[1];
00223 else if ( it->second[1] == pE->second[0] )
00224 it->second[1] = pE->second[1];
00225 aEdgeList.push_back( it->first );
00226 }
00227 }
00228
00229
00230 unsigned long ulPt0 = std::min<unsigned long>(rF1._aulPoints[(side1+1)%3], rF2._aulPoints[(side2+1)%3]);
00231 unsigned long ulPt1 = std::max<unsigned long>(rF1._aulPoints[(side1+1)%3], rF2._aulPoints[(side2+1)%3]);
00232 std::pair<unsigned long, unsigned long> aNewEdge = std::make_pair(ulPt0, ulPt1);
00233 aEdge2Face[aNewEdge] = pE->second;
00234 aEdge2Face.erase(pE);
00235 }
00236 }
00237 }
00238
00239
00240 static float cos_maxangle(const Base::Vector3f &v1,
00241 const Base::Vector3f &v2,
00242 const Base::Vector3f &v3)
00243 {
00244 float a = Base::Distance(v2,v3);
00245 float b = Base::Distance(v3,v1);
00246 float c = Base::Distance(v1,v2);
00247 float A = a * (b*b + c*c - a*a);
00248 float B = b * (c*c + a*a - b*b);
00249 float C = c * (a*a + b*b - c*c);
00250 return 0.5f * std::min<float>(std::min<float>(A,B),C) / (a*b*c);
00251 }
00252
00253 static float swap_benefit(const Base::Vector3f &v1, const Base::Vector3f &v2,
00254 const Base::Vector3f &v3, const Base::Vector3f &v4)
00255 {
00256 Base::Vector3f n124 = (v4 - v2) % (v1 - v2);
00257 Base::Vector3f n234 = (v3 - v2) % (v4 - v2);
00258 if ((n124 * n234) <= 0.0f)
00259 return 0.0f;
00260
00261 return std::max<float>(-cos_maxangle(v1,v2,v3), -cos_maxangle(v1,v3,v4)) -
00262 std::max<float>(-cos_maxangle(v1,v2,v4), -cos_maxangle(v2,v3,v4));
00263 }
00264
00265 float MeshTopoAlgorithm::SwapEdgeBenefit(unsigned long f, int e) const
00266 {
00267 const MeshFacetArray& faces = _rclMesh.GetFacets();
00268 const MeshPointArray& vertices = _rclMesh.GetPoints();
00269
00270 unsigned long n = faces[f]._aulNeighbours[e];
00271 if (n == ULONG_MAX)
00272 return 0.0f;
00273
00274 unsigned long v1 = faces[f]._aulPoints[e];
00275 unsigned long v2 = faces[f]._aulPoints[(e+1)%3];
00276 unsigned long v3 = faces[f]._aulPoints[(e+2)%3];
00277 unsigned short s = faces[n].Side(faces[f]);
00278 if (s == USHRT_MAX) {
00279 std::cerr << "MeshTopoAlgorithm::SwapEdgeBenefit: error in neighbourhood "
00280 << "of faces " << f << " and " << n << std::endl;
00281 return 0.0f;
00282 }
00283 unsigned long v4 = faces[n]._aulPoints[(s+2)%3];
00284 if (v3 == v4) {
00285 std::cerr << "MeshTopoAlgorithm::SwapEdgeBenefit: duplicate faces "
00286 << f << " and " << n << std::endl;
00287 return 0.0f;
00288 }
00289 return swap_benefit(vertices[v2], vertices[v3],
00290 vertices[v1], vertices[v4]);
00291 }
00292
00293 typedef std::pair<unsigned long,int> FaceEdge;
00294 typedef std::pair<float, FaceEdge> FaceEdgePriority;
00295
00296 void MeshTopoAlgorithm::OptimizeTopology()
00297 {
00298
00299
00300 const MeshFacetArray& faces = _rclMesh.GetFacets();
00301 unsigned long nf = _rclMesh.CountFacets();
00302 std::priority_queue<FaceEdgePriority> todo;
00303 for (unsigned long i = 0; i < nf; i++) {
00304 for (int j = 0; j < 3; j++) {
00305 float b = SwapEdgeBenefit(i, j);
00306 if (b > 0.0f)
00307 todo.push(std::make_pair(b, std::make_pair(i, j)));
00308 }
00309 }
00310
00311
00312 while (!todo.empty()) {
00313 unsigned long f = todo.top().second.first;
00314 int e = todo.top().second.second;
00315 todo.pop();
00316
00317 if (SwapEdgeBenefit(f, e) <= 0.0f)
00318 continue;
00319
00320 unsigned long f2 = faces[f]._aulNeighbours[e];
00321 SwapEdge(f, f2);
00322
00323 for (int j = 0; j < 3; j++) {
00324 float b = SwapEdgeBenefit(f, j);
00325 if (b > 0.0f)
00326 todo.push(std::make_pair(b, std::make_pair(f, j)));
00327 }
00328 for (int j = 0; j < 3; j++) {
00329 float b = SwapEdgeBenefit(f2, j);
00330 if (b > 0.0f)
00331 todo.push(std::make_pair(b, std::make_pair(f2, j)));
00332 }
00333 }
00334 }
00335
00336 void MeshTopoAlgorithm::DelaunayFlip(float fMaxAngle)
00337 {
00338
00339 std::set<std::pair<unsigned long, unsigned long> > aEdge2Face;
00340 unsigned long index = 0;
00341 for (MeshFacetArray::_TIterator pI = _rclMesh._aclFacetArray.begin(); pI != _rclMesh._aclFacetArray.end(); pI++, index++) {
00342 for (int i = 0; i < 3; i++) {
00343
00344 if (pI->_aulNeighbours[i] != ULONG_MAX) {
00345 unsigned long ulFt0 = std::min<unsigned long>(index, pI->_aulNeighbours[i]);
00346 unsigned long ulFt1 = std::max<unsigned long>(index, pI->_aulNeighbours[i]);
00347 aEdge2Face.insert(std::pair<unsigned long, unsigned long>(ulFt0, ulFt1));
00348 }
00349 }
00350 }
00351
00352 Base::Vector3f center;
00353 while (!aEdge2Face.empty()) {
00354 std::set<std::pair<unsigned long, unsigned long> >::iterator it = aEdge2Face.begin();
00355 std::pair<unsigned long, unsigned long> edge = *it;
00356 aEdge2Face.erase(it);
00357 if (ShouldSwapEdge(edge.first, edge.second, fMaxAngle)) {
00358 float radius = _rclMesh.GetFacet(edge.first).CenterOfCircumCircle(center);
00359 radius *= radius;
00360 const MeshFacet& face_1 = _rclMesh._aclFacetArray[edge.first];
00361 const MeshFacet& face_2 = _rclMesh._aclFacetArray[edge.second];
00362 unsigned short side = face_2.Side(edge.first);
00363 Base::Vector3f vertex = _rclMesh.GetPoint(face_2._aulPoints[(side+1)%3]);
00364 if (Base::DistanceP2(center, vertex) < radius) {
00365 SwapEdge(edge.first, edge.second);
00366 for (int i=0; i<3; i++) {
00367 if (face_1._aulNeighbours[i] != ULONG_MAX && face_1._aulNeighbours[i] != edge.second) {
00368 unsigned long ulFt0 = std::min<unsigned long>(edge.first, face_1._aulNeighbours[i]);
00369 unsigned long ulFt1 = std::max<unsigned long>(edge.first, face_1._aulNeighbours[i]);
00370 aEdge2Face.insert(std::pair<unsigned long, unsigned long>(ulFt0, ulFt1));
00371 }
00372 if (face_2._aulNeighbours[i] != ULONG_MAX && face_2._aulNeighbours[i] != edge.first) {
00373 unsigned long ulFt0 = std::min<unsigned long>(edge.second, face_2._aulNeighbours[i]);
00374 unsigned long ulFt1 = std::max<unsigned long>(edge.second, face_2._aulNeighbours[i]);
00375 aEdge2Face.insert(std::pair<unsigned long, unsigned long>(ulFt0, ulFt1));
00376 }
00377 }
00378 }
00379 }
00380 }
00381 }
00382
00383 int MeshTopoAlgorithm::DelaunayFlip()
00384 {
00385 int cnt_swap=0;
00386 _rclMesh._aclFacetArray.ResetFlag(MeshFacet::TMP0);
00387 unsigned long cnt_facets = _rclMesh._aclFacetArray.size();
00388 for (unsigned long i=0;i<cnt_facets;i++) {
00389 const MeshFacet& f_face = _rclMesh._aclFacetArray[i];
00390 if (f_face.IsFlag(MeshFacet::TMP0))
00391 continue;
00392 for (int j=0;j<3;j++) {
00393 unsigned long n = f_face._aulNeighbours[j];
00394 if (n != ULONG_MAX) {
00395 const MeshFacet& n_face = _rclMesh._aclFacetArray[n];
00396 if (n_face.IsFlag(MeshFacet::TMP0))
00397 continue;
00398 unsigned short k = n_face.Side(f_face);
00399 MeshGeomFacet f1 = _rclMesh.GetFacet(f_face);
00400 MeshGeomFacet f2 = _rclMesh.GetFacet(n_face);
00401 Base::Vector3f c1, c2, p1, p2;
00402 p1 = f1._aclPoints[(j+2)%3];
00403 p2 = f2._aclPoints[(k+2)%3];
00404 float r1 = f1.CenterOfCircumCircle(c1);
00405 r1 = r1*r1;
00406 float r2 = f2.CenterOfCircumCircle(c2);
00407 r2 = r2*r2;
00408 float d1 = Base::DistanceP2(c1, p2);
00409 float d2 = Base::DistanceP2(c2, p1);
00410 if (d1 < r1 || d2 < r2) {
00411 SwapEdge(i, n);
00412 cnt_swap++;
00413 f_face.SetFlag(MeshFacet::TMP0);
00414 n_face.SetFlag(MeshFacet::TMP0);
00415 }
00416 }
00417 }
00418 }
00419
00420 return cnt_swap;
00421 }
00422
00423 void MeshTopoAlgorithm::AdjustEdgesToCurvatureDirection()
00424 {
00425 std::vector< Wm4::Vector3<float> > aPnts;
00426 MeshPointIterator cPIt( _rclMesh );
00427 aPnts.reserve(_rclMesh.CountPoints());
00428 for ( cPIt.Init(); cPIt.More(); cPIt.Next() )
00429 aPnts.push_back( Wm4::Vector3<float>( cPIt->x, cPIt->y, cPIt->z ) );
00430
00431
00432 std::vector<int> aIdx;
00433 const MeshFacetArray& raFts = _rclMesh.GetFacets();
00434 aIdx.reserve( 3*raFts.size() );
00435
00436
00437 unsigned long k = 0;
00438 std::map<std::pair<unsigned long, unsigned long>, std::list<unsigned long> > aclEdgeMap;
00439 for ( std::vector<MeshFacet>::const_iterator jt = raFts.begin(); jt != raFts.end(); ++jt, k++ )
00440 {
00441 for (int i=0; i<3; i++)
00442 {
00443 unsigned long ulT0 = jt->_aulPoints[i];
00444 unsigned long ulT1 = jt->_aulPoints[(i+1)%3];
00445 unsigned long ulP0 = std::min<unsigned long>(ulT0, ulT1);
00446 unsigned long ulP1 = std::max<unsigned long>(ulT0, ulT1);
00447 aclEdgeMap[std::make_pair<unsigned long, unsigned long>(ulP0, ulP1)].push_front(k);
00448 aIdx.push_back( (int)jt->_aulPoints[i] );
00449 }
00450 }
00451
00452
00453 Wm4::MeshCurvature<float> meshCurv(_rclMesh.CountPoints(), &(aPnts[0]), _rclMesh.CountFacets(), &(aIdx[0]));
00454
00455
00456 const Wm4::Vector3<float>* aMaxCurvDir = meshCurv.GetMaxDirections();
00457 const Wm4::Vector3<float>* aMinCurvDir = meshCurv.GetMinDirections();
00458 const float* aMaxCurv = meshCurv.GetMaxCurvatures();
00459 const float* aMinCurv = meshCurv.GetMinCurvatures();
00460
00461 raFts.ResetFlag(MeshFacet::VISIT);
00462 const MeshPointArray& raPts = _rclMesh.GetPoints();
00463 for ( std::map<std::pair<unsigned long, unsigned long>, std::list<unsigned long> >::iterator kt = aclEdgeMap.begin(); kt != aclEdgeMap.end(); ++kt )
00464 {
00465 if ( kt->second.size() == 2 ) {
00466 unsigned long uPt1 = kt->first.first;
00467 unsigned long uPt2 = kt->first.second;
00468 unsigned long uFt1 = kt->second.front();
00469 unsigned long uFt2 = kt->second.back();
00470
00471 const MeshFacet& rFace1 = raFts[uFt1];
00472 const MeshFacet& rFace2 = raFts[uFt2];
00473 if ( rFace1.IsFlag(MeshFacet::VISIT) || rFace2.IsFlag(MeshFacet::VISIT) )
00474 continue;
00475
00476 unsigned long uPt3, uPt4;
00477 unsigned short side = rFace1.Side(uPt1, uPt2);
00478 uPt3 = rFace1._aulPoints[(side+2)%3];
00479 side = rFace2.Side(uPt1, uPt2);
00480 uPt4 = rFace2._aulPoints[(side+2)%3];
00481
00482 Wm4::Vector3<float> dir;
00483 float fActCurvature;
00484 if ( fabs(aMinCurv[uPt1]) > fabs(aMaxCurv[uPt1]) ) {
00485 fActCurvature = aMinCurv[uPt1];
00486 dir = aMaxCurvDir[uPt1];
00487 } else {
00488 fActCurvature = aMaxCurv[uPt1];
00489 dir = aMinCurvDir[uPt1];
00490 }
00491
00492 Base::Vector3f cMinDir(dir.X(), dir.Y(), dir.Z());
00493 Base::Vector3f cEdgeDir1 = raPts[uPt1] - raPts[uPt2];
00494 Base::Vector3f cEdgeDir2 = raPts[uPt3] - raPts[uPt4];
00495 cMinDir.Normalize(); cEdgeDir1.Normalize(); cEdgeDir2.Normalize();
00496
00497
00498 MeshGeomFacet cPlane(raPts[uPt1], raPts[uPt2], raPts[uPt3]);
00499
00500 float fDist = raPts[uPt4].DistanceToPlane(cPlane._aclPoints[0], cPlane.GetNormal());
00501
00502 float fLength12 = Base::Distance(raPts[uPt1], raPts[uPt2]);
00503 float fLength34 = Base::Distance(raPts[uPt3], raPts[uPt4]);
00504 if ( fabs(cEdgeDir1*cMinDir) < fabs(cEdgeDir2*cMinDir) )
00505 {
00506 if ( IsSwapEdgeLegal(uFt1, uFt2) && fLength34 < 1.05f*fLength12 && fActCurvature*fDist > 0.0f) {
00507 SwapEdge(uFt1, uFt2);
00508 rFace1.SetFlag(MeshFacet::VISIT);
00509 rFace2.SetFlag(MeshFacet::VISIT);
00510 }
00511 }
00512 }
00513 }
00514 }
00515
00516 bool MeshTopoAlgorithm::InsertVertexAndSwapEdge(unsigned long ulFacetPos, const Base::Vector3f& rclPoint, float fMaxAngle)
00517 {
00518 if ( !InsertVertex(ulFacetPos, rclPoint) )
00519 return false;
00520
00521
00522 unsigned long ulF1Ind = _rclMesh._aclFacetArray.size()-2;
00523 unsigned long ulF2Ind = _rclMesh._aclFacetArray.size()-1;
00524 MeshFacet& rclF1 = _rclMesh._aclFacetArray[ulFacetPos];
00525 MeshFacet& rclF2 = _rclMesh._aclFacetArray[ulF1Ind];
00526 MeshFacet& rclF3 = _rclMesh._aclFacetArray[ulF2Ind];
00527
00528
00529 int i;
00530 for ( i=0; i<3; i++ )
00531 {
00532 unsigned long uNeighbour = rclF1._aulNeighbours[i];
00533 if ( uNeighbour!=ULONG_MAX && uNeighbour!=ulF1Ind && uNeighbour!=ulF2Ind )
00534 {
00535 if ( ShouldSwapEdge(ulFacetPos, uNeighbour, fMaxAngle) ) {
00536 SwapEdge(ulFacetPos, uNeighbour);
00537 break;
00538 }
00539 }
00540 }
00541 for ( i=0; i<3; i++ )
00542 {
00543
00544 unsigned long uNeighbour = rclF2._aulNeighbours[i];
00545 if ( uNeighbour!=ULONG_MAX && uNeighbour!=ulFacetPos && uNeighbour!=ulF2Ind )
00546 {
00547 if ( ShouldSwapEdge(ulF1Ind, uNeighbour, fMaxAngle) ) {
00548 SwapEdge(ulF1Ind, uNeighbour);
00549 break;
00550 }
00551 }
00552 }
00553
00554
00555 for ( i=0; i<3; i++ )
00556 {
00557 unsigned long uNeighbour = rclF3._aulNeighbours[i];
00558 if ( uNeighbour!=ULONG_MAX && uNeighbour!=ulFacetPos && uNeighbour!=ulF1Ind )
00559 {
00560 if ( ShouldSwapEdge(ulF2Ind, uNeighbour, fMaxAngle) ) {
00561 SwapEdge(ulF2Ind, uNeighbour);
00562 break;
00563 }
00564 }
00565 }
00566
00567 return true;
00568 }
00569
00570 bool MeshTopoAlgorithm::IsSwapEdgeLegal(unsigned long ulFacetPos, unsigned long ulNeighbour) const
00571 {
00572 MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];
00573 MeshFacet& rclN = _rclMesh._aclFacetArray[ulNeighbour];
00574
00575 unsigned short uFSide = rclF.Side(rclN);
00576 unsigned short uNSide = rclN.Side(rclF);
00577
00578 if (uFSide == USHRT_MAX || uNSide == USHRT_MAX)
00579 return false;
00580
00581 Base::Vector3f cP1 = _rclMesh._aclPointArray[rclF._aulPoints[uFSide]];
00582 Base::Vector3f cP2 = _rclMesh._aclPointArray[rclF._aulPoints[(uFSide+1)%3]];
00583 Base::Vector3f cP3 = _rclMesh._aclPointArray[rclF._aulPoints[(uFSide+2)%3]];
00584 Base::Vector3f cP4 = _rclMesh._aclPointArray[rclN._aulPoints[(uNSide+2)%3]];
00585
00586
00587 MeshGeomFacet cT3(cP4, cP3, cP1);
00588 if ( cT3.IsDegenerated() )
00589 return false;
00590 MeshGeomFacet cT4(cP3, cP4, cP2);
00591 if ( cT4.IsDegenerated() )
00592 return false;
00593
00594
00595
00596 Base::Vector3f cU = cP2-cP1;
00597 Base::Vector3f cV = cP4-cP3;
00598
00599 Base::Vector3f cN1 = (cU % cV) % cU;
00600 if ( ((cP3-cP1)*cN1)*((cP4-cP1)*cN1) >= 0.0f )
00601 return false;
00602
00603 Base::Vector3f cN2 = (cU % cV) % cV;
00604 if ( ((cP1-cP3)*cN2)*((cP2-cP3)*cN2) >= 0.0f )
00605 return false;
00606
00607 return true;
00608 }
00609
00610 bool MeshTopoAlgorithm::ShouldSwapEdge(unsigned long ulFacetPos, unsigned long ulNeighbour, float fMaxAngle) const
00611 {
00612 if ( !IsSwapEdgeLegal(ulFacetPos, ulNeighbour) )
00613 return false;
00614
00615 MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];
00616 MeshFacet& rclN = _rclMesh._aclFacetArray[ulNeighbour];
00617
00618 unsigned short uFSide = rclF.Side(rclN);
00619 unsigned short uNSide = rclN.Side(rclF);
00620
00621 Base::Vector3f cP1 = _rclMesh._aclPointArray[rclF._aulPoints[uFSide]];
00622 Base::Vector3f cP2 = _rclMesh._aclPointArray[rclF._aulPoints[(uFSide+1)%3]];
00623 Base::Vector3f cP3 = _rclMesh._aclPointArray[rclF._aulPoints[(uFSide+2)%3]];
00624 Base::Vector3f cP4 = _rclMesh._aclPointArray[rclN._aulPoints[(uNSide+2)%3]];
00625
00626 MeshGeomFacet cT1(cP1, cP2, cP3); float fMax1 = cT1.MaximumAngle();
00627 MeshGeomFacet cT2(cP2, cP1, cP4); float fMax2 = cT2.MaximumAngle();
00628 MeshGeomFacet cT3(cP4, cP3, cP1); float fMax3 = cT3.MaximumAngle();
00629 MeshGeomFacet cT4(cP3, cP4, cP2); float fMax4 = cT4.MaximumAngle();
00630
00631
00632 Base::Vector3f cN1 = cT1.GetNormal();
00633 Base::Vector3f cN2 = cT2.GetNormal();
00634 if ( cN1.GetAngle(cN2) > fMaxAngle )
00635 return false;
00636
00637 float fMax12 = std::max<float>(fMax1, fMax2);
00638 float fMax34 = std::max<float>(fMax3, fMax4);
00639
00640 return fMax12 > fMax34;
00641 }
00642
00643 void MeshTopoAlgorithm::SwapEdge(unsigned long ulFacetPos, unsigned long ulNeighbour)
00644 {
00645 MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];
00646 MeshFacet& rclN = _rclMesh._aclFacetArray[ulNeighbour];
00647
00648 unsigned short uFSide = rclF.Side(rclN);
00649 unsigned short uNSide = rclN.Side(rclF);
00650
00651 if (uFSide == USHRT_MAX || uNSide == USHRT_MAX)
00652 return;
00653
00654
00655 if (rclF._aulNeighbours[(uFSide+1)%3] != ULONG_MAX)
00656 _rclMesh._aclFacetArray[rclF._aulNeighbours[(uFSide+1)%3]].ReplaceNeighbour(ulFacetPos, ulNeighbour);
00657 if (rclN._aulNeighbours[(uNSide+1)%3] != ULONG_MAX)
00658 _rclMesh._aclFacetArray[rclN._aulNeighbours[(uNSide+1)%3]].ReplaceNeighbour(ulNeighbour, ulFacetPos);
00659
00660
00661 rclF._aulPoints[(uFSide+1)%3] = rclN._aulPoints[(uNSide+2)%3];
00662 rclN._aulPoints[(uNSide+1)%3] = rclF._aulPoints[(uFSide+2)%3];
00663 rclF._aulNeighbours[uFSide] = rclN._aulNeighbours[(uNSide+1)%3];
00664 rclN._aulNeighbours[uNSide] = rclF._aulNeighbours[(uFSide+1)%3];
00665 rclF._aulNeighbours[(uFSide+1)%3] = ulNeighbour;
00666 rclN._aulNeighbours[(uNSide+1)%3] = ulFacetPos;
00667 }
00668
00669 bool MeshTopoAlgorithm::SplitEdge(unsigned long ulFacetPos, unsigned long ulNeighbour, const Base::Vector3f& rP)
00670 {
00671 MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];
00672 MeshFacet& rclN = _rclMesh._aclFacetArray[ulNeighbour];
00673
00674 unsigned short uFSide = rclF.Side(rclN);
00675 unsigned short uNSide = rclN.Side(rclF);
00676
00677 if (uFSide == USHRT_MAX || uNSide == USHRT_MAX)
00678 return false;
00679
00680 unsigned long uPtCnt = _rclMesh._aclPointArray.size();
00681 unsigned long uPtInd = this->GetOrAddIndex(rP);
00682 unsigned long ulSize = _rclMesh._aclFacetArray.size();
00683
00684
00685
00686 if (uPtInd < uPtCnt)
00687 return false;
00688
00689
00690 if (rclF._aulNeighbours[(uFSide+1)%3] != ULONG_MAX)
00691 _rclMesh._aclFacetArray[rclF._aulNeighbours[(uFSide+1)%3]].ReplaceNeighbour(ulFacetPos, ulSize);
00692 if (rclN._aulNeighbours[(uNSide+2)%3] != ULONG_MAX)
00693 _rclMesh._aclFacetArray[rclN._aulNeighbours[(uNSide+2)%3]].ReplaceNeighbour(ulNeighbour, ulSize+1);
00694
00695 MeshFacet cNew1, cNew2;
00696 cNew1._aulPoints[0] = uPtInd;
00697 cNew1._aulPoints[1] = rclF._aulPoints[(uFSide+1)%3];
00698 cNew1._aulPoints[2] = rclF._aulPoints[(uFSide+2)%3];
00699 cNew1._aulNeighbours[0] = ulSize+1;
00700 cNew1._aulNeighbours[1] = rclF._aulNeighbours[(uFSide+1)%3];
00701 cNew1._aulNeighbours[2] = ulFacetPos;
00702
00703 cNew2._aulPoints[0] = rclN._aulPoints[uNSide];
00704 cNew2._aulPoints[1] = uPtInd;
00705 cNew2._aulPoints[2] = rclN._aulPoints[(uNSide+2)%3];
00706 cNew2._aulNeighbours[0] = ulSize;
00707 cNew2._aulNeighbours[1] = ulNeighbour;
00708 cNew2._aulNeighbours[2] = rclN._aulNeighbours[(uNSide+2)%3];
00709
00710
00711 rclF._aulPoints[(uFSide+1)%3] = uPtInd;
00712 rclF._aulNeighbours[(uFSide+1)%3] = ulSize;
00713 rclN._aulPoints[uNSide] = uPtInd;
00714 rclN._aulNeighbours[(uNSide+2)%3] = ulSize+1;
00715
00716
00717 _rclMesh._aclFacetArray.push_back(cNew1);
00718 _rclMesh._aclFacetArray.push_back(cNew2);
00719
00720 return true;
00721 }
00722
00723 void MeshTopoAlgorithm::SplitOpenEdge(unsigned long ulFacetPos, unsigned short uSide, const Base::Vector3f& rP)
00724 {
00725 MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];
00726 if (rclF._aulNeighbours[uSide] != ULONG_MAX)
00727 return;
00728
00729 unsigned long uPtCnt = _rclMesh._aclPointArray.size();
00730 unsigned long uPtInd = this->GetOrAddIndex(rP);
00731 unsigned long ulSize = _rclMesh._aclFacetArray.size();
00732
00733 if ( uPtInd < uPtCnt )
00734 return;
00735
00736
00737 if (rclF._aulNeighbours[(uSide+1)%3] != ULONG_MAX)
00738 _rclMesh._aclFacetArray[rclF._aulNeighbours[(uSide+1)%3]].ReplaceNeighbour(ulFacetPos, ulSize);
00739
00740 MeshFacet cNew;
00741 cNew._aulPoints[0] = uPtInd;
00742 cNew._aulPoints[1] = rclF._aulPoints[(uSide+1)%3];
00743 cNew._aulPoints[2] = rclF._aulPoints[(uSide+2)%3];
00744 cNew._aulNeighbours[0] = ULONG_MAX;
00745 cNew._aulNeighbours[1] = rclF._aulNeighbours[(uSide+1)%3];
00746 cNew._aulNeighbours[2] = ulFacetPos;
00747
00748
00749 rclF._aulPoints[(uSide+1)%3] = uPtInd;
00750 rclF._aulNeighbours[(uSide+1)%3] = ulSize;
00751
00752
00753 _rclMesh._aclFacetArray.push_back(cNew);
00754 }
00755
00756 bool MeshTopoAlgorithm::Vertex_Less::operator ()(const Base::Vector3f& u,
00757 const Base::Vector3f& v) const
00758 {
00759 if (fabs (u.x - v.x) > FLOAT_EPS)
00760 return u.x < v.x;
00761 if (fabs (u.y - v.y) > FLOAT_EPS)
00762 return u.y < v.y;
00763 if (fabs (u.z - v.z) > FLOAT_EPS)
00764 return u.z < v.z;
00765 return false;
00766 }
00767
00768 void MeshTopoAlgorithm::BeginCache()
00769 {
00770 if (_cache) {
00771 delete _cache;
00772 }
00773 _cache = new tCache();
00774 unsigned long nbPoints = _rclMesh._aclPointArray.size();
00775 for (unsigned int pntCpt = 0 ; pntCpt < nbPoints ; ++pntCpt) {
00776 _cache->insert(std::make_pair(_rclMesh._aclPointArray[pntCpt],pntCpt));
00777 }
00778 }
00779
00780 void MeshTopoAlgorithm::EndCache()
00781 {
00782 if (_cache) {
00783 _cache->clear();
00784 delete _cache;
00785 _cache = 0;
00786 }
00787 }
00788
00789 unsigned long MeshTopoAlgorithm::GetOrAddIndex (const MeshPoint &rclPoint)
00790 {
00791 if (!_cache)
00792 return _rclMesh._aclPointArray.GetOrAddIndex(rclPoint);
00793
00794 unsigned long sz = _rclMesh._aclPointArray.size();
00795 std::pair<tCache::iterator,bool> retval = _cache->insert(std::make_pair(rclPoint,sz));
00796 if (retval.second)
00797 _rclMesh._aclPointArray.push_back(rclPoint);
00798 return retval.first->second;
00799 }
00800
00801 std::vector<unsigned long> MeshTopoAlgorithm::GetFacetsToPoint(unsigned long uFacetPos, unsigned long uPointPos) const
00802 {
00803
00804 std::list<unsigned long> aReference;
00805 aReference.push_back(uFacetPos);
00806 std::set<unsigned long> aRefFacet;
00807 while ( !aReference.empty() )
00808 {
00809 unsigned long uIndex = aReference.front();
00810 aReference.pop_front();
00811 aRefFacet.insert(uIndex);
00812 MeshFacet& rFace = _rclMesh._aclFacetArray[uIndex];
00813 for ( int i=0; i<3; i++ ) {
00814 if ( rFace._aulPoints[i] == uPointPos ) {
00815 if ( rFace._aulNeighbours[i] != ULONG_MAX )
00816 {
00817 if ( aRefFacet.find(rFace._aulNeighbours[i]) == aRefFacet.end() )
00818 aReference.push_back( rFace._aulNeighbours[i] );
00819 }
00820 if ( rFace._aulNeighbours[(i+2)%3] != ULONG_MAX )
00821 {
00822 if ( aRefFacet.find(rFace._aulNeighbours[(i+2)%3]) == aRefFacet.end() )
00823 aReference.push_back( rFace._aulNeighbours[(i+2)%3] );
00824 }
00825 break;
00826 }
00827 }
00828 }
00829
00830
00831 std::vector<unsigned long> aRefs;
00832 aRefs.insert(aRefs.end(), aRefFacet.begin(), aRefFacet.end());
00833 return aRefs;
00834 }
00835
00836 void MeshTopoAlgorithm::Cleanup()
00837 {
00838 _rclMesh.RemoveInvalids();
00839 _needsCleanup = false;
00840 }
00841
00842 bool MeshTopoAlgorithm::CollapseEdge(unsigned long ulFacetPos, unsigned long ulNeighbour)
00843 {
00844 MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];
00845 MeshFacet& rclN = _rclMesh._aclFacetArray[ulNeighbour];
00846
00847 unsigned short uFSide = rclF.Side(rclN);
00848 unsigned short uNSide = rclN.Side(rclF);
00849
00850 if (uFSide == USHRT_MAX || uNSide == USHRT_MAX)
00851 return false;
00852
00853 if (!rclF.IsValid() || !rclN.IsValid())
00854 return false;
00855
00856
00857 unsigned long ulPointPos = rclF._aulPoints[uFSide];
00858 unsigned long ulPointNew = rclN._aulPoints[uNSide];
00859
00860
00861 std::vector<unsigned long> aRefs = GetFacetsToPoint(ulFacetPos, ulPointPos);
00862 for ( std::vector<unsigned long>::iterator it = aRefs.begin(); it != aRefs.end(); ++it )
00863 {
00864 MeshFacet& rFace = _rclMesh._aclFacetArray[*it];
00865 rFace.Transpose( ulPointPos, ulPointNew );
00866 }
00867
00868
00869 if (rclF._aulNeighbours[(uFSide+1)%3] != ULONG_MAX)
00870 _rclMesh._aclFacetArray[rclF._aulNeighbours[(uFSide+1)%3]].ReplaceNeighbour(ulFacetPos, rclF._aulNeighbours[(uFSide+2)%3]);
00871 if (rclF._aulNeighbours[(uFSide+2)%3] != ULONG_MAX)
00872 _rclMesh._aclFacetArray[rclF._aulNeighbours[(uFSide+2)%3]].ReplaceNeighbour(ulFacetPos, rclF._aulNeighbours[(uFSide+1)%3]);
00873 if (rclN._aulNeighbours[(uNSide+1)%3] != ULONG_MAX)
00874 _rclMesh._aclFacetArray[rclN._aulNeighbours[(uNSide+1)%3]].ReplaceNeighbour(ulNeighbour, rclN._aulNeighbours[(uNSide+2)%3]);
00875 if (rclN._aulNeighbours[(uNSide+2)%3] != ULONG_MAX)
00876 _rclMesh._aclFacetArray[rclN._aulNeighbours[(uNSide+2)%3]].ReplaceNeighbour(ulNeighbour, rclN._aulNeighbours[(uNSide+1)%3]);
00877
00878
00879 rclF._aulNeighbours[0] = ULONG_MAX;
00880 rclF._aulNeighbours[1] = ULONG_MAX;
00881 rclF._aulNeighbours[2] = ULONG_MAX;
00882 rclF.SetInvalid();
00883 rclN._aulNeighbours[0] = ULONG_MAX;
00884 rclN._aulNeighbours[1] = ULONG_MAX;
00885 rclN._aulNeighbours[2] = ULONG_MAX;
00886 rclN.SetInvalid();
00887 _rclMesh._aclPointArray[ulPointPos].SetInvalid();
00888
00889 _needsCleanup = true;
00890
00891 return true;
00892 }
00893
00894 bool MeshTopoAlgorithm::CollapseFacet(unsigned long ulFacetPos)
00895 {
00896 MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];
00897 if (!rclF.IsValid())
00898 return false;
00899
00900
00901 unsigned long ulPointInd0 = rclF._aulPoints[0];
00902 unsigned long ulPointInd1 = rclF._aulPoints[1];
00903 unsigned long ulPointInd2 = rclF._aulPoints[2];
00904
00905
00906 Base::Vector3f cCenter = _rclMesh.GetGravityPoint(rclF);
00907 _rclMesh._aclPointArray[ulPointInd0] = cCenter;
00908
00909
00910 std::vector<unsigned long> aRefs = GetFacetsToPoint(ulFacetPos, ulPointInd1);
00911 for (std::vector<unsigned long>::iterator it = aRefs.begin(); it != aRefs.end(); ++it) {
00912 MeshFacet& rFace = _rclMesh._aclFacetArray[*it];
00913 rFace.Transpose(ulPointInd1, ulPointInd0);
00914 }
00915
00916 aRefs = GetFacetsToPoint(ulFacetPos, ulPointInd2);
00917 for (std::vector<unsigned long>::iterator it = aRefs.begin(); it != aRefs.end(); ++it) {
00918 MeshFacet& rFace = _rclMesh._aclFacetArray[*it];
00919 rFace.Transpose(ulPointInd2, ulPointInd0);
00920 }
00921
00922
00923 for (int i=0; i<3; i++) {
00924 if (rclF._aulNeighbours[i] == ULONG_MAX)
00925 continue;
00926 MeshFacet& rclN = _rclMesh._aclFacetArray[rclF._aulNeighbours[i]];
00927 unsigned short uNSide = rclN.Side(rclF);
00928
00929 if (rclN._aulNeighbours[(uNSide+1)%3] != ULONG_MAX) {
00930 _rclMesh._aclFacetArray[rclN._aulNeighbours[(uNSide+1)%3]]
00931 .ReplaceNeighbour(rclF._aulNeighbours[i],rclN._aulNeighbours[(uNSide+2)%3]);
00932 }
00933 if (rclN._aulNeighbours[(uNSide+2)%3] != ULONG_MAX) {
00934 _rclMesh._aclFacetArray[rclN._aulNeighbours[(uNSide+2)%3]]
00935 .ReplaceNeighbour(rclF._aulNeighbours[i],rclN._aulNeighbours[(uNSide+1)%3]);
00936 }
00937
00938
00939 rclN._aulNeighbours[0] = ULONG_MAX;
00940 rclN._aulNeighbours[1] = ULONG_MAX;
00941 rclN._aulNeighbours[2] = ULONG_MAX;
00942 rclN.SetInvalid();
00943 }
00944
00945
00946 rclF._aulNeighbours[0] = ULONG_MAX;
00947 rclF._aulNeighbours[1] = ULONG_MAX;
00948 rclF._aulNeighbours[2] = ULONG_MAX;
00949 rclF.SetInvalid();
00950 _rclMesh._aclPointArray[ulPointInd1].SetInvalid();
00951 _rclMesh._aclPointArray[ulPointInd2].SetInvalid();
00952
00953 _needsCleanup = true;
00954
00955 return true;
00956 }
00957
00959 void MeshTopoAlgorithm::SplitFacet(unsigned long ulFacetPos, const Base::Vector3f& rP1, const Base::Vector3f& rP2)
00960 {
00961 float fEps = MESH_MIN_EDGE_LEN;
00962 MeshFacet& rFace = _rclMesh._aclFacetArray[ulFacetPos];
00963 MeshPoint& rVertex0 = _rclMesh._aclPointArray[rFace._aulPoints[0]];
00964 MeshPoint& rVertex1 = _rclMesh._aclPointArray[rFace._aulPoints[1]];
00965 MeshPoint& rVertex2 = _rclMesh._aclPointArray[rFace._aulPoints[2]];
00966
00967 unsigned short equalP1=USHRT_MAX, equalP2=USHRT_MAX;
00968 if ( Base::Distance(rVertex0, rP1) < fEps )
00969 equalP1=0;
00970 else if ( Base::Distance(rVertex1, rP1) < fEps )
00971 equalP1=1;
00972 else if ( Base::Distance(rVertex2, rP1) < fEps )
00973 equalP1=2;
00974 if ( Base::Distance(rVertex0, rP2) < fEps )
00975 equalP2=0;
00976 else if ( Base::Distance(rVertex1, rP2) < fEps )
00977 equalP2=1;
00978 else if ( Base::Distance(rVertex2, rP2) < fEps )
00979 equalP2=2;
00980
00981
00982 if ( equalP1 != USHRT_MAX && equalP2 != USHRT_MAX )
00983 return;
00984
00985 if ( equalP1 != USHRT_MAX )
00986 {
00987
00988 float fMinDist = FLOAT_MAX;
00989 unsigned short iEdgeNo=USHRT_MAX;
00990 for ( unsigned short i=0; i<3; i++ )
00991 {
00992 Base::Vector3f cBase(_rclMesh._aclPointArray[rFace._aulPoints[i]]);
00993 Base::Vector3f cEnd (_rclMesh._aclPointArray[rFace._aulPoints[(i+1)%3]]);
00994 Base::Vector3f cDir = cEnd - cBase;
00995
00996 float fDist = rP2.DistanceToLine(cBase, cDir);
00997 if ( fMinDist < fDist )
00998 {
00999 fMinDist = fDist;
01000 iEdgeNo = i;
01001 }
01002 }
01003 if ( fMinDist < 0.05f )
01004 {
01005 if ( rFace._aulNeighbours[iEdgeNo] != ULONG_MAX )
01006 SplitEdge(ulFacetPos, rFace._aulNeighbours[iEdgeNo], rP2);
01007 else
01008 SplitOpenEdge(ulFacetPos, iEdgeNo, rP2);
01009 }
01010 }
01011 else if ( equalP2 != USHRT_MAX )
01012 {
01013
01014 float fMinDist = FLOAT_MAX;
01015 unsigned short iEdgeNo=USHRT_MAX;
01016 for ( unsigned short i=0; i<3; i++ )
01017 {
01018 Base::Vector3f cBase(_rclMesh._aclPointArray[rFace._aulPoints[i]]);
01019 Base::Vector3f cEnd (_rclMesh._aclPointArray[rFace._aulPoints[(i+1)%3]]);
01020 Base::Vector3f cDir = cEnd - cBase;
01021
01022 float fDist = rP1.DistanceToLine(cBase, cDir);
01023 if ( fMinDist < fDist )
01024 {
01025 fMinDist = fDist;
01026 iEdgeNo = i;
01027 }
01028 }
01029 if ( fMinDist < 0.05f )
01030 {
01031 if ( rFace._aulNeighbours[iEdgeNo] != ULONG_MAX )
01032 SplitEdge(ulFacetPos, rFace._aulNeighbours[iEdgeNo], rP1);
01033 else
01034 SplitOpenEdge(ulFacetPos, iEdgeNo, rP1);
01035 }
01036 }
01037 else
01038 {
01039
01040 unsigned short iEdgeNo1=USHRT_MAX, iEdgeNo2=USHRT_MAX;
01041 float fMinDist1 = FLOAT_MAX, fMinDist2 = FLOAT_MAX;
01042 const MeshFacet& rFace = _rclMesh._aclFacetArray[ulFacetPos];
01043 for ( unsigned short i=0; i<3; i++ )
01044 {
01045 Base::Vector3f cBase(_rclMesh._aclPointArray[rFace._aulPoints[i]]);
01046 Base::Vector3f cEnd (_rclMesh._aclPointArray[rFace._aulPoints[(i+1)%3]]);
01047 Base::Vector3f cDir = cEnd - cBase;
01048
01049 float fDist = rP1.DistanceToLine(cBase, cDir);
01050 if ( fMinDist1 < fDist )
01051 {
01052 fMinDist1 = fDist;
01053 iEdgeNo1 = i;
01054 }
01055 fDist = rP2.DistanceToLine(cBase, cDir);
01056 if ( fMinDist2 < fDist )
01057 {
01058 fMinDist2 = fDist;
01059 iEdgeNo2 = i;
01060 }
01061 }
01062
01063 if ( iEdgeNo1 == iEdgeNo2 || fMinDist1 >= 0.05f || fMinDist2 >= 0.05f )
01064 return;
01065
01066
01067 Base::Vector3f cP1 = rP1;
01068 Base::Vector3f cP2 = rP2;
01069 if ( (iEdgeNo2+1)%3 == iEdgeNo1 )
01070 {
01071 unsigned short tmp = iEdgeNo1;
01072 iEdgeNo1 = iEdgeNo2;
01073 iEdgeNo2 = tmp;
01074 cP1 = rP2;
01075 cP2 = rP1;
01076 }
01077
01078
01079 if ( rFace._aulNeighbours[iEdgeNo1] != ULONG_MAX )
01080 SplitNeighbourFacet(ulFacetPos, iEdgeNo1, cP1);
01081 if ( rFace._aulNeighbours[iEdgeNo2] != ULONG_MAX )
01082 SplitNeighbourFacet(ulFacetPos, iEdgeNo2, cP1);
01083 }
01084 }
01085
01086 void MeshTopoAlgorithm::SplitNeighbourFacet(unsigned long ulFacetPos, unsigned short uFSide, const Base::Vector3f rPoint)
01087 {
01088 MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos];
01089
01090 unsigned long ulNeighbour = rclF._aulNeighbours[uFSide];
01091 MeshFacet& rclN = _rclMesh._aclFacetArray[ulNeighbour];
01092
01093 unsigned short uNSide = rclN.Side(rclF);
01094
01095
01096 unsigned long uPtInd = this->GetOrAddIndex(rPoint);
01097 unsigned long ulSize = _rclMesh._aclFacetArray.size();
01098
01099
01100 if (rclN._aulNeighbours[(uNSide+1)%3] != ULONG_MAX)
01101 _rclMesh._aclFacetArray[rclN._aulNeighbours[(uNSide+1)%3]].ReplaceNeighbour(ulNeighbour, ulSize);
01102
01103 MeshFacet cNew;
01104 cNew._aulPoints[0] = uPtInd;
01105 cNew._aulPoints[1] = rclN._aulPoints[(uNSide+1)%3];
01106 cNew._aulPoints[2] = rclN._aulPoints[(uNSide+2)%3];
01107 cNew._aulNeighbours[0] = ulFacetPos;
01108 cNew._aulNeighbours[1] = rclN._aulNeighbours[(uNSide+1)%3];
01109 cNew._aulNeighbours[2] = ulNeighbour;
01110
01111
01112 rclN._aulPoints[(uNSide+1)%3] = uPtInd;
01113 rclN._aulNeighbours[(uNSide+1)%3] = ulSize;
01114
01115
01116 _rclMesh._aclFacetArray.push_back(cNew);
01117 }
01118
01119 #if 0
01120
01121 MeshGeomFacet clFacet;
01122
01123
01124 clFacet._aclPoints[0] = cP1;
01125 clFacet._aclPoints[1] = _rclMesh._aclPointArray[rFace._aulPoints[(iEdgeNo1+1)%3]];
01126 clFacet._aclPoints[2] = cP2;
01127 clFacet.CalcNormal();
01128 _aclNewFacets.push_back(clFacet);
01129
01130 clFacet._aclPoints[0] = cP2;
01131 clFacet._aclPoints[1] = _rclMesh._aclPointArray[rFace._aulPoints[(iEdgeNo1+2)%3]];
01132 clFacet._aclPoints[2] = _rclMesh._aclPointArray[rFace._aulPoints[iEdgeNo1]];
01133 clFacet.CalcNormal();
01134 _aclNewFacets.push_back(clFacet);
01135
01136 clFacet._aclPoints[0] = cP2;
01137 clFacet._aclPoints[1] = _rclMesh._aclPointArray[rFace._aulPoints[iEdgeNo1]];
01138 clFacet._aclPoints[2] = cP1;
01139 clFacet.CalcNormal();
01140 _aclNewFacets.push_back(clFacet);
01141 #endif
01142
01143 void MeshTopoAlgorithm::RemoveDegeneratedFacet(unsigned long index)
01144 {
01145 if (index >= _rclMesh._aclFacetArray.size()) return;
01146 MeshFacet& rFace = _rclMesh._aclFacetArray[index];
01147
01148
01149 for (int i=0; i<3; i++) {
01150 const MeshPoint& rE0 = _rclMesh._aclPointArray[rFace._aulPoints[i]];
01151 const MeshPoint& rE1 = _rclMesh._aclPointArray[rFace._aulPoints[(i+1)%3]];
01152 if (rE0 == rE1) {
01153 unsigned long uN1 = rFace._aulNeighbours[(i+1)%3];
01154 unsigned long uN2 = rFace._aulNeighbours[(i+2)%3];
01155 if (uN2 != ULONG_MAX)
01156 _rclMesh._aclFacetArray[uN2].ReplaceNeighbour(index, uN1);
01157 if (uN1 != ULONG_MAX)
01158 _rclMesh._aclFacetArray[uN1].ReplaceNeighbour(index, uN2);
01159
01160
01161 rFace._aulNeighbours[0] = ULONG_MAX;
01162 rFace._aulNeighbours[1] = ULONG_MAX;
01163 rFace._aulNeighbours[2] = ULONG_MAX;
01164 _rclMesh.DeleteFacet(index);
01165 return;
01166 }
01167 }
01168
01169
01170
01171
01172 for (int j=0; j<3; j++) {
01173 Base::Vector3f cVec1 = _rclMesh._aclPointArray[rFace._aulPoints[(j+1)%3]] - _rclMesh._aclPointArray[rFace._aulPoints[j]];
01174 Base::Vector3f cVec2 = _rclMesh._aclPointArray[rFace._aulPoints[(j+2)%3]] - _rclMesh._aclPointArray[rFace._aulPoints[j]];
01175
01176
01177 if (cVec1 * cVec2 < 0.0f) {
01178 unsigned long uN1 = rFace._aulNeighbours[(j+1)%3];
01179 if (uN1 != ULONG_MAX) {
01180
01181 MeshFacet& rNb = _rclMesh._aclFacetArray[uN1];
01182 unsigned short side = rNb.Side(index);
01183
01184
01185 rFace._aulPoints[(j+2)%3] = rNb._aulPoints[(side+2)%3];
01186 rNb._aulPoints[(side+1)%3] = rFace._aulPoints[j];
01187
01188
01189 unsigned long uN2 = rFace._aulNeighbours[(j+2)%3];
01190 rNb._aulNeighbours[side] = uN2;
01191 if (uN2 != ULONG_MAX) {
01192 _rclMesh._aclFacetArray[uN2].ReplaceNeighbour(index, uN1);
01193 }
01194 unsigned long uN3 = rNb._aulNeighbours[(side+1)%3];
01195 rFace._aulNeighbours[(j+1)%3] = uN3;
01196 if (uN3 != ULONG_MAX) {
01197 _rclMesh._aclFacetArray[uN3].ReplaceNeighbour(uN1, index);
01198 }
01199 rNb._aulNeighbours[(side+1)%3] = index;
01200 rFace._aulNeighbours[(j+2)%3] = uN1;
01201 }
01202 else
01203 _rclMesh.DeleteFacet(index);
01204
01205 return;
01206 }
01207 }
01208 }
01209
01210 void MeshTopoAlgorithm::RemoveCorruptedFacet(unsigned long index)
01211 {
01212 if (index >= _rclMesh._aclFacetArray.size()) return;
01213 MeshFacet& rFace = _rclMesh._aclFacetArray[index];
01214
01215
01216 for (int i=0; i<3; i++) {
01217 if (rFace._aulPoints[i] == rFace._aulPoints[(i+1)%3]) {
01218 unsigned long uN1 = rFace._aulNeighbours[(i+1)%3];
01219 unsigned long uN2 = rFace._aulNeighbours[(i+2)%3];
01220 if (uN2 != ULONG_MAX)
01221 _rclMesh._aclFacetArray[uN2].ReplaceNeighbour(index, uN1);
01222 if (uN1 != ULONG_MAX)
01223 _rclMesh._aclFacetArray[uN1].ReplaceNeighbour(index, uN2);
01224
01225
01226 rFace._aulNeighbours[0] = ULONG_MAX;
01227 rFace._aulNeighbours[1] = ULONG_MAX;
01228 rFace._aulNeighbours[2] = ULONG_MAX;
01229 _rclMesh.DeleteFacet(index);
01230 return;
01231 }
01232 }
01233 }
01234
01235 void MeshTopoAlgorithm::FillupHoles(unsigned long length, int level,
01236 AbstractPolygonTriangulator& cTria,
01237 std::list<std::vector<unsigned long> >& aFailed)
01238 {
01239
01240 std::list<std::vector<unsigned long> > aBorders;
01241 MeshAlgorithm cAlgo(_rclMesh);
01242 cAlgo.GetMeshBorders(aBorders);
01243
01244
01245 cAlgo.SplitBoundaryLoops(aBorders);
01246
01247
01248 MeshRefPointToFacets cPt2Fac(_rclMesh);
01249
01250 MeshFacetArray newFacets;
01251 MeshPointArray newPoints;
01252 unsigned long numberOfOldPoints = _rclMesh._aclPointArray.size();
01253 for ( std::list<std::vector<unsigned long> >::iterator it = aBorders.begin(); it != aBorders.end(); ++it ) {
01254 if ( it->size()-1 > length )
01255 continue;
01256 MeshFacetArray cFacets;
01257 MeshPointArray cPoints;
01258 if (cAlgo.FillupHole(*it, cTria, cFacets, cPoints, level, &cPt2Fac)) {
01259 if (it->front() == it->back())
01260 it->pop_back();
01261
01262 unsigned long countBoundaryPoints = it->size();
01263 unsigned long countDifference = cPoints.size() - countBoundaryPoints;
01264 if (countDifference > 0) {
01265 MeshPointArray::_TIterator pt = cPoints.begin() + countBoundaryPoints;
01266 for (unsigned long i=0; i<countDifference; i++, pt++) {
01267 it->push_back(numberOfOldPoints++);
01268 newPoints.push_back(*pt);
01269 }
01270 }
01271 for (MeshFacetArray::_TIterator kt = cFacets.begin(); kt != cFacets.end(); ++kt ) {
01272 kt->_aulPoints[0] = (*it)[kt->_aulPoints[0]];
01273 kt->_aulPoints[1] = (*it)[kt->_aulPoints[1]];
01274 kt->_aulPoints[2] = (*it)[kt->_aulPoints[2]];
01275 newFacets.push_back(*kt);
01276 }
01277 }
01278 else {
01279 aFailed.push_back(*it);
01280 }
01281 }
01282
01283
01284 _rclMesh._aclPointArray.insert(_rclMesh._aclPointArray.end(), newPoints.begin(), newPoints.end());
01285 for (MeshPointArray::_TIterator it = newPoints.begin(); it != newPoints.end(); ++it)
01286 _rclMesh._clBoundBox &= *it;
01287 if (!newFacets.empty())
01288 _rclMesh.AddFacets(newFacets);
01289 }
01290
01291 void MeshTopoAlgorithm::FillupHoles(int level, AbstractPolygonTriangulator& cTria,
01292 const std::list<std::vector<unsigned long> >& aBorders,
01293 std::list<std::vector<unsigned long> >& aFailed)
01294 {
01295
01296 MeshRefPointToFacets cPt2Fac(_rclMesh);
01297 MeshAlgorithm cAlgo(_rclMesh);
01298
01299 MeshFacetArray newFacets;
01300 MeshPointArray newPoints;
01301 unsigned long numberOfOldPoints = _rclMesh._aclPointArray.size();
01302 for (std::list<std::vector<unsigned long> >::const_iterator it = aBorders.begin(); it != aBorders.end(); ++it) {
01303 MeshFacetArray cFacets;
01304 MeshPointArray cPoints;
01305 std::vector<unsigned long> bound = *it;
01306 if (cAlgo.FillupHole(bound, cTria, cFacets, cPoints, level, &cPt2Fac)) {
01307 if (bound.front() == bound.back())
01308 bound.pop_back();
01309
01310 unsigned long countBoundaryPoints = bound.size();
01311 unsigned long countDifference = cPoints.size() - countBoundaryPoints;
01312 if (countDifference > 0) {
01313 MeshPointArray::_TIterator pt = cPoints.begin() + countBoundaryPoints;
01314 for (unsigned long i=0; i<countDifference; i++, pt++) {
01315 bound.push_back(numberOfOldPoints++);
01316 newPoints.push_back(*pt);
01317 }
01318 }
01319 for (MeshFacetArray::_TIterator kt = cFacets.begin(); kt != cFacets.end(); ++kt ) {
01320 kt->_aulPoints[0] = bound[kt->_aulPoints[0]];
01321 kt->_aulPoints[1] = bound[kt->_aulPoints[1]];
01322 kt->_aulPoints[2] = bound[kt->_aulPoints[2]];
01323 newFacets.push_back(*kt);
01324 }
01325 }
01326 else {
01327 aFailed.push_back(*it);
01328 }
01329 }
01330
01331
01332 _rclMesh._aclPointArray.insert(_rclMesh._aclPointArray.end(), newPoints.begin(), newPoints.end());
01333 for (MeshPointArray::_TIterator it = newPoints.begin(); it != newPoints.end(); ++it)
01334 _rclMesh._clBoundBox &= *it;
01335 if (!newFacets.empty())
01336 _rclMesh.AddFacets(newFacets);
01337 }
01338
01339 void MeshTopoAlgorithm::FindHoles(unsigned long length,
01340 std::list<std::vector<unsigned long> >& aBorders) const
01341 {
01342 std::list<std::vector<unsigned long> > border;
01343 MeshAlgorithm cAlgo(_rclMesh);
01344 cAlgo.GetMeshBorders(border);
01345 for (std::list<std::vector<unsigned long> >::iterator it = border.begin();
01346 it != border.end(); ++it) {
01347 if (it->size() <= length) aBorders.push_back(*it);
01348 }
01349 }
01350
01351 void MeshTopoAlgorithm::FindComponents(unsigned long count, std::vector<unsigned long>& findIndices)
01352 {
01353 std::vector<std::vector<unsigned long> > segments;
01354 MeshComponents comp(_rclMesh);
01355 comp.SearchForComponents(MeshComponents::OverEdge,segments);
01356
01357 for (std::vector<std::vector<unsigned long> >::iterator it = segments.begin(); it != segments.end(); ++it) {
01358 if (it->size() <= (unsigned long)count)
01359 findIndices.insert(findIndices.end(), it->begin(), it->end());
01360 }
01361 }
01362
01363 void MeshTopoAlgorithm::RemoveComponents(unsigned long count)
01364 {
01365 std::vector<unsigned long> removeFacets;
01366 FindComponents(count, removeFacets);
01367 if (!removeFacets.empty())
01368 _rclMesh.DeleteFacets(removeFacets);
01369 }
01370
01371 void MeshTopoAlgorithm::HarmonizeNormals (void)
01372 {
01373 std::vector<unsigned long> uIndices = MeshEvalOrientation(_rclMesh).GetIndices();
01374 for ( std::vector<unsigned long>::iterator it = uIndices.begin(); it != uIndices.end(); ++it )
01375 _rclMesh._aclFacetArray[*it].FlipNormal();
01376 }
01377
01378 void MeshTopoAlgorithm::FlipNormals (void)
01379 {
01380 for (MeshFacetArray::_TIterator i = _rclMesh._aclFacetArray.begin(); i < _rclMesh._aclFacetArray.end(); i++)
01381 i->FlipNormal();
01382 }
01383
01384
01385
01407 MeshComponents::MeshComponents( const MeshKernel& rclMesh )
01408 : _rclMesh(rclMesh)
01409 {
01410 }
01411
01412 MeshComponents::~MeshComponents()
01413 {
01414 }
01415
01416 void MeshComponents::SearchForComponents(TMode tMode, std::vector<std::vector<unsigned long> >& aclT) const
01417 {
01418
01419 std::vector<unsigned long> aulAllFacets(_rclMesh.CountFacets());
01420 unsigned long k = 0;
01421 for (std::vector<unsigned long>::iterator pI = aulAllFacets.begin(); pI != aulAllFacets.end(); pI++)
01422 *pI = k++;
01423
01424 SearchForComponents( tMode, aulAllFacets, aclT );
01425 }
01426
01427 void MeshComponents::SearchForComponents(TMode tMode, const std::vector<unsigned long>& aSegment, std::vector<std::vector<unsigned long> >& aclT) const
01428 {
01429 unsigned long ulStartFacet, ulVisited;
01430
01431 if (_rclMesh.CountFacets() == 0)
01432 return;
01433
01434
01435 MeshAlgorithm cAlgo(_rclMesh);
01436 cAlgo.SetFacetFlag(MeshFacet::VISIT);
01437 cAlgo.ResetFacetsFlag(aSegment, MeshFacet::VISIT);
01438
01439 const MeshFacetArray& rFAry = _rclMesh.GetFacets();
01440 MeshFacetArray::_TConstIterator iTri = rFAry.begin();
01441 MeshFacetArray::_TConstIterator iBeg = rFAry.begin();
01442 MeshFacetArray::_TConstIterator iEnd = rFAry.end();
01443
01444
01445 ulVisited = cAlgo.CountFacetFlag(MeshFacet::VISIT);
01446 iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshIsNotFlag<MeshFacet>(), MeshFacet::VISIT));
01447 ulStartFacet = iTri - iBeg;
01448
01449
01450 std::vector<unsigned long> aclComponent;
01451 std::vector<std::vector<unsigned long> > aclConnectComp;
01452 MeshTopFacetVisitor clFVisitor( aclComponent );
01453
01454 while ( ulStartFacet != ULONG_MAX )
01455 {
01456
01457 aclComponent.clear();
01458 if (tMode == OverEdge)
01459 ulVisited += _rclMesh.VisitNeighbourFacets(clFVisitor, ulStartFacet);
01460 else if (tMode == OverPoint)
01461 ulVisited += _rclMesh.VisitNeighbourFacetsOverCorners(clFVisitor, ulStartFacet);
01462
01463
01464 aclComponent.push_back(ulStartFacet);
01465 aclConnectComp.push_back(aclComponent);
01466
01467
01468
01469
01470 iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshIsNotFlag<MeshFacet>(), MeshFacet::VISIT));
01471
01472 if (iTri < iEnd)
01473 ulStartFacet = iTri - iBeg;
01474 else
01475 ulStartFacet = ULONG_MAX;
01476 }
01477
01478
01479 std::sort(aclConnectComp.begin(), aclConnectComp.end(), CNofFacetsCompare());
01480 aclT = aclConnectComp;
01481 }