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>
20 #include <BRepBuilderAPI_MakeVertex.hxx>
22 #include <TopoDS_Compound.hxx>
23 #include <BRep_Builder.hxx>
24 #include <BRepTools.hxx>
25 #include <Standard_ErrorHandler.hxx>
28 //=======================================================================
29 //function : BRepMesh_DataStructureOfDelaun
31 //=======================================================================
32 BRepMesh_DataStructureOfDelaun::BRepMesh_DataStructureOfDelaun(
33 const Handle(NCollection_IncAllocator)& theAllocator,
34 const Standard_Integer theReservedNodeSize)
35 : myAllocator (theAllocator),
36 myNodes (new BRepMesh_VertexTool(theReservedNodeSize, myAllocator)),
37 myLinks (theReservedNodeSize * 3, myAllocator),
38 myDelLinks (myAllocator),
39 myElements (theReservedNodeSize * 2, myAllocator),
40 myElementsOfDomain(theReservedNodeSize * 2, myAllocator),
41 myLinksOfDomain (theReservedNodeSize * 2, myAllocator)
45 //=======================================================================
46 //function : SubstituteNode
48 //=======================================================================
49 Standard_Integer BRepMesh_DataStructureOfDelaun::AddNode(
50 const BRepMesh_Vertex& theNode,
51 const Standard_Boolean isForceAdd)
53 const Standard_Integer aNodeId = myNodes->Add(theNode, isForceAdd);
54 if (!myNodeLinks.IsBound(aNodeId))
55 myNodeLinks.Bind(aNodeId, BRepMesh::ListOfInteger(myAllocator));
60 //=======================================================================
61 //function : SubstituteNode
63 //=======================================================================
64 Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteNode(
65 const Standard_Integer theIndex,
66 const BRepMesh_Vertex& theNewNode)
68 if (myNodes->FindIndex(theNewNode) != 0)
69 return Standard_False;
71 myNodes->Substitute(theIndex, theNewNode);
75 //=======================================================================
78 //=======================================================================
79 Standard_Integer BRepMesh_DataStructureOfDelaun::AddLink(
80 const BRepMesh_Edge& theLink)
82 Standard_Integer aLinkIndex = IndexOf(theLink);
85 return theLink.IsSameOrientation(GetLink(aLinkIndex)) ?
86 aLinkIndex : -aLinkIndex;
89 BRepMesh_PairOfIndex aPair;
90 if (!myDelLinks.IsEmpty())
92 aLinkIndex = myDelLinks.First();
93 myLinks.Substitute(aLinkIndex, theLink, aPair);
94 myDelLinks.RemoveFirst();
97 aLinkIndex = myLinks.Add(theLink, aPair);
99 const Standard_Integer aLinkId = Abs(aLinkIndex);
100 linksConnectedTo(theLink.FirstNode()).Append(aLinkId);
101 linksConnectedTo(theLink.LastNode() ).Append(aLinkId);
102 myLinksOfDomain.Add(aLinkIndex);
107 //=======================================================================
108 //function : SubstituteLink
110 //=======================================================================
111 Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteLink(
112 const Standard_Integer theIndex,
113 const BRepMesh_Edge& theNewLink)
115 BRepMesh_PairOfIndex aPair;
116 BRepMesh_Edge aLink = GetLink(theIndex);
117 if (aLink.Movability() == BRepMesh_Deleted)
119 myLinks.Substitute(theIndex, theNewLink, aPair);
120 return Standard_True;
123 if (IndexOf(theNewLink) != 0)
124 return Standard_False;
126 aLink.SetMovability(BRepMesh_Deleted);
127 myLinks.Substitute(theIndex, aLink, aPair);
128 cleanLink(theIndex, aLink);
130 const Standard_Integer aLinkId = Abs(theIndex);
131 linksConnectedTo(theNewLink.FirstNode()).Append(aLinkId);
132 linksConnectedTo(theNewLink.LastNode() ).Append(aLinkId);
133 myLinks.Substitute(theIndex, theNewLink, aPair);
135 return Standard_True;
138 //=======================================================================
139 //function : ForceRemoveLink
141 //=======================================================================
142 void BRepMesh_DataStructureOfDelaun::RemoveLink(
143 const Standard_Integer theIndex,
144 const Standard_Boolean isForce)
146 BRepMesh_Edge& aLink = (BRepMesh_Edge&)GetLink(theIndex);
147 if (aLink.Movability() == BRepMesh_Deleted ||
148 (!isForce && aLink.Movability() != BRepMesh_Free) ||
149 ElementsConnectedTo(theIndex).Extent() != 0)
154 cleanLink(theIndex, aLink);
155 aLink.SetMovability(BRepMesh_Deleted);
157 myLinksOfDomain.Remove(theIndex);
158 myDelLinks.Append (theIndex);
161 //=======================================================================
162 //function : cleanLink
164 //=======================================================================
165 void BRepMesh_DataStructureOfDelaun::cleanLink(
166 const Standard_Integer theIndex,
167 const BRepMesh_Edge& theLink)
169 for (Standard_Integer i = 0; i < 2; ++i)
171 const Standard_Integer aNodeId = (i == 0) ?
172 theLink.FirstNode() : theLink.LastNode();
174 BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aNodeId);
175 BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
176 for(; aLinkIt.More(); aLinkIt.Next())
178 if (aLinkIt.Value() == theIndex)
180 aLinkList.Remove(aLinkIt);
187 //=======================================================================
188 //function : AddElement
190 //=======================================================================
191 Standard_Integer BRepMesh_DataStructureOfDelaun::AddElement(
192 const BRepMesh_Triangle& theElement)
194 Standard_Integer aElementIndex = IndexOf(theElement);
195 if (aElementIndex > 0)
196 return aElementIndex;
198 aElementIndex = myElements.Add(theElement);
199 myElementsOfDomain.Add(aElementIndex);
201 Standard_Integer e[3];
202 Standard_Boolean o[3];
203 theElement.Edges(e, o);
204 for (Standard_Integer i = 0; i < 3; ++i)
205 myLinks(e[i]).Append(aElementIndex);
207 return aElementIndex;
210 //=======================================================================
211 //function : RemoveElement
213 //=======================================================================
214 void BRepMesh_DataStructureOfDelaun::RemoveElement(
215 const Standard_Integer theIndex)
217 BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(theIndex);
218 if (aElement.Movability() == BRepMesh_Deleted)
221 cleanElement(theIndex, aElement);
222 aElement.SetMovability(BRepMesh_Deleted);
223 myElementsOfDomain.Remove(theIndex);
226 //=======================================================================
227 //function : cleanElement
229 //=======================================================================
230 void BRepMesh_DataStructureOfDelaun::cleanElement(
231 const Standard_Integer theIndex,
232 const BRepMesh_Triangle& theElement)
234 if (theElement.Movability() != BRepMesh_Free)
237 Standard_Integer e[3];
238 Standard_Boolean o[3];
239 theElement.Edges(e, o);
241 for (Standard_Integer i = 0; i < 3; ++i)
242 removeElementIndex(theIndex, myLinks(e[i]));
245 //=======================================================================
246 //function : removeElementIndex
248 //=======================================================================
249 void BRepMesh_DataStructureOfDelaun::removeElementIndex(
250 const Standard_Integer theIndex,
251 BRepMesh_PairOfIndex& thePair)
253 for (Standard_Integer i = 1, n = thePair.Extent(); i <= n; ++i)
255 if (thePair.Index(i) == theIndex)
257 thePair.RemoveIndex(i);
263 //=======================================================================
264 //function : SubstituteElement
266 //=======================================================================
267 Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteElement(
268 const Standard_Integer theIndex,
269 const BRepMesh_Triangle& theNewElement)
271 const BRepMesh_Triangle& aElement = GetElement(theIndex);
272 if (aElement.Movability() == BRepMesh_Deleted)
274 myElements.Substitute(theIndex, theNewElement);
275 return Standard_True;
278 if (IndexOf(theNewElement) != 0)
279 return Standard_False;
281 cleanElement(theIndex, aElement);
282 // Warning: here new element and old element should have different Hash code
283 myElements.Substitute(theIndex, theNewElement);
285 Standard_Integer e[3];
286 Standard_Boolean o[3];
287 theNewElement.Edges(e, o);
288 for (Standard_Integer i = 0; i < 3; ++i)
289 myLinks(e[i]).Append(theIndex);
291 return Standard_True;
294 //=======================================================================
295 //function : ElementNodes
297 //=======================================================================
298 void BRepMesh_DataStructureOfDelaun::ElementNodes(
299 const BRepMesh_Triangle& theElement,
300 Standard_Integer (&theNodes)[3])
302 Standard_Integer e[3];
303 Standard_Boolean o[3];
304 theElement.Edges(e, o);
306 const BRepMesh_Edge& aLink1 = GetLink(e[0]);
309 theNodes[0] = aLink1.FirstNode();
310 theNodes[1] = aLink1.LastNode();
314 theNodes[1] = aLink1.FirstNode();
315 theNodes[0] = aLink1.LastNode();
318 const BRepMesh_Edge& aLink2 = GetLink(e[2]);
320 theNodes[2] = aLink2.FirstNode();
322 theNodes[2] = aLink2.LastNode();
325 //=======================================================================
326 //function : ClearDomain
328 //=======================================================================
329 void BRepMesh_DataStructureOfDelaun::ClearDomain()
331 BRepMesh::MapOfInteger aFreeEdges;
332 BRepMesh::MapOfInteger::Iterator aElementIt(myElementsOfDomain);
333 for (; aElementIt.More(); aElementIt.Next())
335 const Standard_Integer aElementId = aElementIt.Key();
336 BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(aElementId);
338 Standard_Integer e[3];
339 Standard_Boolean o[3];
340 aElement.Edges(e, o);
342 for (Standard_Integer i = 0; i < 3; ++i)
343 aFreeEdges.Add(e[i]);
345 cleanElement(aElementId, aElement);
346 aElement.SetMovability(BRepMesh_Deleted);
348 myElementsOfDomain.Clear();
350 BRepMesh::MapOfInteger::Iterator aEdgeIt(aFreeEdges);
351 for (; aEdgeIt.More(); aEdgeIt.Next())
352 RemoveLink(aEdgeIt.Key());
355 //=======================================================================
356 //function : clearDeletedLinks
358 //=======================================================================
359 void BRepMesh_DataStructureOfDelaun::clearDeletedLinks()
361 Standard_Integer aLastLiveItem = NbLinks();
362 while (!myDelLinks.IsEmpty())
364 while (aLastLiveItem > 0)
366 if (GetLink(aLastLiveItem).Movability() != BRepMesh_Deleted)
369 myLinks.RemoveLast();
373 Standard_Integer aDelItem = myDelLinks.First();
374 myDelLinks.RemoveFirst();
376 if (aDelItem > aLastLiveItem)
379 BRepMesh_Edge aLink = GetLink(aLastLiveItem);
380 BRepMesh_PairOfIndex& aPair = myLinks(aLastLiveItem);
382 myLinks.RemoveLast();
383 myLinks.Substitute(aDelItem, aLink, aPair);
385 myLinksOfDomain.Remove(aLastLiveItem);
386 myLinksOfDomain.Add(aDelItem);
389 const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
390 BRepMesh::ListOfInteger::Iterator aLinkIt;
391 // update link references
392 for (Standard_Integer i = 0; i < 2; ++i)
394 const Standard_Integer aCurNodeId = (i == 0) ?
395 aLink.FirstNode() : aLink.LastNode();
397 for (aLinkIt.Init(linksConnectedTo(aCurNodeId)); aLinkIt.More(); aLinkIt.Next())
399 Standard_Integer& aLinkId = aLinkIt.ChangeValue();
400 if (aLinkId == aLastLiveItemId)
408 // update elements references
409 for(Standard_Integer j = 1, jn = aPair.Extent(); j <= jn; ++j)
411 const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j));
413 Standard_Integer e[3];
414 Standard_Boolean o[3];
415 aElement.Edges(e, o);
416 for (Standard_Integer i = 0; i < 3; ++i)
418 if (e[i] == aLastLiveItemId)
425 myElements.Substitute(aLinkIt.Value(),
426 BRepMesh_Triangle(e, o, aElement.Movability()));
431 //=======================================================================
432 //function : clearDeletedNodes
434 //=======================================================================
435 void BRepMesh_DataStructureOfDelaun::clearDeletedNodes()
437 BRepMesh::ListOfInteger& aDelNodes =
438 (BRepMesh::ListOfInteger&)myNodes->GetListOfDelNodes();
440 Standard_Integer aLastLiveItem = NbNodes();
441 while (!aDelNodes.IsEmpty())
443 while (aLastLiveItem > 0)
445 if (GetNode(aLastLiveItem).Movability() != BRepMesh_Deleted)
448 myNodes->RemoveLast();
452 Standard_Integer aDelItem = aDelNodes.First();
453 aDelNodes.RemoveFirst();
455 if (aDelItem > aLastLiveItem)
458 BRepMesh_Vertex aNode = GetNode(aLastLiveItem);
459 BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aLastLiveItem);
461 myNodes->RemoveLast();
464 myNodes->Substitute(aDelItem, aNode);
465 myNodeLinks.ChangeFind(aDelItem) = aLinkList;
467 const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
468 BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
469 for (; aLinkIt.More(); aLinkIt.Next())
471 const Standard_Integer aLinkId = aLinkIt.Value();
472 const BRepMesh_Edge& aLink = GetLink(aLinkId);
473 BRepMesh_PairOfIndex& aPair = myLinks(aLinkId);
475 Standard_Integer v[2] = { aLink.FirstNode(), aLink.LastNode() };
476 if (v[0] == aLastLiveItemId)
478 else if (v[1] == aLastLiveItemId)
481 myLinks.Substitute(aLinkId,
482 BRepMesh_Edge(v[0], v[1], aLink.Movability()), aPair);
487 //=======================================================================
488 //function : Statistics
490 //=======================================================================
491 void BRepMesh_DataStructureOfDelaun::Statistics(Standard_OStream& theStream) const
493 theStream << " Map of nodes : \n";
494 myNodes->Statistics(theStream);
495 theStream << "\n Deleted nodes : " << myNodes->GetListOfDelNodes().Extent() << endl;
497 theStream << "\n\n Map of Links : \n";
498 myLinks.Statistics(theStream);
499 theStream << "\n Deleted links : " << myDelLinks.Extent() << endl;
501 theStream << "\n\n Map of elements : \n";
502 myElements.Statistics(theStream);
505 //=======================================================================
506 //function : BRepMesh_Write
508 // Global function not declared in any public header, intended for use
509 // from debugger prompt (Command Window in Visual Studio).
511 // Stores the mesh data structure to BRep file with the given name.
512 //=======================================================================
513 Standard_CString BRepMesh_Dump(void* theMeshHandlePtr,
514 Standard_CString theFileNameStr)
516 if (theMeshHandlePtr == 0 || theFileNameStr == 0)
518 return "Error: file name or mesh data is null";
521 Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
522 *(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
524 if (aMeshData.IsNull())
525 return "Error: mesh data is empty";
527 TopoDS_Compound aMesh;
528 BRep_Builder aBuilder;
529 aBuilder.MakeCompound(aMesh);
535 if (aMeshData->LinksOfDomain().IsEmpty())
537 const Standard_Integer aNodesNb = aMeshData->NbNodes();
538 for (Standard_Integer i = 1; i <= aNodesNb; ++i)
540 const gp_XY& aNode = aMeshData->GetNode(i).Coord();
541 gp_Pnt aPnt(aNode.X(), aNode.Y(), 0.);
542 aBuilder.Add(aMesh, BRepBuilderAPI_MakeVertex(aPnt));
547 BRepMesh::MapOfInteger::Iterator aLinksIt(aMeshData->LinksOfDomain());
548 for (; aLinksIt.More(); aLinksIt.Next())
550 const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Value());
552 for (Standard_Integer i = 0; i < 2; ++i)
554 const Standard_Integer aNodeId =
555 (i == 0) ? aLink.FirstNode() : aLink.LastNode();
557 const gp_XY& aNode = aMeshData->GetNode(aNodeId).Coord();
558 aPnt[i] = gp_Pnt(aNode.X(), aNode.Y(), 0.);
561 if (aPnt[0].SquareDistance(aPnt[1]) < Precision::SquareConfusion())
564 aBuilder.Add(aMesh, BRepBuilderAPI_MakeEdge(aPnt[0], aPnt[1]));
568 if (!BRepTools::Write(aMesh, theFileNameStr))
569 return "Error: write failed";
571 catch (Standard_Failure)
573 return Standard_Failure::Caught()->GetMessageString();
576 return theFileNameStr;