0025113: Mesh - Progress indication and user break functionality for BRepMesh component
[occt.git] / src / BRepMesh / BRepMesh_NodeInsertionMeshAlgo.hxx
1 // Created on: 2016-07-07
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_NodeInsertionMeshAlgo_HeaderFile
17 #define _BRepMesh_NodeInsertionMeshAlgo_HeaderFile
18
19 #include <BRepMesh_Classifier.hxx>
20 #include <IMeshData_Wire.hxx>
21 #include <IMeshData_Edge.hxx>
22 #include <IMeshData_PCurve.hxx>
23 #include <BRepMesh_Vertex.hxx>
24 #include <TopExp_Explorer.hxx>
25 #include <TopoDS_Vertex.hxx>
26 #include <BRep_Tool.hxx>
27 #include <Standard_ErrorHandler.hxx>
28 #include <BRepMesh_Delaun.hxx>
29
30 //! Extends base meshing algo in order to enable possibility 
31 //! of addition of free vertices into the mesh.
32 template<class RangeSplitter, class BaseAlgo>
33 class BRepMesh_NodeInsertionMeshAlgo : public BaseAlgo
34 {
35 public:
36
37   //! Constructor.
38   BRepMesh_NodeInsertionMeshAlgo()
39   {
40   }
41
42   //! Destructor.
43   virtual ~BRepMesh_NodeInsertionMeshAlgo()
44   {
45   }
46
47   //! Performs processing of the given face.
48   virtual void Perform(
49     const IMeshData::IFaceHandle& theDFace,
50     const IMeshTools_Parameters&  theParameters,
51     const Message_ProgressRange&  theRange) Standard_OVERRIDE
52   {
53     myRangeSplitter.Reset(theDFace, theParameters);
54     myClassifier = new BRepMesh_Classifier;
55     if (!theRange.More())
56     {
57       return;
58     }
59     BaseAlgo::Perform(theDFace, theParameters, theRange);
60     myClassifier.Nullify();
61   }
62
63 protected:
64
65   typedef NCollection_Shared<NCollection_Sequence<const gp_Pnt2d*> > SequenceOfPnt2d;
66
67   //! Performs initialization of data structure using existing model data.
68   virtual Standard_Boolean initDataStructure() Standard_OVERRIDE
69   {
70     Handle(NCollection_IncAllocator) aTmpAlloc = new NCollection_IncAllocator;
71
72     const IMeshData::IFaceHandle& aDFace = this->getDFace();
73     NCollection_Array1<Handle(SequenceOfPnt2d)> aWires(0, aDFace->WiresNb() - 1);
74     for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
75     {
76       const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
77       if (aDWire->IsSet(IMeshData_SelfIntersectingWire) ||
78          (aDWire->IsSet(IMeshData_OpenWire) && aWireIt != 0))
79       {
80         continue;
81       }
82
83       aWires(aWireIt) = collectWirePoints(aDWire, aTmpAlloc);
84     }
85
86     myRangeSplitter.AdjustRange();
87     if (!myRangeSplitter.IsValid())
88     {
89       aDFace->SetStatus(IMeshData_Failure);
90       return Standard_False;
91     }
92
93     const std::pair<Standard_Real, Standard_Real>& aDelta = myRangeSplitter.GetDelta();
94     const std::pair<Standard_Real, Standard_Real>& aTolUV = myRangeSplitter.GetToleranceUV();
95     const Standard_Real uCellSize = 14.0 * aTolUV.first;
96     const Standard_Real vCellSize = 14.0 * aTolUV.second;
97
98     this->getStructure()->Data()->SetCellSize (uCellSize    / aDelta.first, vCellSize     / aDelta.second);
99     this->getStructure()->Data()->SetTolerance(aTolUV.first / aDelta.first, aTolUV.second / aDelta.second);
100
101     for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
102     {
103       const Handle(SequenceOfPnt2d)& aWire = aWires(aWireIt);
104       if (!aWire.IsNull() && !aWire->IsEmpty())
105       {
106         myClassifier->RegisterWire(*aWire, aTolUV,
107                                    myRangeSplitter.GetRangeU(),
108                                    myRangeSplitter.GetRangeV());
109       }
110     }
111
112     if (this->getParameters().InternalVerticesMode)
113     {
114       insertInternalVertices();
115     }
116
117     return BaseAlgo::initDataStructure();
118   }
119
120   //! Adds the given 2d point to mesh data structure.
121   //! Returns index of node in the structure.
122   virtual Standard_Integer addNodeToStructure(
123     const gp_Pnt2d&                thePoint,
124     const Standard_Integer         theLocation3d,
125     const BRepMesh_DegreeOfFreedom theMovability,
126     const Standard_Boolean         isForceAdd) Standard_OVERRIDE
127   {
128     return BaseAlgo::addNodeToStructure(
129       myRangeSplitter.Scale(thePoint, Standard_True),
130       theLocation3d, theMovability, isForceAdd);
131   }
132
133   //! Returns 2d point associated to the given vertex.
134   virtual gp_Pnt2d getNodePoint2d(
135     const BRepMesh_Vertex& theVertex) const Standard_OVERRIDE
136   {
137     return myRangeSplitter.Scale(theVertex.Coord(), Standard_False);
138   }
139
140   //! Returns range splitter.
141   const RangeSplitter& getRangeSplitter() const
142   {
143     return myRangeSplitter;
144   }
145
146   //! Returns classifier.
147   const Handle(BRepMesh_Classifier)& getClassifier() const
148   {
149     return myClassifier;
150   }
151
152 private:
153
154   //! Creates collection of points representing discrete wire.
155   Handle(SequenceOfPnt2d) collectWirePoints(
156     const IMeshData::IWireHandle&           theDWire,
157     const Handle(NCollection_IncAllocator)& theAllocator)
158   {
159     Handle(SequenceOfPnt2d) aWirePoints = new SequenceOfPnt2d(theAllocator);
160     for (Standard_Integer aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt)
161     {
162       const IMeshData::IEdgeHandle    aDEdge = theDWire->GetEdge(aEdgeIt);
163       const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(
164         this->getDFace().get(), theDWire->GetEdgeOrientation(aEdgeIt));
165
166       Standard_Integer aPointIt, aEndIndex, aInc;
167       if (aPCurve->IsForward())
168       {
169         // For an infinite cylinder (for example)
170         // aPCurve->ParametersNb() == 0
171
172         aEndIndex = aPCurve->ParametersNb() - 1;
173         aPointIt = Min(0, aEndIndex);
174         aInc = 1;
175       }
176       else
177       {
178         // For an infinite cylinder (for example)
179         // aPCurve->ParametersNb() == 0
180
181         aPointIt = aPCurve->ParametersNb() - 1;
182         aEndIndex = Min(0, aPointIt);
183         aInc = -1;
184       }
185
186       // For an infinite cylinder (for example)
187       // this cycle will not be executed.
188       for (; aPointIt != aEndIndex; aPointIt += aInc)
189       {
190         const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt);
191         aWirePoints->Append(&aPnt2d);
192         myRangeSplitter.AddPoint(aPnt2d);
193       }
194     }
195
196     return aWirePoints;
197   }
198
199   //! Iterates over internal vertices of a face and 
200   //! creates corresponding nodes in data structure.
201   void insertInternalVertices()
202   {
203     TopExp_Explorer aExplorer(this->getDFace()->GetFace(), TopAbs_VERTEX, TopAbs_EDGE);
204     for (; aExplorer.More(); aExplorer.Next())
205     {
206       const TopoDS_Vertex& aVertex = TopoDS::Vertex(aExplorer.Current());
207       if (aVertex.Orientation() != TopAbs_INTERNAL)
208       {
209         continue;
210       }
211
212       insertInternalVertex(aVertex);
213     }
214   }
215
216   //! Inserts the given vertex into mesh.
217   void insertInternalVertex(const TopoDS_Vertex& theVertex)
218   {
219     try
220     {
221       OCC_CATCH_SIGNALS
222
223         gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, this->getDFace()->GetFace());
224       // check UV values for internal vertices
225       if (myClassifier->Perform(aPnt2d) != TopAbs_IN)
226         return;
227
228       this->registerNode(BRep_Tool::Pnt(theVertex), aPnt2d,
229                          BRepMesh_Fixed, Standard_False);
230     }
231     catch (Standard_Failure const&)
232     {
233     }
234   }
235
236 private:
237
238   RangeSplitter               myRangeSplitter;
239   Handle(BRepMesh_Classifier) myClassifier;
240 };
241
242 #endif