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
00027 #ifndef _PreComp_
00028 # include <ios>
00029 #endif
00030
00031 #include <fstream>
00032 #include "SetOperations.h"
00033 #include "Algorithm.h"
00034 #include "Elements.h"
00035 #include "Iterator.h"
00036 #include "Grid.h"
00037 #include "MeshIO.h"
00038 #include "Visitor.h"
00039 #include "Builder.h"
00040 #include "Grid.h"
00041 #include "Evaluation.h"
00042 #include "Definitions.h"
00043 #include "Triangulation.h"
00044
00045 #include <Base/Sequencer.h>
00046 #include <Base/Builder3D.h>
00047 #include <Base/Tools2D.h>
00048
00049 using namespace Base;
00050 using namespace MeshCore;
00051
00052
00053 SetOperations::SetOperations (const MeshKernel &cutMesh1, const MeshKernel &cutMesh2, MeshKernel &result, OperationType opType, float minDistanceToPoint)
00054 : _cutMesh0(cutMesh1),
00055 _cutMesh1(cutMesh2),
00056 _resultMesh(result),
00057 _operationType(opType),
00058 _minDistanceToPoint(minDistanceToPoint)
00059 {
00060 }
00061
00062 SetOperations::~SetOperations (void)
00063 {
00064 }
00065
00066 void SetOperations::Do ()
00067 {
00068 _minDistanceToPoint = 0.000001f;
00069 float saveMinMeshDistance = MeshDefinitions::_fMinPointDistance;
00070 MeshDefinitions::SetMinPointDistance(0.000001f);
00071
00072
00073
00074
00075
00076
00077 std::set<unsigned long> facetsCuttingEdge0, facetsCuttingEdge1;
00078 Cut(facetsCuttingEdge0, facetsCuttingEdge1);
00079
00080
00081 if (facetsCuttingEdge0.empty() || facetsCuttingEdge1.empty())
00082 {
00083 switch (_operationType)
00084 {
00085 case Union:
00086 {
00087 _resultMesh = _cutMesh0;
00088 _resultMesh.Merge(_cutMesh1);
00089 } break;
00090 case Intersect:
00091 {
00092 _resultMesh.Clear();
00093 } break;
00094 case Difference:
00095 case Inner:
00096 case Outer:
00097 {
00098 _resultMesh = _cutMesh0;
00099 } break;
00100 default:
00101 {
00102 _resultMesh.Clear();
00103 break;
00104 }
00105 }
00106
00107 MeshDefinitions::SetMinPointDistance(saveMinMeshDistance);
00108 return;
00109 }
00110
00111 unsigned long i;
00112 for (i = 0; i < _cutMesh0.CountFacets(); i++)
00113 {
00114 if (facetsCuttingEdge0.find(i) == facetsCuttingEdge0.end())
00115 _newMeshFacets[0].push_back(_cutMesh0.GetFacet(i));
00116 }
00117
00118 for (i = 0; i < _cutMesh1.CountFacets(); i++)
00119 {
00120 if (facetsCuttingEdge1.find(i) == facetsCuttingEdge1.end())
00121 _newMeshFacets[1].push_back(_cutMesh1.GetFacet(i));
00122 }
00123
00124
00125 TriangulateMesh(_cutMesh0, 0);
00126
00127
00128 TriangulateMesh(_cutMesh1, 1);
00129
00130 float mult0, mult1;
00131 switch (_operationType)
00132 {
00133 case Union: mult0 = -1.0f; mult1 = -1.0f; break;
00134 case Intersect: mult0 = 1.0f; mult1 = 1.0f; break;
00135 case Difference: mult0 = -1.0f; mult1 = 1.0f; break;
00136 case Inner: mult0 = 1.0f; mult1 = 0.0f; break;
00137 case Outer: mult0 = -1.0f; mult1 = 0.0f; break;
00138 default: mult0 = 0.0f; mult1 = 0.0f; break;
00139 }
00140
00141
00142 CollectFacets(0, mult0);
00143
00144 CollectFacets(1, mult1);
00145
00146 std::vector<MeshGeomFacet> facets;
00147
00148 std::vector<MeshGeomFacet>::iterator itf;
00149 for (itf = _facetsOf[0].begin(); itf != _facetsOf[0].end(); itf++)
00150 {
00151 if (_operationType == Difference)
00152 {
00153 std::swap(itf->_aclPoints[0], itf->_aclPoints[1]);
00154 itf->CalcNormal();
00155 }
00156
00157 facets.push_back(*itf);
00158 }
00159
00160 for (itf = _facetsOf[1].begin(); itf != _facetsOf[1].end(); itf++)
00161 {
00162 facets.push_back(*itf);
00163 }
00164
00165 _resultMesh = facets;
00166
00167
00168
00169
00170 MeshDefinitions::SetMinPointDistance(saveMinMeshDistance);
00171 }
00172
00173 void SetOperations::Cut (std::set<unsigned long>& facetsCuttingEdge0, std::set<unsigned long>& facetsCuttingEdge1)
00174 {
00175 MeshFacetGrid grid1(_cutMesh0, 20);
00176 MeshFacetGrid grid2(_cutMesh1, 20);
00177
00178 unsigned long ctGx1, ctGy1, ctGz1;
00179 grid1.GetCtGrids(ctGx1, ctGy1, ctGz1);
00180
00181 unsigned long gx1;
00182 for (gx1 = 0; gx1 < ctGx1; gx1++)
00183 {
00184 unsigned long gy1;
00185 for (gy1 = 0; gy1 < ctGy1; gy1++)
00186 {
00187 unsigned long gz1;
00188 for (gz1 = 0; gz1 < ctGz1; gz1++)
00189 {
00190 if (grid1.GetCtElements(gx1, gy1, gz1) > 0)
00191 {
00192 std::vector<unsigned long> vecFacets2;
00193 grid2.Inside(grid1.GetBoundBox(gx1, gy1, gz1), vecFacets2);
00194
00195 if (vecFacets2.size() > 0)
00196 {
00197 std::set<unsigned long> vecFacets1;
00198 grid1.GetElements(gx1, gy1, gz1, vecFacets1);
00199
00200 std::set<unsigned long>::iterator it1;
00201 for (it1 = vecFacets1.begin(); it1 != vecFacets1.end(); it1++)
00202 {
00203 unsigned long fidx1 = *it1;
00204 MeshGeomFacet f1 = _cutMesh0.GetFacet(*it1);
00205
00206 std::vector<unsigned long>::iterator it2;
00207 for (it2 = vecFacets2.begin(); it2 != vecFacets2.end(); it2++)
00208 {
00209 unsigned long fidx2 = *it2;
00210 MeshGeomFacet f2 = _cutMesh1.GetFacet(fidx2);
00211
00212 MeshPoint p0, p1;
00213
00214 int isect = f1.IntersectWithFacet(f2, p0, p1);
00215 if (isect > 0)
00216 {
00217
00218 float minDist1 = _minDistanceToPoint, minDist2 = _minDistanceToPoint;
00219 MeshPoint np0 = p0, np1 = p1;
00220 int i;
00221 for (i = 0; i < 3; i++)
00222 {
00223 float d1 = (f1._aclPoints[i] - p0).Length();
00224 float d2 = (f1._aclPoints[i] - p1).Length();
00225 if (d1 < minDist1)
00226 {
00227 minDist1 = d1;
00228 np0 = f1._aclPoints[i];
00229 }
00230 if (d2 < minDist2)
00231 {
00232 minDist2 = d2;
00233 p1 = f1._aclPoints[i];
00234 }
00235 }
00236
00237
00238 for (i = 0; i < 3; i++)
00239 {
00240 float d1 = (f2._aclPoints[i] - p0).Length();
00241 float d2 = (f2._aclPoints[i] - p1).Length();
00242 if (d1 < minDist1)
00243 {
00244 minDist1 = d1;
00245 np0 = f2._aclPoints[i];
00246 }
00247 if (d2 < minDist2)
00248 {
00249 minDist2 = d2;
00250 np1 = f2._aclPoints[i];
00251 }
00252 }
00253
00254 MeshPoint mp0 = np0;
00255 MeshPoint mp1 = np1;
00256
00257 if (mp0 != mp1)
00258 {
00259 facetsCuttingEdge0.insert(fidx1);
00260 facetsCuttingEdge1.insert(fidx2);
00261
00262 _cutPoints.insert(mp0);
00263 _cutPoints.insert(mp1);
00264
00265 std::pair<std::set<MeshPoint>::iterator, bool> pit0 = _cutPoints.insert(mp0);
00266 std::pair<std::set<MeshPoint>::iterator, bool> pit1 = _cutPoints.insert(mp1);
00267
00268 _edges[Edge(mp0, mp1)] = EdgeInfo();
00269
00270 _facet2points[0][fidx1].push_back(pit0.first);
00271 _facet2points[0][fidx1].push_back(pit1.first);
00272 _facet2points[1][fidx2].push_back(pit0.first);
00273 _facet2points[1][fidx2].push_back(pit1.first);
00274
00275 }
00276 else
00277 {
00278 std::pair<std::set<MeshPoint>::iterator, bool> pit = _cutPoints.insert(mp0);
00279
00280
00281
00282 {
00283 facetsCuttingEdge0.insert(fidx1);
00284 _facet2points[0][fidx1].push_back(pit.first);
00285 }
00286
00287
00288 {
00289 facetsCuttingEdge1.insert(fidx2);
00290 _facet2points[1][fidx2].push_back(pit.first);
00291 }
00292 }
00293
00294 }
00295 }
00296 }
00297 }
00298 }
00299 }
00300 }
00301 }
00302 }
00303
00304 void SetOperations::TriangulateMesh (const MeshKernel &cutMesh, int side)
00305 {
00306
00307 std::map<unsigned long, std::list<std::set<MeshPoint>::iterator> >::iterator it1;
00308 for (it1 = _facet2points[side].begin(); it1 != _facet2points[side].end(); it1++)
00309 {
00310 std::vector<Vector3f> points;
00311 std::set<MeshPoint> pointsSet;
00312
00313 unsigned long fidx = it1->first;
00314 MeshGeomFacet f = cutMesh.GetFacet(fidx);
00315
00316
00317
00318
00319
00320
00321 int i;
00322 for (i = 0; i < 3; i++)
00323 {
00324 pointsSet.insert(f._aclPoints[i]);
00325 points.push_back(f._aclPoints[i]);
00326 }
00327
00328
00329 std::list<std::set<MeshPoint>::iterator>::iterator it2;
00330 for (it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
00331 {
00332 if (pointsSet.find(*(*it2)) == pointsSet.end())
00333 {
00334 pointsSet.insert(*(*it2));
00335 points.push_back(*(*it2));
00336 }
00337
00338 }
00339
00340 Vector3f normal = f.GetNormal();
00341 Vector3f base = points[0];
00342 Vector3f dirX = points[1] - points[0];
00343 dirX.Normalize();
00344 Vector3f dirY = dirX % normal;
00345
00346
00347 i = 0;
00348 std::vector<Vector3f>::iterator it;
00349 std::vector<Vector3f> vertices;
00350 for (it = points.begin(); it != points.end(); it++)
00351 {
00352 Vector3f pv = *it;
00353 pv.TransformToCoordinateSystem(base, dirX, dirY);
00354 vertices.push_back(pv);
00355 }
00356
00357 DelaunayTriangulator tria;
00358 tria.SetPolygon(vertices);
00359 tria.TriangulatePolygon();
00360
00361 std::vector<MeshFacet> facets = tria.GetFacets();
00362 for (std::vector<MeshFacet>::iterator it = facets.begin(); it != facets.end(); ++it)
00363 {
00364 if ((it->_aulPoints[0] == it->_aulPoints[1]) ||
00365 (it->_aulPoints[1] == it->_aulPoints[2]) ||
00366 (it->_aulPoints[2] == it->_aulPoints[0]))
00367 {
00368 continue;
00369 }
00370
00371 MeshGeomFacet facet(points[it->_aulPoints[0]],
00372 points[it->_aulPoints[1]],
00373 points[it->_aulPoints[2]]);
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 float dist0 = facet._aclPoints[0].DistanceToLine
00384 (facet._aclPoints[1],facet._aclPoints[1] - facet._aclPoints[2]);
00385 float dist1 = facet._aclPoints[1].DistanceToLine
00386 (facet._aclPoints[0],facet._aclPoints[0] - facet._aclPoints[2]);
00387 float dist2 = facet._aclPoints[2].DistanceToLine
00388 (facet._aclPoints[0],facet._aclPoints[0] - facet._aclPoints[1]);
00389
00390 if ((dist0 < _minDistanceToPoint) ||
00391 (dist1 < _minDistanceToPoint) ||
00392 (dist2 < _minDistanceToPoint))
00393 {
00394 continue;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 facet.CalcNormal();
00407 if ((facet.GetNormal() * f.GetNormal()) < 0.0f)
00408 {
00409 std::swap(facet._aclPoints[0], facet._aclPoints[1]);
00410 facet.CalcNormal();
00411 }
00412
00413
00414 int j;
00415 for (j = 0; j < 3; j++)
00416 {
00417 std::map<Edge, EdgeInfo>::iterator eit = _edges.find(Edge(facet._aclPoints[j], facet._aclPoints[(j+1)%3]));
00418
00419 if (eit != _edges.end())
00420 {
00421
00422 if (eit->second.fcounter[side] < 2)
00423 {
00424
00425
00426
00427 eit->second.facet[side] = fidx;
00428 eit->second.facets[side][eit->second.fcounter[side]] = facet;
00429 eit->second.fcounter[side]++;
00430 facet.SetFlag(MeshFacet::MARKED);
00431
00432 }
00433 }
00434 }
00435
00436 _newMeshFacets[side].push_back(facet);
00437
00438 }
00439 }
00440 }
00441
00442 void SetOperations::CollectFacets (int side, float mult)
00443 {
00444
00445
00446
00447 MeshKernel mesh;
00448 MeshBuilder mb(mesh);
00449 mb.Initialize(_newMeshFacets[side].size());
00450 std::vector<MeshGeomFacet>::iterator it;
00451 for (it = _newMeshFacets[side].begin(); it != _newMeshFacets[side].end(); it++)
00452 {
00453
00454
00455
00456
00457 mb.AddFacet(*it, true);
00458 }
00459 mb.Finish();
00460
00461 MeshAlgorithm algo(mesh);
00462 algo.ResetFacetFlag((MeshFacet::TFlagType)(MeshFacet::VISIT | MeshFacet::TMP0));
00463
00464
00465
00466 MeshFacetArray::_TConstIterator itf;
00467 const MeshFacetArray& rFacets = mesh.GetFacets();
00468 for (itf = rFacets.begin(); itf != rFacets.end(); itf++)
00469 {
00470 if (!itf->IsFlag(MeshFacet::VISIT))
00471 {
00472 std::vector<unsigned long> facets;
00473 facets.push_back(itf - rFacets.begin());
00474 CollectFacetVisitor visitor(mesh, facets, _edges, side, mult, _builder);
00475 mesh.VisitNeighbourFacets(visitor, itf - rFacets.begin());
00476
00477 if (visitor._addFacets == 0)
00478 {
00479 algo.SetFacetsFlag(facets, MeshFacet::TMP0);
00480 }
00481 }
00482 }
00483
00484
00485 for (itf = rFacets.begin(); itf != rFacets.end(); itf++)
00486 {
00487 if (itf->IsFlag(MeshFacet::TMP0))
00488 {
00489 _facetsOf[side].push_back(mesh.GetFacet(*itf));
00490 }
00491 }
00492
00493
00494 }
00495
00496 SetOperations::CollectFacetVisitor::CollectFacetVisitor (const MeshKernel& mesh, std::vector<unsigned long>& facets, std::map<Edge, EdgeInfo>& edges, int side, float mult , Base::Builder3D& builder )
00497 : _facets(facets),
00498 _mesh(mesh),
00499 _edges(edges),
00500 _side(side),
00501 _mult(mult),
00502 _addFacets(-1)
00503 ,_builder(builder)
00504 {
00505 }
00506
00507 bool SetOperations::CollectFacetVisitor::Visit (const MeshFacet &rclFacet, const MeshFacet &rclFrom, unsigned long ulFInd, unsigned long ulLevel)
00508 {
00509 _facets.push_back(ulFInd);
00510 return true;
00511 }
00512
00513
00514 bool SetOperations::CollectFacetVisitor::AllowVisit (const MeshFacet& rclFacet, const MeshFacet& rclFrom, unsigned long ulFInd, unsigned long ulLevel, unsigned short neighbourIndex)
00515 {
00516 if (rclFacet.IsFlag(MeshFacet::MARKED) && rclFrom.IsFlag(MeshFacet::MARKED))
00517 {
00518 unsigned long pt0 = rclFrom._aulPoints[neighbourIndex], pt1 = rclFrom._aulPoints[(neighbourIndex+1)%3];
00519 Edge edge(_mesh.GetPoint(pt0), _mesh.GetPoint(pt1));
00520
00521 std::map<Edge, EdgeInfo>::iterator it = _edges.find(edge);
00522
00523 if (it != _edges.end())
00524 {
00525 if (_addFacets == -1)
00526 {
00527 MeshGeomFacet facet = _mesh.GetFacet(rclFrom);
00528 MeshGeomFacet facetOther = it->second.facets[1-_side][0];
00529 Vector3f normalOther = facetOther.GetNormal();
00530
00531
00532 Vector3f edgeDir = it->first.pt1 - it->first.pt2;
00533 Vector3f ocDir = (edgeDir % (facet.GetGravityPoint() - it->first.pt1)) % edgeDir;
00534 ocDir.Normalize();
00535 Vector3f ocDirOther = (edgeDir % (facetOther.GetGravityPoint() - it->first.pt1)) % edgeDir;
00536 ocDirOther.Normalize();
00537
00538
00539
00540
00541 bool match = ((ocDir * normalOther) * _mult) < 0.0f;
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 if (match)
00600 _addFacets = 0;
00601 else
00602 _addFacets = 1;
00603
00604
00605 }
00606
00607 return false;
00608 }
00609 }
00610
00611 return true;
00612 }
00613