Download src/Mod/Mesh/App/Core/SetOperations.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 32.6 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Mesh/App/Core/SetOperations.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Mesh/App/Core/SetOperations.cpp
-
curl -L -o SetOperations.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Mesh/App/Core/SetOperations.cpp
32.6 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * Copyright (c) 2005 Berthold Grupp * | |
| * * | |
| * This file is part of the FreeCAD CAx development system. * | |
| * * | |
| * This library is free software; you can redistribute it and/or * | |
| * modify it under the terms of the GNU Library General Public * | |
| * License as published by the Free Software Foundation; either * | |
| * version 2 of the License, or (at your option) any later version. * | |
| * * | |
| * This library is distributed in the hope that it will be useful, * | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| * GNU Library General Public License for more details. * | |
| * * | |
| * You should have received a copy of the GNU Library General Public * | |
| * License along with this library; see the file COPYING.LIB. If not, * | |
| * write to the Free Software Foundation, Inc., 59 Temple Place, * | |
| * Suite 330, Boston, MA 02111-1307, USA * | |
| * * | |
| ***************************************************************************/ | |
| using namespace Base; | |
| using namespace MeshCore; | |
| SetOperations::SetOperations( | |
| const MeshKernel& cutMesh1, | |
| const MeshKernel& cutMesh2, | |
| MeshKernel& result, | |
| OperationType opType, | |
| float minDistanceToPoint | |
| ) | |
| : _cutMesh0(cutMesh1) | |
| , _cutMesh1(cutMesh2) | |
| , _resultMesh(result) | |
| , _operationType(opType) | |
| , _minDistanceToPoint(minDistanceToPoint) | |
| {} | |
| void SetOperations::Do() | |
| { | |
| _minDistanceToPoint = 0.000001F; | |
| float saveMinMeshDistance = MeshDefinitions::_fMinPointDistance; | |
| MeshDefinitions::SetMinPointDistance(0.000001F); | |
| // Base::Sequencer().start("set operation", 5); | |
| // _builder.clear(); | |
| // Base::Sequencer().next(); | |
| std::set<FacetIndex> facetsCuttingEdge0, facetsCuttingEdge1; | |
| Cut(facetsCuttingEdge0, facetsCuttingEdge1); | |
| // no intersection curve of the meshes found | |
| if (facetsCuttingEdge0.empty() || facetsCuttingEdge1.empty()) { | |
| switch (_operationType) { | |
| case Union: { | |
| _resultMesh = _cutMesh0; | |
| _resultMesh.Merge(_cutMesh1); | |
| } break; | |
| case Intersect: { | |
| _resultMesh.Clear(); | |
| } break; | |
| case Difference: | |
| case Inner: | |
| case Outer: { | |
| _resultMesh = _cutMesh0; | |
| } break; | |
| default: { | |
| _resultMesh.Clear(); | |
| break; | |
| } | |
| } | |
| MeshDefinitions::SetMinPointDistance(saveMinMeshDistance); | |
| return; | |
| } | |
| for (auto i = 0UL; i < _cutMesh0.CountFacets(); i++) { | |
| if (facetsCuttingEdge0.find(i) == facetsCuttingEdge0.end()) { | |
| _newMeshFacets[0].push_back(_cutMesh0.GetFacet(i)); | |
| } | |
| } | |
| for (auto i = 0UL; i < _cutMesh1.CountFacets(); i++) { | |
| if (facetsCuttingEdge1.find(i) == facetsCuttingEdge1.end()) { | |
| _newMeshFacets[1].push_back(_cutMesh1.GetFacet(i)); | |
| } | |
| } | |
| // Base::Sequencer().next(); | |
| TriangulateMesh(_cutMesh0, 0); | |
| // Base::Sequencer().next(); | |
| TriangulateMesh(_cutMesh1, 1); | |
| float mult0 {}, mult1 {}; | |
| switch (_operationType) { | |
| case Union: | |
| mult0 = -1.0F; | |
| mult1 = -1.0F; | |
| break; | |
| case Intersect: | |
| mult0 = 1.0F; | |
| mult1 = 1.0F; | |
| break; | |
| case Difference: | |
| mult0 = -1.0F; | |
| mult1 = 1.0F; | |
| break; | |
| case Inner: | |
| mult0 = 1.0F; | |
| mult1 = 0.0F; | |
| break; | |
| case Outer: | |
| mult0 = -1.0F; | |
| mult1 = 0.0F; | |
| break; | |
| default: | |
| mult0 = 0.0F; | |
| mult1 = 0.0F; | |
| break; | |
| } | |
| // Base::Sequencer().next(); | |
| CollectFacets(0, mult0); | |
| // Base::Sequencer().next(); | |
| CollectFacets(1, mult1); | |
| std::vector<MeshGeomFacet> facets; | |
| std::vector<MeshGeomFacet>::iterator itf; | |
| for (itf = _facetsOf[0].begin(); itf != _facetsOf[0].end(); ++itf) { | |
| if (_operationType == Difference) { // toggle normal | |
| std::swap(itf->_aclPoints[0], itf->_aclPoints[1]); | |
| itf->CalcNormal(); | |
| } | |
| facets.push_back(*itf); | |
| } | |
| for (itf = _facetsOf[1].begin(); itf != _facetsOf[1].end(); ++itf) { | |
| facets.push_back(*itf); | |
| } | |
| _resultMesh = facets; | |
| // Base::Sequencer().stop(); | |
| // _builder.saveToFile("c:/temp/vdbg.iv"); | |
| MeshDefinitions::SetMinPointDistance(saveMinMeshDistance); | |
| } | |
| void SetOperations::Cut(std::set<FacetIndex>& facetsCuttingEdge0, std::set<FacetIndex>& facetsCuttingEdge1) | |
| { | |
| MeshFacetGrid grid1(_cutMesh0, 20); | |
| MeshFacetGrid grid2(_cutMesh1, 20); | |
| unsigned long ctGx1 {}, ctGy1 {}, ctGz1 {}; | |
| grid1.GetCtGrids(ctGx1, ctGy1, ctGz1); | |
| for (auto gx1 = 0UL; gx1 < ctGx1; gx1++) { | |
| for (auto gy1 = 0UL; gy1 < ctGy1; gy1++) { | |
| for (auto gz1 = 0UL; gz1 < ctGz1; gz1++) { | |
| if (grid1.GetCtElements(gx1, gy1, gz1) > 0) { | |
| std::vector<FacetIndex> vecFacets2; | |
| grid2.Inside(grid1.GetBoundBox(gx1, gy1, gz1), vecFacets2); | |
| if (!vecFacets2.empty()) { | |
| std::set<FacetIndex> vecFacets1; | |
| grid1.GetElements(gx1, gy1, gz1, vecFacets1); | |
| std::set<FacetIndex>::iterator it1; | |
| for (it1 = vecFacets1.begin(); it1 != vecFacets1.end(); ++it1) { | |
| FacetIndex fidx1 = *it1; | |
| MeshGeomFacet f1 = _cutMesh0.GetFacet(*it1); | |
| std::vector<FacetIndex>::iterator it2; | |
| for (it2 = vecFacets2.begin(); it2 != vecFacets2.end(); ++it2) { | |
| FacetIndex fidx2 = *it2; | |
| MeshGeomFacet f2 = _cutMesh1.GetFacet(fidx2); | |
| MeshPoint p0, p1; | |
| int isect = f1.IntersectWithFacet(f2, p0, p1); | |
| if (isect > 0) { | |
| // optimize cut line if distance to nearest point is too small | |
| float minDist1 = _minDistanceToPoint, | |
| minDist2 = _minDistanceToPoint; | |
| MeshPoint np0 = p0, np1 = p1; | |
| for (int i = 0; i < 3; i++) // NOLINT | |
| { | |
| float d1 = (f1._aclPoints[i] - p0).Length(); | |
| float d2 = (f1._aclPoints[i] - p1).Length(); | |
| if (d1 < minDist1) { | |
| minDist1 = d1; | |
| np0 = f1._aclPoints[i]; | |
| } | |
| if (d2 < minDist2) { | |
| minDist2 = d2; | |
| p1 = f1._aclPoints[i]; | |
| } | |
| } // for (int i = 0; i < 3; i++) | |
| // optimize cut line if distance to nearest point is too small | |
| for (int i = 0; i < 3; i++) // NOLINT | |
| { | |
| float d1 = (f2._aclPoints[i] - p0).Length(); | |
| float d2 = (f2._aclPoints[i] - p1).Length(); | |
| if (d1 < minDist1) { | |
| minDist1 = d1; | |
| np0 = f2._aclPoints[i]; | |
| } | |
| if (d2 < minDist2) { | |
| minDist2 = d2; | |
| np1 = f2._aclPoints[i]; | |
| } | |
| } // for (int i = 0; i < 3; i++) | |
| MeshPoint mp0 = np0; | |
| MeshPoint mp1 = np1; | |
| if (mp0 != mp1) { | |
| facetsCuttingEdge0.insert(fidx1); | |
| facetsCuttingEdge1.insert(fidx2); | |
| _cutPoints.insert(mp0); | |
| _cutPoints.insert(mp1); | |
| std::pair<std::set<MeshPoint>::iterator, bool> pit0 | |
| = _cutPoints.insert(mp0); | |
| std::pair<std::set<MeshPoint>::iterator, bool> pit1 | |
| = _cutPoints.insert(mp1); | |
| _edges[Edge(mp0, mp1)] = EdgeInfo(); | |
| _facet2points[0][fidx1].push_back(pit0.first); | |
| _facet2points[0][fidx1].push_back(pit1.first); | |
| _facet2points[1][fidx2].push_back(pit0.first); | |
| _facet2points[1][fidx2].push_back(pit1.first); | |
| } | |
| else { | |
| std::pair<std::set<MeshPoint>::iterator, bool> pit | |
| = _cutPoints.insert(mp0); | |
| // do not insert a facet when only one corner point cuts the | |
| // edge if (!((mp0 == f1._aclPoints[0]) || (mp0 == | |
| // f1._aclPoints[1]) || (mp0 == f1._aclPoints[2]))) | |
| { | |
| facetsCuttingEdge0.insert(fidx1); | |
| _facet2points[0][fidx1].push_back(pit.first); | |
| } | |
| // if (!((mp0 == f2._aclPoints[0]) || (mp0 == | |
| // f2._aclPoints[1]) || (mp0 == f2._aclPoints[2]))) | |
| { | |
| facetsCuttingEdge1.insert(fidx2); | |
| _facet2points[1][fidx2].push_back(pit.first); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| void SetOperations::TriangulateMesh(const MeshKernel& cutMesh, int side) | |
| { | |
| // Triangulate Mesh | |
| std::map<FacetIndex, std::list<std::set<MeshPoint>::iterator>>::iterator it1; | |
| for (it1 = _facet2points[side].begin(); it1 != _facet2points[side].end(); ++it1) { | |
| std::vector<Vector3f> points; | |
| std::set<MeshPoint> pointsSet; | |
| FacetIndex fidx = it1->first; | |
| MeshGeomFacet f = cutMesh.GetFacet(fidx); | |
| // if (side == 1) | |
| // _builder.addSingleTriangle(f._aclPoints[0], f._aclPoints[1], f._aclPoints[2], 3, 0, | |
| // 1, 1); | |
| // facet corner points | |
| // const MeshFacet& mf = cutMesh._aclFacetArray[fidx]; | |
| for (int i = 0; i < 3; i++) // NOLINT | |
| { | |
| pointsSet.insert(f._aclPoints[i]); | |
| points.push_back(f._aclPoints[i]); | |
| } | |
| // triangulated facets | |
| std::list<std::set<MeshPoint>::iterator>::iterator it2; | |
| for (it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) { | |
| if (pointsSet.find(*(*it2)) == pointsSet.end()) { | |
| pointsSet.insert(*(*it2)); | |
| points.push_back(*(*it2)); | |
| } | |
| } | |
| Vector3f normal = f.GetNormal(); | |
| Vector3f base = points[0]; | |
| Vector3f dirX = points[1] - points[0]; | |
| dirX.Normalize(); | |
| Vector3f dirY = dirX % normal; | |
| // project points to 2D plane | |
| std::vector<Vector3f>::iterator it; | |
| std::vector<Vector3f> vertices; | |
| for (it = points.begin(); it != points.end(); ++it) { | |
| Vector3f pv = *it; | |
| pv.TransformToCoordinateSystem(base, dirX, dirY); | |
| vertices.push_back(pv); | |
| } | |
| DelaunayTriangulator tria; | |
| tria.SetPolygon(vertices); | |
| tria.TriangulatePolygon(); | |
| std::vector<MeshFacet> facets = tria.GetFacets(); | |
| for (auto& it : facets) { | |
| if ((it._aulPoints[0] == it._aulPoints[1]) || (it._aulPoints[1] == it._aulPoints[2]) | |
| || (it._aulPoints[2] == it._aulPoints[0])) { // two same triangle corner points | |
| continue; | |
| } | |
| MeshGeomFacet facet( | |
| points[it._aulPoints[0]], | |
| points[it._aulPoints[1]], | |
| points[it._aulPoints[2]] | |
| ); | |
| // if (side == 1) | |
| // _builder.addSingleTriangle(facet._aclPoints[0], facet._aclPoints[1], | |
| // facet._aclPoints[2], true, 3, 0, 1, 1); | |
| // if (facet.Area() < 0.0001f) | |
| //{ // too small facet | |
| // continue; | |
| // } | |
| float dist0 = facet._aclPoints[0].DistanceToLine( | |
| facet._aclPoints[1], | |
| facet._aclPoints[1] - facet._aclPoints[2] | |
| ); | |
| float dist1 = facet._aclPoints[1].DistanceToLine( | |
| facet._aclPoints[0], | |
| facet._aclPoints[0] - facet._aclPoints[2] | |
| ); | |
| float dist2 = facet._aclPoints[2].DistanceToLine( | |
| facet._aclPoints[0], | |
| facet._aclPoints[0] - facet._aclPoints[1] | |
| ); | |
| if ((dist0 < _minDistanceToPoint) || (dist1 < _minDistanceToPoint) | |
| || (dist2 < _minDistanceToPoint)) { | |
| continue; | |
| } | |
| // dist0 = (facet._aclPoints[0] - facet._aclPoints[1]).Length(); | |
| // dist1 = (facet._aclPoints[1] - facet._aclPoints[2]).Length(); | |
| // dist2 = (facet._aclPoints[2] - facet._aclPoints[3]).Length(); | |
| // if ((dist0 < _minDistanceToPoint) || (dist1 < _minDistanceToPoint) || (dist2 < | |
| // _minDistanceToPoint)) | |
| //{ | |
| // continue; | |
| // } | |
| facet.CalcNormal(); | |
| if ((facet.GetNormal() * f.GetNormal()) < 0.0F) { // adjust normal | |
| std::swap(facet._aclPoints[0], facet._aclPoints[1]); | |
| facet.CalcNormal(); | |
| } | |
| for (int j = 0; j < 3; j++) { | |
| auto eit = _edges.find(Edge(facet._aclPoints[j], facet._aclPoints[(j + 1) % 3])); | |
| if (eit != _edges.end()) { | |
| if (eit->second.fcounter[side] < 2) { | |
| // if (side == 0) | |
| // _builder.addSingleTriangle(facet._aclPoints[0], facet._aclPoints[1], | |
| // facet._aclPoints[2], true, 3, 0, 1, 1); | |
| eit->second.facet[side] = fidx; | |
| eit->second.facets[side][eit->second.fcounter[side]] = facet; | |
| eit->second.fcounter[side]++; | |
| facet.SetFlag(MeshFacet::MARKED); // set all facets connected to an edge: MARKED | |
| } | |
| } | |
| } | |
| _newMeshFacets[side].push_back(facet); | |
| } | |
| } | |
| } | |
| void SetOperations::CollectFacets(int side, float mult) | |
| { | |
| // float distSave = MeshDefinitions::_fMinPointDistance; | |
| // MeshDefinitions::SetMinPointDistance(1.0e-4f); | |
| MeshKernel mesh; | |
| MeshBuilder mb(mesh); | |
| mb.Initialize(_newMeshFacets[side].size()); | |
| std::vector<MeshGeomFacet>::iterator it; | |
| for (it = _newMeshFacets[side].begin(); it != _newMeshFacets[side].end(); ++it) { | |
| // if (it->IsFlag(MeshFacet::MARKED)) | |
| //{ | |
| // _builder.addSingleTriangle(it->_aclPoints[0], it->_aclPoints[1], it->_aclPoints[2], | |
| // true, 3.0, 0.0, 1.0, 1.0); | |
| // } | |
| mb.AddFacet(*it, true); | |
| } | |
| mb.Finish(); | |
| MeshAlgorithm algo(mesh); | |
| algo.ResetFacetFlag(static_cast<MeshFacet::TFlagType>(MeshFacet::VISIT | MeshFacet::TMP0)); | |
| // bool hasFacetsNotVisited = true; // until facets not visited | |
| // search for facet not visited | |
| MeshFacetArray::_TConstIterator itf; | |
| const MeshFacetArray& rFacets = mesh.GetFacets(); | |
| for (itf = rFacets.begin(); itf != rFacets.end(); ++itf) { | |
| if (!itf->IsFlag(MeshFacet::VISIT)) { // Facet found, visit neighbours | |
| std::vector<FacetIndex> facets; | |
| facets.push_back(itf - rFacets.begin()); // add seed facet | |
| CollectFacetVisitor visitor(mesh, facets, _edges, side, mult, _builder); | |
| mesh.VisitNeighbourFacets(visitor, itf - rFacets.begin()); | |
| if (visitor._addFacets == 0) { // mark all facets to add it to the result | |
| algo.SetFacetsFlag(facets, MeshFacet::TMP0); | |
| } | |
| } | |
| } | |
| // add all facets to the result vector | |
| for (itf = rFacets.begin(); itf != rFacets.end(); ++itf) { | |
| if (itf->IsFlag(MeshFacet::TMP0)) { | |
| _facetsOf[side].push_back(mesh.GetFacet(*itf)); | |
| } | |
| } | |
| // MeshDefinitions::SetMinPointDistance(distSave); | |
| } | |
| SetOperations::CollectFacetVisitor::CollectFacetVisitor( | |
| const MeshKernel& mesh, | |
| std::vector<FacetIndex>& facets, | |
| std::map<Edge, EdgeInfo>& edges, | |
| int side, | |
| float mult, | |
| Base::Builder3D& builder | |
| ) | |
| : _facets(facets) | |
| , _mesh(mesh) | |
| , _edges(edges) | |
| , _side(side) | |
| , _mult(mult) | |
| , _builder(builder) | |
| {} | |
| bool SetOperations::CollectFacetVisitor::Visit( | |
| const MeshFacet& rclFacet, | |
| const MeshFacet& rclFrom, | |
| FacetIndex ulFInd, | |
| unsigned long ulLevel | |
| ) | |
| { | |
| (void)rclFacet; | |
| (void)rclFrom; | |
| (void)ulLevel; | |
| _facets.push_back(ulFInd); | |
| return true; | |
| } | |
| // static int matchCounter = 0; | |
| bool SetOperations::CollectFacetVisitor::AllowVisit( | |
| const MeshFacet& rclFacet, | |
| const MeshFacet& rclFrom, | |
| FacetIndex ulFInd, | |
| unsigned long ulLevel, | |
| unsigned short neighbourIndex | |
| ) | |
| { | |
| (void)ulFInd; | |
| (void)ulLevel; | |
| if (rclFacet.IsFlag(MeshFacet::MARKED) && rclFrom.IsFlag(MeshFacet::MARKED)) { | |
| // facet connected to an edge | |
| PointIndex pt0 = rclFrom._aulPoints[neighbourIndex], | |
| pt1 = rclFrom._aulPoints[(neighbourIndex + 1) % 3]; | |
| Edge edge(_mesh.GetPoint(pt0), _mesh.GetPoint(pt1)); | |
| std::map<Edge, EdgeInfo>::iterator it = _edges.find(edge); | |
| if (it != _edges.end()) { | |
| if (_addFacets == -1) { | |
| // determine if the facets should add or not only once | |
| MeshGeomFacet facet = _mesh.GetFacet(rclFrom); // triangulated facet | |
| MeshGeomFacet facetOther = it->second.facets[1 - _side][0]; // triangulated facet | |
| // from same edge and | |
| // other mesh | |
| Vector3f normalOther = facetOther.GetNormal(); | |
| // Vector3f normal = facet.GetNormal(); | |
| Vector3f edgeDir = it->first.pt1 - it->first.pt2; | |
| Vector3f ocDir = (edgeDir % (facet.GetGravityPoint() - it->first.pt1)) % edgeDir; | |
| ocDir.Normalize(); | |
| Vector3f ocDirOther = (edgeDir % (facetOther.GetGravityPoint() - it->first.pt1)) | |
| % edgeDir; | |
| ocDirOther.Normalize(); | |
| // Vector3f dir = ocDir % normal; | |
| // Vector3f dirOther = ocDirOther % normalOther; | |
| bool match = ((ocDir * normalOther) * _mult) < 0.0F; | |
| // if (matchCounter == 1) | |
| //{ | |
| // // _builder.addSingleArrow(it->second.pt1, it->second.pt1 + edgeDir, 3, | |
| // 0.0, 1.0, 0.0); | |
| // _builder.addSingleTriangle(facet._aclPoints[0], facet._aclPoints[1], | |
| // facet._aclPoints[2], true, 3.0, 1.0, 0.0, 0.0); | |
| // // _builder.addSingleArrow(facet.GetGravityPoint(), facet.GetGravityPoint() + | |
| // ocDir, 3, 1.0, 0.0, 0.0); _builder.addSingleArrow(facet.GetGravityPoint(), | |
| // facet.GetGravityPoint() + normal, 3, 1.0, 0.5, 0.0); | |
| // // _builder.addSingleArrow(facet.GetGravityPoint(), facet.GetGravityPoint() + | |
| // dir, 3, 1.0, 1.0, 0.0); | |
| // _builder.addSingleTriangle(facetOther._aclPoints[0], facetOther._aclPoints[1], | |
| // facetOther._aclPoints[2], true, 3.0, 0.0, 0.0, 1.0); | |
| // // _builder.addSingleArrow(facetOther.GetGravityPoint(), | |
| // facetOther.GetGravityPoint() + ocDirOther, 3, 0.0, 0.0, 1.0); | |
| // _builder.addSingleArrow(facetOther.GetGravityPoint(), | |
| // facetOther.GetGravityPoint() + normalOther, 3, 0.0, 0.5, 1.0); | |
| // // _builder.addSingleArrow(facetOther.GetGravityPoint(), | |
| // facetOther.GetGravityPoint() + dirOther, 3, 0.0, 1.0, 1.0); | |
| //} | |
| // float scalar = dir * dirOther * _mult; | |
| // bool match = scalar > 0.0f; | |
| // MeshPoint pt0 = it->first.pt1; | |
| // MeshPoint pt1 = it->first.pt2; | |
| // int i, n0 = -1, n1 = -1, m0 = -1, m1 = -1; | |
| // for (i = 0; i < 3; i++) | |
| //{ | |
| // if ((n0 == -1) && (facet._aclPoints[i] == pt0)) | |
| // n0 = i; | |
| // if ((n1 == -1) && (facet._aclPoints[i] == pt1)) | |
| // n1 = i; | |
| // if ((m0 == -1) && (facetOther._aclPoints[i] == pt0)) | |
| // m0 = i; | |
| // if ((m1 == -1) && (facetOther._aclPoints[i] == pt1)) | |
| // m1 = i; | |
| // } | |
| // if ((n0 != -1) && (n1 != -1) && (m0 != -1) && (m1 != -1)) | |
| //{ | |
| // bool orient_n = n1 > n0; | |
| // bool orient_m = m1 > m0; | |
| // Vector3f dirN = facet._aclPoints[n1] - facet._aclPoints[n0]; | |
| // Vector3f dirM = facetOther._aclPoints[m1] - facetOther._aclPoints[m0]; | |
| // if (matchCounter == 1) | |
| // { | |
| // _builder.addSingleArrow(facet.GetGravityPoint(), facet.GetGravityPoint() + | |
| // dirN, 3, 1.0, 1.0, 0.0); _builder.addSingleArrow(facetOther.GetGravityPoint(), | |
| // facetOther.GetGravityPoint() + dirM, 3, 0.0, 1.0, 1.0); | |
| // } | |
| // if (_mult > 0.0) | |
| // match = orient_n == orient_m; | |
| // else | |
| // match = orient_n != orient_m; | |
| //} | |
| if (match) { | |
| _addFacets = 0; | |
| } | |
| else { | |
| _addFacets = 1; | |
| } | |
| // matchCounter++; | |
| } | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| // ---------------------------------------------------------------------------- | |
| bool MeshIntersection::hasIntersection() const | |
| { | |
| Base::BoundBox3f bbox1 = kernel1.GetBoundBox(); | |
| Base::BoundBox3f bbox2 = kernel2.GetBoundBox(); | |
| if (!(bbox1 && bbox2)) { | |
| return false; | |
| } | |
| return (testIntersection(kernel1, kernel2)); | |
| } | |
| void MeshIntersection::getIntersection(std::list<MeshIntersection::Tuple>& intsct) const | |
| { | |
| const MeshKernel& k1 = kernel1; | |
| const MeshKernel& k2 = kernel2; | |
| // Contains bounding boxes for every facet of 'k1' | |
| std::vector<Base::BoundBox3f> boxes1; | |
| MeshFacetIterator cMFI1(k1); | |
| for (cMFI1.Begin(); cMFI1.More(); cMFI1.Next()) { | |
| boxes1.push_back((*cMFI1).GetBoundBox()); | |
| } | |
| // Contains bounding boxes for every facet of 'k2' | |
| std::vector<Base::BoundBox3f> boxes2; | |
| MeshFacetIterator cMFI2(k2); | |
| for (cMFI2.Begin(); cMFI2.More(); cMFI2.Next()) { | |
| boxes2.push_back((*cMFI2).GetBoundBox()); | |
| } | |
| // Splits the mesh using grid for speeding up the calculation | |
| MeshFacetGrid cMeshFacetGrid(k1); | |
| const MeshFacetArray& rFaces2 = k2.GetFacets(); | |
| Base::SequencerLauncher seq("Checking for intersections...", rFaces2.size()); | |
| int index = 0; | |
| MeshGeomFacet facet1, facet2; | |
| Base::Vector3f pt1, pt2; | |
| // Iterate over the facets of the 2nd mesh and find the grid elements of the 1st mesh | |
| for (auto it = rFaces2.begin(); it != rFaces2.end(); ++it, index++) { | |
| seq.next(); | |
| std::vector<FacetIndex> elements; | |
| cMeshFacetGrid.Inside(boxes2[index], elements, true); | |
| cMFI2.Set(index); | |
| facet2 = *cMFI2; | |
| for (FacetIndex element : elements) { | |
| if (boxes2[index] && boxes1[element]) { | |
| cMFI1.Set(element); | |
| facet1 = *cMFI1; | |
| int ret = facet1.IntersectWithFacet(facet2, pt1, pt2); | |
| if (ret == 2) { | |
| Tuple d; | |
| d.p1 = pt1; | |
| d.p2 = pt2; | |
| d.f1 = element; | |
| d.f2 = index; | |
| intsct.push_back(d); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| bool MeshIntersection::testIntersection(const MeshKernel& k1, const MeshKernel& k2) | |
| { | |
| // Contains bounding boxes for every facet of 'k1' | |
| std::vector<Base::BoundBox3f> boxes1; | |
| MeshFacetIterator cMFI1(k1); | |
| for (cMFI1.Begin(); cMFI1.More(); cMFI1.Next()) { | |
| boxes1.push_back((*cMFI1).GetBoundBox()); | |
| } | |
| // Contains bounding boxes for every facet of 'k2' | |
| std::vector<Base::BoundBox3f> boxes2; | |
| MeshFacetIterator cMFI2(k2); | |
| for (cMFI2.Begin(); cMFI2.More(); cMFI2.Next()) { | |
| boxes2.push_back((*cMFI2).GetBoundBox()); | |
| } | |
| // Splits the mesh using grid for speeding up the calculation | |
| MeshFacetGrid cMeshFacetGrid(k1); | |
| const MeshFacetArray& rFaces2 = k2.GetFacets(); | |
| Base::SequencerLauncher seq("Checking for intersections...", rFaces2.size()); | |
| int index = 0; | |
| MeshGeomFacet facet1, facet2; | |
| Base::Vector3f pt1, pt2; | |
| // Iterate over the facets of the 2nd mesh and find the grid elements of the 1st mesh | |
| for (auto it = rFaces2.begin(); it != rFaces2.end(); ++it, index++) { | |
| seq.next(); | |
| std::vector<FacetIndex> elements; | |
| cMeshFacetGrid.Inside(boxes2[index], elements, true); | |
| cMFI2.Set(index); | |
| facet2 = *cMFI2; | |
| for (FacetIndex element : elements) { | |
| if (boxes2[index] && boxes1[element]) { | |
| cMFI1.Set(element); | |
| facet1 = *cMFI1; | |
| int ret = facet1.IntersectWithFacet(facet2, pt1, pt2); | |
| if (ret == 2) { | |
| // abort after the first detected self-intersection | |
| return true; | |
| } | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| void MeshIntersection::connectLines( | |
| bool onlyclosed, | |
| const std::list<MeshIntersection::Tuple>& rdata, | |
| std::list<std::list<MeshIntersection::Triple>>& lines | |
| ) | |
| { | |
| float fMinEps = minDistance * minDistance; | |
| std::list<Tuple> data = rdata; | |
| while (!data.empty()) { | |
| std::list<Tuple>::iterator pF; | |
| std::list<Triple> newPoly; | |
| // add first line and delete from the list | |
| Triple front, back; | |
| front.f1 = data.begin()->f1; | |
| front.f2 = data.begin()->f2; | |
| front.p = data.begin()->p1; // current start point of the polyline | |
| back.f1 = data.begin()->f1; | |
| back.f2 = data.begin()->f2; | |
| back.p = data.begin()->p2; // current end point of the polyline | |
| newPoly.push_back(front); | |
| newPoly.push_back(back); | |
| data.erase(data.begin()); | |
| // search for the next line on the begin/end of the polyline and add it | |
| std::list<Tuple>::iterator pFront, pEnd; | |
| bool bFoundLine {}; | |
| do { | |
| float fFrontMin = fMinEps, fEndMin = fMinEps; | |
| bool bFrontFirst = false, bEndFirst = false; | |
| pFront = data.end(); | |
| pEnd = data.end(); | |
| bFoundLine = false; | |
| for (pF = data.begin(); pF != data.end(); ++pF) { | |
| if (Base::DistanceP2(front.p, pF->p1) < fFrontMin) { | |
| fFrontMin = Base::DistanceP2(front.p, pF->p1); | |
| pFront = pF; | |
| bFrontFirst = true; | |
| } | |
| else if (Base::DistanceP2(back.p, pF->p1) < fEndMin) { | |
| fEndMin = Base::DistanceP2(back.p, pF->p1); | |
| pEnd = pF; | |
| bEndFirst = true; | |
| } | |
| else if (Base::DistanceP2(front.p, pF->p2) < fFrontMin) { | |
| fFrontMin = Base::DistanceP2(front.p, pF->p2); | |
| pFront = pF; | |
| bFrontFirst = false; | |
| } | |
| else if (Base::DistanceP2(back.p, pF->p2) < fEndMin) { | |
| fEndMin = Base::DistanceP2(back.p, pF->p2); | |
| pEnd = pF; | |
| bEndFirst = false; | |
| } | |
| if (fFrontMin == 0.0F || fEndMin == 0.0F) { | |
| break; | |
| } | |
| } | |
| if (pFront != data.end()) { | |
| bFoundLine = true; | |
| if (bFrontFirst) { | |
| front.f1 = pFront->f1; | |
| front.f2 = pFront->f2; | |
| front.p = pFront->p2; | |
| newPoly.push_front(front); | |
| } | |
| else { | |
| front.f1 = pFront->f1; | |
| front.f2 = pFront->f2; | |
| front.p = pFront->p1; | |
| newPoly.push_front(front); | |
| } | |
| data.erase(pFront); | |
| } | |
| if (pEnd != data.end()) { | |
| bFoundLine = true; | |
| if (bEndFirst) { | |
| back.f1 = pEnd->f1; | |
| back.f2 = pEnd->f2; | |
| back.p = pEnd->p2; | |
| newPoly.push_back(back); | |
| } | |
| else { | |
| back.f1 = pEnd->f1; | |
| back.f2 = pEnd->f2; | |
| back.p = pEnd->p1; | |
| newPoly.push_back(back); | |
| } | |
| data.erase(pEnd); | |
| } | |
| } while (bFoundLine); | |
| if (onlyclosed) { | |
| if (newPoly.size() > 2 | |
| && Base::DistanceP2(newPoly.front().p, newPoly.back().p) < fMinEps) { | |
| lines.push_back(newPoly); | |
| } | |
| } | |
| else { | |
| lines.push_back(newPoly); | |
| } | |
| } | |
| } | |