// 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 * * * ***************************************************************************/ #ifndef MESH_SETOPERATIONS_H #define MESH_SETOPERATIONS_H #include #include #include #include #include "Iterator.h" #include "MeshKernel.h" #include "Visitor.h" // forward declarations namespace MeshCore { class MeshGeomFacet; class MeshGeomEdge; class MeshBuilder; class MeshKernel; class MeshFacetGrid; class MeshFacetArray; class MeshFacetIterator; /** * The MeshAlgorithm class provides algorithms base on meshes. */ class MeshExport SetOperations { public: enum OperationType { Union, Intersect, Difference, Inner, Outer }; /// Construction SetOperations( const MeshKernel& cutMesh1, const MeshKernel& cutMesh2, MeshKernel& result, OperationType opType, float minDistanceToPoint = 1e-5F ); public: /** Cut this mesh with another one. The result is a list of polylines * If the distance of the polyline to one of the points is less than minDistanceToPoint the * polyline goes direct to the point */ void Do(); private: const MeshKernel& _cutMesh0; /** Mesh for set operations source 1 */ const MeshKernel& _cutMesh1; /** Mesh for set operations source 2 */ MeshKernel& _resultMesh; /** Result mesh */ OperationType _operationType; /** Set Operation Type */ float _minDistanceToPoint; /** Minimal distance to facet corner points */ private: // Helper class cutting edge to its two attached facets class Edge { public: MeshPoint pt1, pt2; // edge Edge() = default; Edge(MeshPoint p1, MeshPoint p2) { if (p1 < p2) { pt1 = p1; pt2 = p2; } else { pt2 = p1; pt1 = p2; } } bool operator==(const Edge& edge) const { return (pt1 == edge.pt1) && (pt2 == edge.pt2); } bool operator<(const Edge& edge) const { return (pt1 == edge.pt1) ? (pt2 < edge.pt2) : (pt1 < edge.pt1); } }; class EdgeInfo { public: int fcounter[2] {}; // counter of facets attacted to the edge MeshGeomFacet facets[2][2]; // Geom-Facets attached to the edge FacetIndex facet[2] {}; // underlying Facet-Index }; // class CollectFacetVisitor : public MeshFacetVisitor //{ // public: // std::vector &_facets; // MeshKernel &_mesh; // std::map &_edges; // int _side; // float _mult; // int _addFacets; // 0: add facets to the result 1: do not add // facets to the result Base::Builder3D& _builder; // CollectFacetVisitor (MeshKernel& mesh, std::vector& facets, std::map& edges, int side, float mult, Base::Builder3D& builder); bool Visit (MeshFacet // &rclFacet, const MeshFacet &rclFrom, unsigned long ulFInd, unsigned long ulLevel); bool // AllowVisit (MeshFacet& rclFacet, MeshFacet& rclFrom, unsigned long ulFInd, unsigned long // ulLevel, unsigned short neighbourIndex); //}; class CollectFacetVisitor: public MeshFacetVisitor { public: std::vector& _facets; const MeshKernel& _mesh; std::map& _edges; int _side; float _mult; int _addFacets {-1}; // 0: add facets to the result 1: do not add facets to the result Base::Builder3D& _builder; CollectFacetVisitor( const MeshKernel& mesh, std::vector& facets, std::map& edges, int side, float mult, Base::Builder3D& builder ); bool Visit( const MeshFacet& rclFacet, const MeshFacet& rclFrom, FacetIndex ulFInd, unsigned long ulLevel ) override; bool AllowVisit( const MeshFacet& rclFacet, const MeshFacet& rclFrom, FacetIndex ulFInd, unsigned long ulLevel, unsigned short neighbourIndex ) override; }; /** all points from cut */ std::set _cutPoints; /** all edges */ std::map _edges; /** map from facet index to its cut points (mesh 1 and mesh 2) Key: Facet-Index Value: List of * iterators of set */ std::map::iterator>> _facet2points[2]; /** Facets collected from region growing */ std::vector _facetsOf[2]; std::vector _newMeshFacets[2]; /** Cut mesh 1 with mesh 2 */ void Cut(std::set& facetsCuttingEdge0, std::set& facetsCuttingEdge1); /** Trianglute each facets cut with its cutting points */ void TriangulateMesh(const MeshKernel& cutMesh, int side); /** search facets for adding (with region growing) */ void CollectFacets(int side, float mult); /** close gap in the mesh */ void CloseGaps(MeshBuilder& meshBuilder); /** visual debugger */ Base::Builder3D _builder; }; /*! Determine the intersections between two meshes. */ class MeshExport MeshIntersection { public: struct Tuple { Base::Vector3f p1, p2; FacetIndex f1, f2; }; struct Triple { Base::Vector3f p; FacetIndex f1, f2; }; struct Pair { Base::Vector3f p; FacetIndex f; }; MeshIntersection(const MeshKernel& m1, const MeshKernel& m2, float dist) : kernel1(m1) , kernel2(m2) , minDistance(dist) {} bool hasIntersection() const; void getIntersection(std::list&) const; /*! From an unsorted list of intersection points make a list of sorted intersection points. If parameter \a onlyclosed is set to true then only closed intersection curves are taken and all other curves are filtered out. */ void connectLines(bool onlyclosed, const std::list&, std::list>&); private: static bool testIntersection(const MeshKernel& k1, const MeshKernel& k2); private: const MeshKernel& kernel1; const MeshKernel& kernel2; float minDistance; }; } // namespace MeshCore #endif // MESH_SETOPERATIONS_H