1 // Created on: 1993-05-11
2 // Created by: Didier PIFFAULT
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <BRepMesh_DataStructureOfDelaun.hxx>
18 #include <BRepMesh_PairOfIndex.hxx>
19 #include <BRepBuilderAPI_MakeEdge.hxx>
21 #include <TopoDS_Compound.hxx>
22 #include <BRep_Builder.hxx>
23 #include <BRepTools.hxx>
24 #include <Standard_ErrorHandler.hxx>
26 IMPLEMENT_STANDARD_HANDLE (BRepMesh_DataStructureOfDelaun, Standard_Transient)
27 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_DataStructureOfDelaun, Standard_Transient)
29 //=======================================================================
30 //function : BRepMesh_DataStructureOfDelaun
32 //=======================================================================
33 BRepMesh_DataStructureOfDelaun::BRepMesh_DataStructureOfDelaun(
34 const Handle(NCollection_IncAllocator)& theAllocator,
35 const Standard_Integer theReservedNodeSize)
36 : myNodes (theReservedNodeSize, theAllocator),
37 myLinks (theReservedNodeSize * 3),
38 myDelLinks (theAllocator),
39 myElements (theReservedNodeSize * 2),
40 myElementsOfDomain(theReservedNodeSize * 2, theAllocator),
41 myLinksOfDomain (theReservedNodeSize * 2, theAllocator),
42 myAllocator (theAllocator)
46 //=======================================================================
47 //function : SubstituteNode
49 //=======================================================================
50 Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteNode(
51 const Standard_Integer theIndex,
52 const BRepMesh_Vertex& theNewNode)
54 if (myNodes.FindIndex(theNewNode) != 0)
55 return Standard_False;
57 const BRepMesh::ListOfInteger& aLinks = myNodes(theIndex);
58 myNodes.Substitute(theIndex, theNewNode, aLinks);
62 //=======================================================================
65 //=======================================================================
66 Standard_Integer BRepMesh_DataStructureOfDelaun::AddLink(
67 const BRepMesh_Edge& theLink)
69 Standard_Integer aLinkIndex = IndexOf(theLink);
72 return theLink.IsSameOrientation(GetLink(aLinkIndex)) ?
73 aLinkIndex : -aLinkIndex;
76 BRepMesh_PairOfIndex aPair;
77 if (!myDelLinks.IsEmpty())
79 aLinkIndex = myDelLinks.First();
80 myLinks.Substitute(aLinkIndex, theLink, aPair);
81 myDelLinks.RemoveFirst();
84 aLinkIndex = myLinks.Add(theLink, aPair);
86 const Standard_Integer aLinkId = Abs(aLinkIndex);
87 myNodes(theLink.FirstNode()).Append(aLinkId);
88 myNodes(theLink.LastNode() ).Append(aLinkId);
89 myLinksOfDomain.Add(aLinkIndex);
94 //=======================================================================
95 //function : SubstituteLink
97 //=======================================================================
98 Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteLink(
99 const Standard_Integer theIndex,
100 const BRepMesh_Edge& theNewLink)
102 BRepMesh_PairOfIndex aPair;
103 BRepMesh_Edge aLink = GetLink(theIndex);
104 if (aLink.Movability() == BRepMesh_Deleted)
106 myLinks.Substitute(theIndex, theNewLink, aPair);
107 return Standard_True;
110 if (IndexOf(theNewLink) != 0)
111 return Standard_False;
113 aLink.SetMovability(BRepMesh_Deleted);
114 myLinks.Substitute(theIndex, aLink, aPair);
115 cleanLink(theIndex, aLink);
117 const Standard_Integer aLinkId = Abs(theIndex);
118 myNodes(theNewLink.FirstNode()).Append(aLinkId);
119 myNodes(theNewLink.LastNode() ).Append(aLinkId);
120 myLinks.Substitute(theIndex, theNewLink, aPair);
122 return Standard_True;
125 //=======================================================================
126 //function : ForceRemoveLink
128 //=======================================================================
129 void BRepMesh_DataStructureOfDelaun::RemoveLink(
130 const Standard_Integer theIndex,
131 const Standard_Boolean isForce)
133 BRepMesh_Edge& aLink = (BRepMesh_Edge&)GetLink(theIndex);
134 if (aLink.Movability() == BRepMesh_Deleted ||
135 (!isForce && aLink.Movability() != BRepMesh_Free) ||
136 ElementsConnectedTo(theIndex).Extent() != 0)
141 cleanLink(theIndex, aLink);
142 aLink.SetMovability(BRepMesh_Deleted);
144 myLinksOfDomain.Remove(theIndex);
145 myDelLinks.Append (theIndex);
148 //=======================================================================
149 //function : cleanLink
151 //=======================================================================
152 void BRepMesh_DataStructureOfDelaun::cleanLink(
153 const Standard_Integer theIndex,
154 const BRepMesh_Edge& theLink)
156 for (Standard_Integer i = 0; i < 2; ++i)
158 const Standard_Integer aNodeId = (i == 0) ?
159 theLink.FirstNode() : theLink.LastNode();
161 BRepMesh::ListOfInteger& aLinkList = myNodes(aNodeId);
162 BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
163 for(; aLinkIt.More(); aLinkIt.Next())
165 if (aLinkIt.Value() == theIndex)
167 aLinkList.Remove(aLinkIt);
174 //=======================================================================
175 //function : AddElement
177 //=======================================================================
178 Standard_Integer BRepMesh_DataStructureOfDelaun::AddElement(
179 const BRepMesh_Triangle& theElement)
181 Standard_Integer aElementIndex = IndexOf(theElement);
182 if (aElementIndex > 0)
183 return aElementIndex;
185 aElementIndex = myElements.Add(theElement);
186 myElementsOfDomain.Add(aElementIndex);
188 Standard_Integer e[3];
189 Standard_Boolean o[3];
190 theElement.Edges(e, o);
191 for (Standard_Integer i = 0; i < 3; ++i)
192 myLinks(e[i]).Append(aElementIndex);
194 return aElementIndex;
197 //=======================================================================
198 //function : RemoveElement
200 //=======================================================================
201 void BRepMesh_DataStructureOfDelaun::RemoveElement(
202 const Standard_Integer theIndex)
204 BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(theIndex);
205 if (aElement.Movability() == BRepMesh_Deleted)
208 cleanElement(theIndex, aElement);
209 aElement.SetMovability(BRepMesh_Deleted);
210 myElementsOfDomain.Remove(theIndex);
213 //=======================================================================
214 //function : cleanElement
216 //=======================================================================
217 void BRepMesh_DataStructureOfDelaun::cleanElement(
218 const Standard_Integer theIndex,
219 const BRepMesh_Triangle& theElement)
221 if (theElement.Movability() != BRepMesh_Free)
224 Standard_Integer e[3];
225 Standard_Boolean o[3];
226 theElement.Edges(e, o);
228 for (Standard_Integer i = 0; i < 3; ++i)
229 removeElementIndex(theIndex, myLinks(e[i]));
232 //=======================================================================
233 //function : removeElementIndex
235 //=======================================================================
236 void BRepMesh_DataStructureOfDelaun::removeElementIndex(
237 const Standard_Integer theIndex,
238 BRepMesh_PairOfIndex& thePair)
240 for (Standard_Integer i = 1, n = thePair.Extent(); i <= n; ++i)
242 if (thePair.Index(i) == theIndex)
244 thePair.RemoveIndex(i);
250 //=======================================================================
251 //function : SubstituteElement
253 //=======================================================================
254 Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteElement(
255 const Standard_Integer theIndex,
256 const BRepMesh_Triangle& theNewElement)
258 const BRepMesh_Triangle& aElement = GetElement(theIndex);
259 if (aElement.Movability() == BRepMesh_Deleted)
261 myElements.Substitute(theIndex, theNewElement);
262 return Standard_True;
265 if (IndexOf(theNewElement) != 0)
266 return Standard_False;
268 cleanElement(theIndex, aElement);
269 // Warning: here new element and old element should have different Hash code
270 myElements.Substitute(theIndex, theNewElement);
272 Standard_Integer e[3];
273 Standard_Boolean o[3];
274 theNewElement.Edges(e, o);
275 for (Standard_Integer i = 0; i < 3; ++i)
276 myLinks(e[i]).Append(theIndex);
278 return Standard_True;
281 //=======================================================================
282 //function : ElementNodes
284 //=======================================================================
285 void BRepMesh_DataStructureOfDelaun::ElementNodes(
286 const BRepMesh_Triangle& theElement,
287 Standard_Integer (&theNodes)[3])
289 Standard_Integer e[3];
290 Standard_Boolean o[3];
291 theElement.Edges(e, o);
293 const BRepMesh_Edge& aLink1 = GetLink(e[0]);
296 theNodes[0] = aLink1.FirstNode();
297 theNodes[1] = aLink1.LastNode();
301 theNodes[1] = aLink1.FirstNode();
302 theNodes[0] = aLink1.LastNode();
305 const BRepMesh_Edge& aLink2 = GetLink(e[2]);
307 theNodes[2] = aLink2.FirstNode();
309 theNodes[2] = aLink2.LastNode();
312 //=======================================================================
313 //function : ClearDomain
315 //=======================================================================
316 void BRepMesh_DataStructureOfDelaun::ClearDomain()
318 BRepMesh::MapOfInteger aFreeEdges;
319 BRepMesh::MapOfInteger::Iterator aElementIt(myElementsOfDomain);
320 for (; aElementIt.More(); aElementIt.Next())
322 const Standard_Integer aElementId = aElementIt.Key();
323 BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(aElementId);
325 Standard_Integer e[3];
326 Standard_Boolean o[3];
327 aElement.Edges(e, o);
329 for (Standard_Integer i = 0; i < 3; ++i)
330 aFreeEdges.Add(e[i]);
332 cleanElement(aElementId, aElement);
333 aElement.SetMovability(BRepMesh_Deleted);
335 myElementsOfDomain.Clear();
337 BRepMesh::MapOfInteger::Iterator aEdgeIt(aFreeEdges);
338 for (; aEdgeIt.More(); aEdgeIt.Next())
339 RemoveLink(aEdgeIt.Key());
342 //=======================================================================
343 //function : clearDeletedLinks
345 //=======================================================================
346 void BRepMesh_DataStructureOfDelaun::clearDeletedLinks()
348 Standard_Integer aLastLiveItem = NbLinks();
349 while (!myDelLinks.IsEmpty())
351 while (aLastLiveItem > 0)
353 if (GetLink(aLastLiveItem).Movability() != BRepMesh_Deleted)
356 myLinks.RemoveLast();
360 Standard_Integer aDelItem = myDelLinks.First();
361 myDelLinks.RemoveFirst();
363 if (aDelItem > aLastLiveItem)
366 BRepMesh_Edge aLink = GetLink(aLastLiveItem);
367 BRepMesh_PairOfIndex& aPair = myLinks(aLastLiveItem);
369 myLinks.RemoveLast();
370 myLinks.Substitute(aDelItem, aLink, aPair);
372 myLinksOfDomain.Remove(aLastLiveItem);
373 myLinksOfDomain.Add(aDelItem);
376 const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
377 BRepMesh::ListOfInteger::Iterator aLinkIt;
378 // update link references
379 for (Standard_Integer i = 0; i < 2; ++i)
381 const Standard_Integer aCurNodeId = (i == 0) ?
382 aLink.FirstNode() : aLink.LastNode();
384 for (aLinkIt.Init(myNodes(aCurNodeId)); aLinkIt.More(); aLinkIt.Next())
386 Standard_Integer& aLinkId = aLinkIt.ChangeValue();
387 if (aLinkId == aLastLiveItemId)
395 // update elements references
396 for(Standard_Integer j = 1, jn = aPair.Extent(); j <= jn; ++j)
398 const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j));
400 Standard_Integer e[3];
401 Standard_Boolean o[3];
402 aElement.Edges(e, o);
403 for (Standard_Integer i = 0; i < 3; ++i)
405 if (e[i] == aLastLiveItemId)
412 myElements.Substitute(aLinkIt.Value(),
413 BRepMesh_Triangle(e, o, aElement.Movability()));
418 //=======================================================================
419 //function : clearDeletedNodes
421 //=======================================================================
422 void BRepMesh_DataStructureOfDelaun::clearDeletedNodes()
424 BRepMesh::ListOfInteger& aDelNodes =
425 (BRepMesh::ListOfInteger&)myNodes.GetListOfDelNodes();
427 Standard_Integer aLastLiveItem = NbNodes();
428 while (!aDelNodes.IsEmpty())
430 while (aLastLiveItem > 0)
432 if (GetNode(aLastLiveItem).Movability() != BRepMesh_Deleted)
435 myNodes.RemoveLast();
439 Standard_Integer aDelItem = aDelNodes.First();
440 aDelNodes.RemoveFirst();
442 if (aDelItem > aLastLiveItem)
445 BRepMesh_Vertex aNode = GetNode(aLastLiveItem);
446 BRepMesh::ListOfInteger& aLinkList = myNodes(aLastLiveItem);
448 myNodes.RemoveLast();
451 myNodes.Substitute(aDelItem, aNode, aLinkList);
453 const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
454 BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
455 for (; aLinkIt.More(); aLinkIt.Next())
457 const Standard_Integer aLinkId = aLinkIt.Value();
458 const BRepMesh_Edge& aLink = GetLink(aLinkId);
459 BRepMesh_PairOfIndex& aPair = myLinks(aLinkId);
461 Standard_Integer v[2] = { aLink.FirstNode(), aLink.LastNode() };
462 if (v[0] == aLastLiveItemId)
464 else if (v[1] == aLastLiveItemId)
467 myLinks.Substitute(aLinkId,
468 BRepMesh_Edge(v[0], v[1], aLink.Movability()), aPair);
473 //=======================================================================
474 //function : Statistics
476 //=======================================================================
477 void BRepMesh_DataStructureOfDelaun::Statistics(Standard_OStream& theStream) const
479 theStream << " Map of nodes : \n";
480 myNodes.Statistics(theStream);
481 theStream << "\n Deleted nodes : " << myNodes.GetListOfDelNodes().Extent() << endl;
483 theStream << "\n\n Map of Links : \n";
484 myLinks.Statistics(theStream);
485 theStream << "\n Deleted links : " << myDelLinks.Extent() << endl;
487 theStream << "\n\n Map of elements : \n";
488 myElements.Statistics(theStream);
491 //=======================================================================
492 //function : BRepMesh_Write
494 // Global function not declared in any public header, intended for use
495 // from debugger prompt (Command Window in Visual Studio).
497 // Stores the mesh data structure to BRep file with the given name.
498 //=======================================================================
499 Standard_CString BRepMesh_Dump(void* theMeshHandlePtr,
500 Standard_CString theFileNameStr)
502 if (theMeshHandlePtr == 0 || theFileNameStr == 0)
504 return "Error: file name or mesh data is null";
507 Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
508 *(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
510 if (aMeshData.IsNull())
511 return "Error: mesh data is empty";
513 TopoDS_Compound aMesh;
514 BRep_Builder aBuilder;
515 aBuilder.MakeCompound(aMesh);
521 BRepMesh::MapOfInteger::Iterator aLinksIt(aMeshData->LinksOfDomain());
522 for (; aLinksIt.More(); aLinksIt.Next())
524 const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Value());
526 for (Standard_Integer i = 0; i < 2; ++i)
528 const Standard_Integer aNodeId =
529 (i == 0) ? aLink.FirstNode() : aLink.LastNode();
531 const gp_XY& aNode = aMeshData->GetNode(aNodeId).Coord();
532 aPnt[i] = gp_Pnt(aNode.X(), aNode.Y(), 0.);
535 if (aPnt[0].SquareDistance(aPnt[1]) < Precision::SquareConfusion())
538 aBuilder.Add(aMesh, BRepBuilderAPI_MakeEdge(aPnt[0], aPnt[1]));
541 if (!BRepTools::Write(aMesh, theFileNameStr))
542 return "Error: write failed";
544 catch (Standard_Failure)
546 return Standard_Failure::Caught()->GetMessageString();
549 return theFileNameStr;