7bd071ed |
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 |