7bd071ed |
1 | // Created on: 2016-04-19 |
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 | #include <BRepMesh_BaseMeshAlgo.hxx> |
7bd071ed |
17 | #include <IMeshData_Wire.hxx> |
18 | #include <IMeshData_Edge.hxx> |
19 | #include <IMeshData_PCurve.hxx> |
20 | #include <IMeshData_Curve.hxx> |
21 | #include <BRepMesh_Delaun.hxx> |
22 | #include <BRepMesh_ShapeTool.hxx> |
23 | #include <Standard_ErrorHandler.hxx> |
24 | |
4945e8be |
25 | IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_BaseMeshAlgo, IMeshTools_MeshAlgo) |
26 | |
7bd071ed |
27 | //======================================================================= |
28 | // Function: Constructor |
29 | // Purpose : |
30 | //======================================================================= |
31 | BRepMesh_BaseMeshAlgo::BRepMesh_BaseMeshAlgo() |
32 | { |
33 | } |
34 | |
35 | //======================================================================= |
36 | // Function: Destructor |
37 | // Purpose : |
38 | //======================================================================= |
39 | BRepMesh_BaseMeshAlgo::~BRepMesh_BaseMeshAlgo() |
40 | { |
41 | } |
42 | |
43 | //======================================================================= |
44 | // Function: Perform |
45 | // Purpose : |
46 | //======================================================================= |
47 | void BRepMesh_BaseMeshAlgo::Perform( |
48 | const IMeshData::IFaceHandle& theDFace, |
ce97cd97 |
49 | const IMeshTools_Parameters& theParameters, |
50 | const Message_ProgressRange& theRange) |
7bd071ed |
51 | { |
52 | try |
53 | { |
54 | OCC_CATCH_SIGNALS |
55 | |
56 | myDFace = theDFace; |
57 | myParameters = theParameters; |
58 | myAllocator = new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); |
59 | myStructure = new BRepMesh_DataStructureOfDelaun(myAllocator); |
60 | myNodesMap = new VectorOfPnt(256, myAllocator); |
61 | myUsedNodes = new DMapOfIntegerInteger(1, myAllocator); |
62 | |
63 | if (initDataStructure()) |
64 | { |
ce97cd97 |
65 | if (!theRange.More()) |
66 | { |
67 | return; |
68 | } |
69 | generateMesh(theRange); |
7bd071ed |
70 | commitSurfaceTriangulation(); |
71 | } |
72 | } |
21c7c457 |
73 | catch (Standard_Failure const& /*theException*/) |
7bd071ed |
74 | { |
75 | } |
76 | |
77 | myDFace.Nullify(); // Do not hold link to face. |
78 | myStructure.Nullify(); |
79 | myNodesMap .Nullify(); |
80 | myUsedNodes.Nullify(); |
81 | myAllocator.Nullify(); |
82 | } |
83 | |
84 | //======================================================================= |
85 | //function : initDataStructure |
86 | //purpose : |
87 | //======================================================================= |
88 | Standard_Boolean BRepMesh_BaseMeshAlgo::initDataStructure() |
89 | { |
90 | for (Standard_Integer aWireIt = 0; aWireIt < myDFace->WiresNb(); ++aWireIt) |
91 | { |
92 | const IMeshData::IWireHandle& aDWire = myDFace->GetWire(aWireIt); |
93 | if (aDWire->IsSet(IMeshData_SelfIntersectingWire)) |
94 | { |
95 | // TODO: here we can add points of self-intersecting wire as fixed points |
96 | // in order to keep consistency of nodes with adjacent faces. |
97 | continue; |
98 | } |
99 | |
100 | for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt) |
101 | { |
102 | const IMeshData::IEdgeHandle aDEdge = aDWire->GetEdge(aEdgeIt); |
103 | const IMeshData::ICurveHandle& aCurve = aDEdge->GetCurve(); |
104 | const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve( |
105 | myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt)); |
106 | |
107 | const TopAbs_Orientation aOri = fixSeamEdgeOrientation(aDEdge, aPCurve); |
108 | |
109 | Standard_Integer aPrevNodeIndex = -1; |
110 | const Standard_Integer aLastPoint = aPCurve->ParametersNb() - 1; |
111 | for (Standard_Integer aPointIt = 0; aPointIt <= aLastPoint; ++aPointIt) |
112 | { |
113 | const Standard_Integer aNodeIndex = registerNode( |
114 | aCurve ->GetPoint(aPointIt), |
115 | aPCurve->GetPoint(aPointIt), |
116 | BRepMesh_Frontier, Standard_False/*aPointIt > 0 && aPointIt < aLastPoint*/); |
117 | |
118 | aPCurve->GetIndex(aPointIt) = aNodeIndex; |
119 | myUsedNodes->Bind(aNodeIndex, aNodeIndex); |
120 | |
121 | if (aPrevNodeIndex != -1 && aPrevNodeIndex != aNodeIndex) |
122 | { |
123 | const Standard_Integer aLinksNb = myStructure->NbLinks(); |
124 | const Standard_Integer aLinkIndex = addLinkToMesh(aPrevNodeIndex, aNodeIndex, aOri); |
125 | if (aWireIt != 0 && aLinkIndex <= aLinksNb) |
126 | { |
127 | // Prevent holes around wire of zero area. |
128 | BRepMesh_Edge& aLink = const_cast<BRepMesh_Edge&>(myStructure->GetLink(aLinkIndex)); |
129 | aLink.SetMovability(BRepMesh_Fixed); |
130 | } |
131 | } |
132 | |
133 | aPrevNodeIndex = aNodeIndex; |
134 | } |
135 | } |
136 | } |
137 | |
138 | return Standard_True; |
139 | } |
140 | |
141 | //======================================================================= |
142 | // Function: registerNode |
143 | // Purpose : |
144 | //======================================================================= |
145 | Standard_Integer BRepMesh_BaseMeshAlgo::registerNode( |
146 | const gp_Pnt& thePoint, |
147 | const gp_Pnt2d& thePoint2d, |
148 | const BRepMesh_DegreeOfFreedom theMovability, |
149 | const Standard_Boolean isForceAdd) |
150 | { |
151 | const Standard_Integer aNodeIndex = addNodeToStructure( |
152 | thePoint2d, myNodesMap->Size(), theMovability, isForceAdd); |
153 | |
154 | if (aNodeIndex > myNodesMap->Size()) |
155 | { |
156 | myNodesMap->Append(thePoint); |
157 | } |
158 | |
159 | return aNodeIndex; |
160 | } |
161 | |
162 | //======================================================================= |
163 | // Function: addNode |
164 | // Purpose : |
165 | //======================================================================= |
166 | Standard_Integer BRepMesh_BaseMeshAlgo::addNodeToStructure( |
167 | const gp_Pnt2d& thePoint, |
168 | const Standard_Integer theLocation3d, |
169 | const BRepMesh_DegreeOfFreedom theMovability, |
170 | const Standard_Boolean isForceAdd) |
171 | { |
172 | BRepMesh_Vertex aNode(thePoint.XY(), theLocation3d, theMovability); |
173 | return myStructure->AddNode(aNode, isForceAdd); |
174 | } |
175 | |
176 | //======================================================================= |
177 | //function : addLinkToMesh |
178 | //purpose : |
179 | //======================================================================= |
180 | Standard_Integer BRepMesh_BaseMeshAlgo::addLinkToMesh( |
181 | const Standard_Integer theFirstNodeId, |
182 | const Standard_Integer theLastNodeId, |
183 | const TopAbs_Orientation theOrientation) |
184 | { |
185 | Standard_Integer aLinkIndex; |
186 | if (theOrientation == TopAbs_REVERSED) |
187 | aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theLastNodeId, theFirstNodeId, BRepMesh_Frontier)); |
188 | else if (theOrientation == TopAbs_INTERNAL) |
189 | aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Fixed)); |
190 | else |
191 | aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Frontier)); |
192 | |
193 | return Abs(aLinkIndex); |
194 | } |
195 | |
196 | //======================================================================= |
197 | //function : fixSeamEdgeOrientation |
198 | //purpose : |
199 | //======================================================================= |
200 | TopAbs_Orientation BRepMesh_BaseMeshAlgo::fixSeamEdgeOrientation( |
201 | const IMeshData::IEdgeHandle& theDEdge, |
202 | const IMeshData::IPCurveHandle& thePCurve) const |
203 | { |
204 | for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt) |
205 | { |
206 | const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt); |
207 | if (aPCurve->GetFace() == myDFace && thePCurve != aPCurve) |
208 | { |
209 | // Simple check that another pcurve of seam edge does not coincide with reference one. |
210 | const gp_Pnt2d& aPnt1_1 = thePCurve->GetPoint(0); |
211 | const gp_Pnt2d& aPnt2_1 = thePCurve->GetPoint(thePCurve->ParametersNb() - 1); |
212 | |
213 | const gp_Pnt2d& aPnt1_2 = aPCurve->GetPoint(0); |
214 | const gp_Pnt2d& aPnt2_2 = aPCurve->GetPoint(aPCurve->ParametersNb() - 1); |
215 | |
216 | const Standard_Real aSqDist1 = Min(aPnt1_1.SquareDistance(aPnt1_2), aPnt1_1.SquareDistance(aPnt2_2)); |
217 | const Standard_Real aSqDist2 = Min(aPnt2_1.SquareDistance(aPnt1_2), aPnt2_1.SquareDistance(aPnt2_2)); |
218 | if (aSqDist1 < Precision::SquareConfusion() && |
219 | aSqDist2 < Precision::SquareConfusion()) |
220 | { |
221 | return TopAbs_INTERNAL; |
222 | } |
223 | } |
224 | } |
225 | |
226 | return thePCurve->GetOrientation(); |
227 | } |
228 | |
229 | //======================================================================= |
230 | //function : commitSurfaceTriangulation |
231 | //purpose : |
232 | //======================================================================= |
233 | void BRepMesh_BaseMeshAlgo::commitSurfaceTriangulation() |
234 | { |
235 | Handle(Poly_Triangulation) aTriangulation = collectTriangles(); |
236 | if (aTriangulation.IsNull()) |
237 | { |
238 | myDFace->SetStatus(IMeshData_Failure); |
239 | return; |
240 | } |
241 | |
242 | collectNodes(aTriangulation); |
243 | |
7bd071ed |
244 | BRepMesh_ShapeTool::AddInFace(myDFace->GetFace(), aTriangulation); |
245 | } |
246 | |
247 | //======================================================================= |
248 | //function : collectTriangles |
249 | //purpose : |
250 | //======================================================================= |
251 | Handle(Poly_Triangulation) BRepMesh_BaseMeshAlgo::collectTriangles() |
252 | { |
253 | const IMeshData::MapOfInteger& aTriangles = myStructure->ElementsOfDomain(); |
254 | if (aTriangles.IsEmpty()) |
255 | { |
256 | return Handle(Poly_Triangulation)(); |
257 | } |
258 | |
a8b605eb |
259 | Handle(Poly_Triangulation) aRes = new Poly_Triangulation(); |
260 | aRes->ResizeTriangles (aTriangles.Extent(), false); |
7bd071ed |
261 | IMeshData::IteratorOfMapOfInteger aTriIt(aTriangles); |
262 | for (Standard_Integer aTriangeId = 1; aTriIt.More(); aTriIt.Next(), ++aTriangeId) |
263 | { |
264 | const BRepMesh_Triangle& aCurElem = myStructure->GetElement(aTriIt.Key()); |
265 | |
266 | Standard_Integer aNode[3]; |
267 | myStructure->ElementNodes(aCurElem, aNode); |
268 | |
269 | for (Standard_Integer i = 0; i < 3; ++i) |
270 | { |
271 | if (!myUsedNodes->IsBound(aNode[i])) |
272 | { |
273 | myUsedNodes->Bind(aNode[i], myUsedNodes->Size() + 1); |
274 | } |
275 | |
276 | aNode[i] = myUsedNodes->Find(aNode[i]); |
277 | } |
278 | |
a8b605eb |
279 | aRes->SetTriangle (aTriangeId, Poly_Triangle (aNode[0], aNode[1], aNode[2])); |
7bd071ed |
280 | } |
a8b605eb |
281 | aRes->ResizeNodes (myUsedNodes->Extent(), false); |
282 | aRes->AddUVNodes(); |
283 | return aRes; |
7bd071ed |
284 | } |
285 | |
286 | //======================================================================= |
287 | //function : collectNodes |
288 | //purpose : |
289 | //======================================================================= |
290 | void BRepMesh_BaseMeshAlgo::collectNodes( |
291 | const Handle(Poly_Triangulation)& theTriangulation) |
292 | { |
7bd071ed |
293 | for (Standard_Integer i = 1; i <= myNodesMap->Size(); ++i) |
294 | { |
295 | if (myUsedNodes->IsBound(i)) |
296 | { |
297 | const BRepMesh_Vertex& aVertex = myStructure->GetNode(i); |
298 | |
299 | const Standard_Integer aNodeIndex = myUsedNodes->Find(i); |
a8b605eb |
300 | theTriangulation->SetNode (aNodeIndex, myNodesMap->Value (aVertex.Location3d())); |
301 | theTriangulation->SetUVNode(aNodeIndex, getNodePoint2d (aVertex)); |
7bd071ed |
302 | } |
303 | } |
304 | } |
305 | |
306 | //======================================================================= |
307 | // Function: getNodePoint2d |
308 | // Purpose : |
309 | //======================================================================= |
310 | gp_Pnt2d BRepMesh_BaseMeshAlgo::getNodePoint2d( |
311 | const BRepMesh_Vertex& theVertex) const |
312 | { |
313 | return theVertex.Coord(); |
314 | } |