0026106: BRepMesh - revision of data model
[occt.git] / src / BRepMesh / BRepMesh_MeshTool.cxx
CommitLineData
7bd071ed 1// Created on: 2016-08-22
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_MeshTool.hxx>
17#include <BRepMesh_SelectorOfDataStructureOfDelaun.hxx>
18#include <stack>
19
20#include <BRepBuilderAPI_MakeFace.hxx>
21#include <BRepBuilderAPI_MakePolygon.hxx>
22#include <BRep_Builder.hxx>
23#include <TopoDS_Compound.hxx>
24#include <BRepTools.hxx>
25#include <gp_Pln.hxx>
26
27namespace
28{
29 //! Returns index of triangle node opposite to the given link.
30 inline Standard_Integer findApexIndex(
31 const Standard_Integer(&aNodes)[3],
32 const BRepMesh_Edge& theLink)
33 {
34 Standard_Integer i = 0;
35 for (; i < 3; ++i)
36 {
37 if (aNodes[i] != theLink.FirstNode() &&
38 aNodes[i] != theLink.LastNode())
39 {
40 break;
41 }
42 }
43
44 return i;
45 }
46}
47
48//=======================================================================
49// Function: Constructor
50// Purpose :
51//=======================================================================
52BRepMesh_MeshTool::BRepMesh_MeshTool(
53 const Handle(BRepMesh_DataStructureOfDelaun)& theStructure)
54 : myStructure(theStructure)
55{
56}
57
58//=======================================================================
59// Function: Destructor
60// Purpose :
61//=======================================================================
62BRepMesh_MeshTool::~BRepMesh_MeshTool()
63{
64}
65
66//=======================================================================
67//function : Legalize
68//purpose :
69//=======================================================================
70void BRepMesh_MeshTool::Legalize(const Standard_Integer theLinkIndex)
71{
72 std::stack<Standard_Integer> aStack;
73 aStack.push(theLinkIndex);
74
75 IMeshData::MapOfInteger aUsedLinks;
76 while (!aStack.empty())
77 {
78 const Standard_Integer aLinkIndex = aStack.top();
79 aStack.pop();
80
81 aUsedLinks.Add(aLinkIndex);
82 const BRepMesh_Edge& aLink = myStructure->GetLink(aLinkIndex);
83 if (aLink.Movability() != BRepMesh_Frontier)
84 {
85 const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aLinkIndex);
86 if (aPair.Extent() == 2)
87 {
88 const BRepMesh_Triangle& aTriangle1 = myStructure->GetElement(aPair.FirstIndex());
89 const BRepMesh_Triangle& aTriangle2 = myStructure->GetElement(aPair.LastIndex());
90
91 Standard_Integer aNodes[2][3];
92 myStructure->ElementNodes(aTriangle1, aNodes[0]);
93 myStructure->ElementNodes(aTriangle2, aNodes[1]);
94
95 const Standard_Integer aApexIndex[2] = {
96 findApexIndex(aNodes[0], aLink),
97 findApexIndex(aNodes[1], aLink)
98 };
99
100 if (checkCircle(aNodes[0], aNodes[1][aApexIndex[1]]) ||
101 checkCircle(aNodes[1], aNodes[0][aApexIndex[0]]))
102 {
103 myStructure->RemoveElement(aPair.FirstIndex());
104 myStructure->RemoveElement(aPair.LastIndex());
105 myStructure->RemoveLink(aLinkIndex);
106
107 addTriangleAndUpdateStack(
108 aNodes[0][(aApexIndex[0])],
109 aNodes[0][(aApexIndex[0] + 1) % 3],
110 aNodes[1][(aApexIndex[1])],
111 aUsedLinks, aStack);
112
113 addTriangleAndUpdateStack(
114 aNodes[1][(aApexIndex[1])],
115 aNodes[1][(aApexIndex[1] + 1) % 3],
116 aNodes[0][(aApexIndex[0])],
117 aUsedLinks, aStack);
118 }
119 }
120 }
121 }
122}
123
124//=======================================================================
125//function : EraseItemsConnectedTo
126//purpose :
127//=======================================================================
128void BRepMesh_MeshTool::EraseItemsConnectedTo(
129 const Standard_Integer theNodeIndex)
130{
131 BRepMesh_SelectorOfDataStructureOfDelaun aSelector(myStructure);
132 aSelector.NeighboursOfNode(theNodeIndex);
133
134 IMeshData::MapOfIntegerInteger aLoopEdges(1, new NCollection_IncAllocator);
135 EraseTriangles(aSelector.Elements(), aLoopEdges);
136 EraseFreeLinks(aLoopEdges);
137 myStructure->RemoveNode(theNodeIndex);
138}
139
140//=======================================================================
141//function : CleanFrontierLinks
142//purpose :
143//=======================================================================
144void BRepMesh_MeshTool::CleanFrontierLinks()
145{
146 Handle(NCollection_IncAllocator) aAlloc = new NCollection_IncAllocator;
147 IMeshData::MapOfInteger aTrianglesToErase;
148 IMeshData::MapOfIntegerInteger aLoopEdges(1, aAlloc);
149
150 Handle(IMeshData::MapOfInteger) aFrontier = GetEdgesByType(BRepMesh_Frontier);
151 IMeshData::IteratorOfMapOfInteger aFrontierIt(*aFrontier);
152 for (; aFrontierIt.More(); aFrontierIt.Next())
153 {
154 Standard_Integer aFrontierId = aFrontierIt.Key();
155 const BRepMesh_Edge& aLink = myStructure->GetLink(aFrontierId);
156
157 Standard_Boolean isTriangleFound = Standard_False;
158 const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aFrontierId);
159 for (Standard_Integer aElemIt = 1; aElemIt <= aPair.Extent() && !isTriangleFound; ++aElemIt)
160 {
161 const Standard_Integer aPriorElemId = aPair.Index(aElemIt);
162 const BRepMesh_Triangle& aElement = myStructure->GetElement(aPriorElemId);
163 const Standard_Integer(&e)[3] = aElement.myEdges;
164 const Standard_Boolean(&o)[3] = aElement.myOrientations;
165
166 for (Standard_Integer n = 0; n < 3 && !isTriangleFound; ++n)
167 {
168 if (aFrontierId == e[n] && !o[n])
169 {
170 // Destruction of external triangles on boundary edges
171 isTriangleFound = Standard_True;
172 aTrianglesToErase.Add(aPriorElemId);
173
174 collectTrianglesOnFreeLinksAroundNodesOf(aLink, e[(n + 1) % 3], aTrianglesToErase);
175 collectTrianglesOnFreeLinksAroundNodesOf(aLink, e[(n + 2) % 3], aTrianglesToErase);
176 }
177 }
178 }
179 }
180
181 EraseTriangles(aTrianglesToErase, aLoopEdges);
182 EraseFreeLinks(aLoopEdges);
183}
184
185//=======================================================================
186//function : EraseTriangles
187//purpose :
188//=======================================================================
189void BRepMesh_MeshTool::EraseTriangles(
190 const IMeshData::MapOfInteger& theTriangles,
191 IMeshData::MapOfIntegerInteger& theLoopEdges)
192{
193 IMeshData::IteratorOfMapOfInteger aFreeTriangles(theTriangles);
194 for (; aFreeTriangles.More(); aFreeTriangles.Next())
195 {
196 EraseTriangle(aFreeTriangles.Key(), theLoopEdges);
197 }
198}
199
200//=======================================================================
201//function : EraseTriangle
202//purpose :
203//=======================================================================
204void BRepMesh_MeshTool::EraseTriangle(
205 const Standard_Integer theTriangleIndex,
206 IMeshData::MapOfIntegerInteger& theLoopEdges)
207{
208 const BRepMesh_Triangle& aElement = myStructure->GetElement(theTriangleIndex);
209 const Standard_Integer(&e)[3] = aElement.myEdges;
210 const Standard_Boolean(&o)[3] = aElement.myOrientations;
211
212 myStructure->RemoveElement(theTriangleIndex);
213
214 for (Standard_Integer i = 0; i < 3; ++i)
215 {
216 if (!theLoopEdges.Bind(e[i], o[i]))
217 {
218 theLoopEdges.UnBind(e[i]);
219 myStructure->RemoveLink(e[i]);
220 }
221 }
222}
223
224//=======================================================================
225//function : EraseFreeLinks
226//purpose :
227//=======================================================================
228void BRepMesh_MeshTool::EraseFreeLinks()
229{
230 for (Standard_Integer i = 1; i <= myStructure->NbLinks(); i++)
231 {
232 if (myStructure->ElementsConnectedTo(i).IsEmpty())
233 {
234 BRepMesh_Edge& anEdge = (BRepMesh_Edge&) myStructure->GetLink(i);
235 if (anEdge.Movability() == BRepMesh_Deleted)
236 {
237 continue;
238 }
239
240 anEdge.SetMovability(BRepMesh_Free);
241 myStructure->RemoveLink(i);
242 }
243 }
244}
245
246//=======================================================================
247//function : collectTrianglesOnFreeLinksAroundNodesOf
248//purpose :
249//=======================================================================
250void BRepMesh_MeshTool::collectTrianglesOnFreeLinksAroundNodesOf(
251 const BRepMesh_Edge& theConstraint,
252 const Standard_Integer theStartLink,
253 IMeshData::MapOfInteger& theTriangles)
254{
255 IMeshData::MapOfInteger aUsedLinks;
256 std::stack<Standard_Integer> aStack;
257 aStack.push(theStartLink);
258 aUsedLinks.Add(theStartLink);
259
260 while (!aStack.empty())
261 {
262 const Standard_Integer aLinkIndex = aStack.top();
263 aStack.pop();
264
265 const BRepMesh_Edge& aLink = myStructure->GetLink(aLinkIndex);
266 if (aLink.Movability() == BRepMesh_Free &&
267 (aLink.FirstNode() == theConstraint.FirstNode() ||
268 aLink.LastNode () == theConstraint.FirstNode() ||
269 aLink.FirstNode() == theConstraint.LastNode () ||
270 aLink.LastNode () == theConstraint.LastNode ()))
271 {
272 const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aLinkIndex);
273 for (Standard_Integer aElemIt = 1; aElemIt <= aPair.Extent(); ++aElemIt)
274 {
275 const Standard_Integer aIndex = aPair.Index(aElemIt);
276 theTriangles.Add(aIndex);
277
278 const BRepMesh_Triangle& aElement = myStructure->GetElement(aIndex);
279 const Standard_Integer(&aEdges)[3] = aElement.myEdges;
280
281 for (Standard_Integer i = 0; i < 3; ++i)
282 {
283 if (aEdges[i] != aLinkIndex && !aUsedLinks.Contains(aEdges[i]))
284 {
285 aUsedLinks.Add(aEdges[i]);
286 aStack .push(aEdges[i]);
287 }
288 }
289 }
290 }
291 }
292}
293
294//=======================================================================
295//function : EraseFreeLinks
296//purpose :
297//=======================================================================
298void BRepMesh_MeshTool::EraseFreeLinks(
299 const IMeshData::MapOfIntegerInteger& theLinks)
300{
301 IMeshData::MapOfIntegerInteger::Iterator aFreeEdges(theLinks);
302 for (; aFreeEdges.More(); aFreeEdges.Next())
303 {
304 if (myStructure->ElementsConnectedTo(aFreeEdges.Key()).IsEmpty())
305 {
306 myStructure->RemoveLink(aFreeEdges.Key());
307 }
308 }
309}
310
311//=======================================================================
312//function : GetEdgesByType
313//purpose :
314//=======================================================================
315Handle(IMeshData::MapOfInteger) BRepMesh_MeshTool::GetEdgesByType(
316 const BRepMesh_DegreeOfFreedom theEdgeType) const
317{
318 Handle(IMeshData::MapOfInteger) aResult = new IMeshData::MapOfInteger;
319 IMeshData::IteratorOfMapOfInteger aEdgeIt(myStructure->LinksOfDomain());
320
321 for (; aEdgeIt.More(); aEdgeIt.Next())
322 {
323 const BRepMesh_Edge& aEdge = myStructure->GetLink(aEdgeIt.Key());
324 if (aEdge.Movability() == theEdgeType)
325 {
326 aResult->Add(aEdgeIt.Key());
327 }
328 }
329
330 return aResult;
331}
332
333//=======================================================================
334//function : DumpStruct
335//purpose :
336//=======================================================================
337void BRepMesh_MeshTool::DumpTriangles(const Standard_CString theFileName,
338 IMeshData::MapOfInteger* theTriangles)
339{
340 BRep_Builder aBuilder;
341 TopoDS_Compound aResult;
342 aBuilder.MakeCompound(aResult);
343
344 const IMeshData::MapOfInteger& aTriangles = myStructure->ElementsOfDomain();
345 for (IMeshData::IteratorOfMapOfInteger aIt(aTriangles); aIt.More(); aIt.Next())
346 {
347 if (theTriangles != NULL && !theTriangles->Contains(aIt.Key()))
348 continue;
349
350 Standard_Integer aNodes[3];
351 const BRepMesh_Triangle& aTri = myStructure->GetElement(aIt.Key());
352 myStructure->ElementNodes(aTri, aNodes);
353
354 const gp_XY& aV1 = myStructure->GetNode(aNodes[0]).Coord();
355 const gp_XY& aV2 = myStructure->GetNode(aNodes[1]).Coord();
356 const gp_XY& aV3 = myStructure->GetNode(aNodes[2]).Coord();
357
358 BRepBuilderAPI_MakePolygon aPoly(gp_Pnt(aV1.X(), aV1.Y(), 0.),
359 gp_Pnt(aV2.X(), aV2.Y(), 0.),
360 gp_Pnt(aV3.X(), aV3.Y(), 0.),
361 Standard_True);
362
363 BRepBuilderAPI_MakeFace aFaceBuilder(gp_Pln(gp::XOY()), aPoly.Wire());
364 aBuilder.Add(aResult, aFaceBuilder.Shape());
365 }
366
367 BRepTools::Write(aResult, theFileName);
368}