14d804e9d7868951f0014e35e3c29e0d5ea4ff4f
[occt.git] / src / BRepMesh / BRepMesh_ModelHealer.hxx
1 // Created on: 2016-06-23
2 // Copyright (c) 2016 OPEN CASCADE SAS
3 // Created by: Oleg AGASHIN
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef _BRepMesh_ModelHealer_HeaderFile
17 #define _BRepMesh_ModelHealer_HeaderFile
18
19 #include <IMeshTools_ModelAlgo.hxx>
20 #include <IMeshTools_Parameters.hxx>
21 #include <IMeshData_Types.hxx>
22 #include <IMeshData_Model.hxx>
23 #include <TopoDS_Vertex.hxx>
24
25 //! Class implements functionality of model healer tool.
26 //! Iterates over model's faces and checks consistency of their wires, 
27 //! i.e.whether wires are closed and do not contain self - intersections.
28 //! In case if wire contains disconnected parts, ends of adjacent edges 
29 //! forming the gaps are connected in parametric space forcibly. The notion 
30 //! of this operation is to create correct discrete model defined relatively 
31 //! parametric space of target face taking into account connectivity and 
32 //! tolerances of 3D space only. This means that there are no specific 
33 //! computations are made for the sake of determination of U and V tolerance.
34 //! Registers intersections on edges forming the face\92s shape and tries to 
35 //! amplify discrete represenation by decreasing of deflection for the target edge. 
36 //! Checks can be performed in parallel mode.
37 class BRepMesh_ModelHealer : public IMeshTools_ModelAlgo
38 {
39 public:
40
41   //! Constructor.
42   Standard_EXPORT BRepMesh_ModelHealer();
43
44   //! Destructor.
45   Standard_EXPORT virtual ~BRepMesh_ModelHealer();
46
47   //! Functor API to discretize the given edge.
48   inline void operator() (const Standard_Integer theEdgeIndex) const {
49     process(theEdgeIndex);
50   }
51
52   //! Functor API to discretize the given edge.
53   inline void operator() (const IMeshData::IFaceHandle& theDFace) const {
54     process(theDFace);
55   }
56
57   DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelHealer, IMeshTools_ModelAlgo)
58
59 protected:
60
61   //! Performs processing of edges of the given model.
62   Standard_EXPORT virtual Standard_Boolean performInternal (
63     const Handle(IMeshData_Model)& theModel,
64     const IMeshTools_Parameters&   theParameters) Standard_OVERRIDE;
65
66 private:
67
68   //! Checks existing discretization of the face and updates data model.
69   inline void process(const Standard_Integer theFaceIndex) const
70   {
71     const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
72     process(aDFace);
73   }
74
75   //! Checks existing discretization of the face and updates data model.
76   void process(const IMeshData::IFaceHandle& theDFace) const;
77
78   //! Amplifies discretization of edges in case if self-intersection problem has been found.
79   void amplifyEdges();
80
81   //! Returns common vertex of two edges or null ptr in case if there is no such vertex.
82   TopoDS_Vertex getCommonVertex(
83     const IMeshData::IEdgeHandle& theEdge1,
84     const IMeshData::IEdgeHandle& theEdge2) const;
85
86   //! Connects pcurves of previous and current edge on the specified face 
87   //! according to topological connectivity. Uses next edge in order to
88   //! identify closest point in case of signle vertex shared between both
89   //! ends of edge (degenerative edge)
90   Standard_Boolean connectClosestPoints(
91     const IMeshData::IPCurveHandle& thePrevDEdge,
92     const IMeshData::IPCurveHandle& theCurrDEdge,
93     const IMeshData::IPCurveHandle& theNextDEdge) const;
94
95   //! Chooses the most closest point to reference one from the given pair.
96   //! Returns square distance between reference point and closest one as 
97   //! well as pointer to closest point.
98   inline Standard_Real closestPoint(
99     gp_Pnt2d&  theRefPnt,
100     gp_Pnt2d&  theFristPnt,
101     gp_Pnt2d&  theSecondPnt,
102     gp_Pnt2d*& theClosestPnt) const
103   {
104     // Find the most closest end-points.
105     const Standard_Real aSqDist1 = theRefPnt.SquareDistance(theFristPnt);
106     const Standard_Real aSqDist2 = theRefPnt.SquareDistance(theSecondPnt);
107     if (aSqDist1 < aSqDist2)
108     {
109       theClosestPnt = &theFristPnt;
110       return aSqDist1;
111     }
112
113     theClosestPnt = &theSecondPnt;
114     return aSqDist2;
115   }
116
117   //! Chooses the most closest points among the given to reference one from the given pair.
118   //! Returns square distance between reference point and closest one as 
119   //! well as pointer to closest point.
120   inline Standard_Real closestPoints(
121     gp_Pnt2d&  theFirstPnt1,
122     gp_Pnt2d&  theSecondPnt1,
123     gp_Pnt2d&  theFirstPnt2,
124     gp_Pnt2d&  theSecondPnt2,
125     gp_Pnt2d*& theClosestPnt1,
126     gp_Pnt2d*& theClosestPnt2) const
127   {
128     gp_Pnt2d *aCurrPrevUV1 = NULL, *aCurrPrevUV2 = NULL;
129     const Standard_Real aSqDist1 = closestPoint(theFirstPnt1,  theFirstPnt2, theSecondPnt2, aCurrPrevUV1);
130     const Standard_Real aSqDist2 = closestPoint(theSecondPnt1, theFirstPnt2, theSecondPnt2, aCurrPrevUV2);
131     if (aSqDist1 - aSqDist2 < gp::Resolution())
132     {
133       theClosestPnt1 = &theFirstPnt1;
134       theClosestPnt2 = aCurrPrevUV1;
135       return aSqDist1;
136     }
137
138     theClosestPnt1 = &theSecondPnt1;
139     theClosestPnt2 = aCurrPrevUV2;
140     return aSqDist2;
141   }
142
143   //! Adjusts the given pair of points supposed to be the same.
144   //! In addition, adjusts another end-point of an edge in order
145   //! to perform correct matching in case of gap.
146   inline void adjustSamePoints(
147     gp_Pnt2d*& theMajorSamePnt1,
148     gp_Pnt2d*& theMinorSamePnt1,
149     gp_Pnt2d*& theMajorSamePnt2,
150     gp_Pnt2d*& theMinorSamePnt2,
151     gp_Pnt2d&  theMajorFirstPnt,
152     gp_Pnt2d&  theMajorLastPnt,
153     gp_Pnt2d&  theMinorFirstPnt,
154     gp_Pnt2d&  theMinorLastPnt) const
155   {
156     if (theMajorSamePnt2 == theMajorSamePnt1)
157     {
158       theMajorSamePnt2 = (theMajorSamePnt2 == &theMajorFirstPnt) ? &theMajorLastPnt : &theMajorFirstPnt;
159       closestPoint(*theMajorSamePnt2, theMinorFirstPnt, theMinorLastPnt, theMinorSamePnt2);
160     }
161
162     *theMajorSamePnt1 = *theMinorSamePnt1;
163     *theMajorSamePnt2 = *theMinorSamePnt2;
164   }
165
166   //! Connects ends of pcurves of face's wires according to topological coherency.
167   void fixFaceBoundaries(const IMeshData::IFaceHandle& theDFace) const;
168
169   //! Returns True if check can be done in parallel.
170   inline Standard_Boolean isParallel() const
171   {
172     return (myParameters.InParallel && myModel->FacesNb() > 1);
173   }
174
175   //! Collects unique edges to be updated from face map. Clears data stored in face map.
176   Standard_Boolean popEdgesToUpdate(IMeshData::MapOfIEdgePtr& theEdgesToUpdate);
177
178 private:
179
180   Handle(IMeshData_Model)                           myModel;
181   IMeshTools_Parameters                             myParameters;
182   Handle(IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs)  myFaceIntersectingEdges;
183 };
184
185 #endif