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