1 // Created on: 1993-05-12
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_Delaun.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <gp_Vec2d.hxx>
24 #include <Precision.hxx>
25 #include <Bnd_Box2d.hxx>
26 #include <Bnd_B2d.hxx>
28 #include <BRepMesh_SelectorOfDataStructureOfDelaun.hxx>
30 #include <BRepMesh_Edge.hxx>
31 #include <BRepMesh_Vertex.hxx>
32 #include <BRepMesh_Triangle.hxx>
34 #include <NCollection_Vector.hxx>
38 const Standard_Real AngDeviation1Deg = M_PI/180.;
39 const Standard_Real AngDeviation90Deg = 90 * AngDeviation1Deg;
40 const Standard_Real Angle2PI = 2 * M_PI;
42 const Standard_Real Precision = Precision::PConfusion();
43 const Standard_Real Precision2 = Precision * Precision;
46 //! Sort two points in projection on vector (1,1)
47 struct ComparatorOfVertexOfDelaun
49 bool operator() (const BRepMesh_Vertex& theLeft, const BRepMesh_Vertex& theRight)
51 return theLeft.Coord().X() + theLeft.Coord().Y() < theRight.Coord().X() + theRight.Coord().Y();
55 //! Sort two points in projection on vector (1,1)
56 struct ComparatorOfIndexedVertexOfDelaun
59 ComparatorOfIndexedVertexOfDelaun (const Handle(BRepMesh_DataStructureOfDelaun)& theDS)
60 : myStructure(theDS) {}
62 bool operator() (Standard_Integer theLeft, Standard_Integer theRight)
64 const BRepMesh_Vertex& aLeft = myStructure->GetNode(theLeft);
65 const BRepMesh_Vertex& aRight = myStructure->GetNode(theRight);
66 return ComparatorOfVertexOfDelaun() (aLeft, aRight);
70 Handle(BRepMesh_DataStructureOfDelaun) myStructure;
73 inline void UpdateBndBox(const gp_XY& thePnt1, const gp_XY& thePnt2, Bnd_B2d& theBox)
75 theBox.Add( thePnt1 );
76 theBox.Add( thePnt2 );
77 theBox.Enlarge(Precision);
79 } // anonymous namespace
81 //=======================================================================
82 //function : BRepMesh_Delaun
83 //purpose : Creates the triangulation with an empty Mesh data structure
84 //=======================================================================
85 BRepMesh_Delaun::BRepMesh_Delaun(IMeshData::Array1OfVertexOfDelaun& theVertices)
86 : myCircles (theVertices.Length(), new NCollection_IncAllocator(
87 IMeshData::MEMORY_BLOCK_SIZE_HUGE))
89 if ( theVertices.Length() > 2 )
91 myMeshData = new BRepMesh_DataStructureOfDelaun(
92 new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE),
93 theVertices.Length() );
98 //=======================================================================
99 //function : BRepMesh_Delaun
100 //purpose : Creates the triangulation with and existent Mesh data structure
101 //=======================================================================
102 BRepMesh_Delaun::BRepMesh_Delaun(
103 const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
104 IMeshData::Array1OfVertexOfDelaun& theVertices)
105 : myMeshData( theOldMesh ),
106 myCircles ( theVertices.Length(), theOldMesh->Allocator() )
108 if ( theVertices.Length() > 2 )
114 //=======================================================================
115 //function : BRepMesh_Delaun
116 //purpose : Creates the triangulation with and existent Mesh data structure
117 //=======================================================================
118 BRepMesh_Delaun::BRepMesh_Delaun(
119 const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
120 IMeshData::VectorOfInteger& theVertexIndices)
121 : myMeshData( theOldMesh ),
122 myCircles ( theVertexIndices.Length(), theOldMesh->Allocator() )
124 perform(theVertexIndices);
127 //=======================================================================
128 //function : BRepMesh_Delaun
129 //purpose : Creates the triangulation with and existent Mesh data structure
130 //=======================================================================
131 BRepMesh_Delaun::BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)& theOldMesh,
132 IMeshData::VectorOfInteger& theVertexIndices,
133 const Standard_Integer theCellsCountU,
134 const Standard_Integer theCellsCountV)
135 : myMeshData (theOldMesh),
136 myCircles (theVertexIndices.Length (), theOldMesh->Allocator ())
138 perform (theVertexIndices, theCellsCountU, theCellsCountV);
141 //=======================================================================
143 //purpose : Initializes the triangulation with an Array of Vertex
144 //=======================================================================
145 void BRepMesh_Delaun::Init(IMeshData::Array1OfVertexOfDelaun& theVertices)
147 Standard_Integer aLowerIdx = theVertices.Lower();
148 Standard_Integer anUpperIdx = theVertices.Upper();
149 IMeshData::VectorOfInteger aVertexIndexes(theVertices.Size());
151 Standard_Integer anIndex = aLowerIdx;
152 for ( ; anIndex <= anUpperIdx; ++anIndex )
154 aVertexIndexes.Append(myMeshData->AddNode( theVertices( anIndex ) ));
157 perform( aVertexIndexes );
160 //=======================================================================
162 //purpose : Create super mesh and run triangulation procedure
163 //=======================================================================
164 void BRepMesh_Delaun::perform(IMeshData::VectorOfInteger& theVertexIndices,
165 const Standard_Integer theCellsCountU /* = -1 */,
166 const Standard_Integer theCellsCountV /* = -1 */)
168 if (theVertexIndices.Length () <= 2)
174 Standard_Integer anIndex = theVertexIndices.Lower ();
175 Standard_Integer anUpper = theVertexIndices.Upper ();
176 for (; anIndex <= anUpper; ++anIndex)
178 aBox.Add (gp_Pnt2d (GetVertex (theVertexIndices (anIndex)).Coord ()));
181 aBox.Enlarge (Precision);
183 Standard_Integer aScaler = 2;
184 if ( myMeshData->NbNodes() > 100 )
188 else if( myMeshData->NbNodes() > 1000 )
193 superMesh (aBox, Max (theCellsCountU, aScaler),
194 Max (theCellsCountV, aScaler));
196 ComparatorOfIndexedVertexOfDelaun aCmp(myMeshData);
197 std::make_heap(theVertexIndices.begin(), theVertexIndices.end(), aCmp);
198 std::sort_heap(theVertexIndices.begin(), theVertexIndices.end(), aCmp);
200 compute( theVertexIndices );
203 //=======================================================================
204 //function : superMesh
205 //purpose : Build the super mesh
206 //=======================================================================
207 void BRepMesh_Delaun::superMesh(const Bnd_Box2d& theBox,
208 const Standard_Integer theCellsCountU,
209 const Standard_Integer theCellsCountV)
211 Standard_Real aMinX, aMinY, aMaxX, aMaxY;
212 theBox.Get ( aMinX, aMinY, aMaxX, aMaxY );
213 Standard_Real aDeltaX = aMaxX - aMinX;
214 Standard_Real aDeltaY = aMaxY - aMinY;
216 Standard_Real aDeltaMin = Min( aDeltaX, aDeltaY );
217 Standard_Real aDeltaMax = Max( aDeltaX, aDeltaY );
218 Standard_Real aDelta = aDeltaX + aDeltaY;
220 myCircles.SetMinMaxSize( gp_XY( aMinX, aMinY ), gp_XY( aMaxX, aMaxY ) );
221 myCircles.SetCellSize( aDeltaX / theCellsCountU, aDeltaY / theCellsCountV);
223 mySupVert[0] = myMeshData->AddNode(
224 BRepMesh_Vertex( ( aMinX + aMaxX ) / 2, aMaxY + aDeltaMax, BRepMesh_Free ) );
226 mySupVert[1] = myMeshData->AddNode(
227 BRepMesh_Vertex( aMinX - aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
229 mySupVert[2] = myMeshData->AddNode(
230 BRepMesh_Vertex( aMaxX + aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
232 Standard_Integer e[3];
233 Standard_Boolean o[3];
234 for (Standard_Integer aNodeId = 0; aNodeId < 3; ++aNodeId)
236 Standard_Integer aFirstNode = aNodeId;
237 Standard_Integer aLastNode = (aNodeId + 1) % 3;
238 Standard_Integer aLinkIndex = myMeshData->AddLink( BRepMesh_Edge(
239 mySupVert[aFirstNode], mySupVert[aLastNode], BRepMesh_Free ) );
241 e[aNodeId] = Abs(aLinkIndex);
242 o[aNodeId] = (aLinkIndex > 0);
245 mySupTrian = BRepMesh_Triangle(e, o, BRepMesh_Free);
248 //=======================================================================
249 //function : deleteTriangle
250 //purpose : Deletes the triangle with the given index and adds the free
251 // edges into the map.
252 // When an edge is suppressed more than one time it is destroyed.
253 //=======================================================================
254 void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex,
255 IMeshData::MapOfIntegerInteger& theLoopEdges )
257 myCircles.Delete( theIndex );
259 const BRepMesh_Triangle& aElement = GetTriangle(theIndex);
260 const Standard_Integer(&e)[3] = aElement.myEdges;
261 const Standard_Boolean(&o)[3] = aElement.myOrientations;
263 myMeshData->RemoveElement( theIndex );
265 for ( Standard_Integer i = 0; i < 3; ++i )
267 if ( !theLoopEdges.Bind( e[i], o[i] ) )
269 theLoopEdges.UnBind( e[i] );
270 myMeshData->RemoveLink( e[i] );
275 //=======================================================================
277 //purpose : Computes the triangulation and add the vertices edges and
278 // triangles to the Mesh data structure
279 //=======================================================================
280 void BRepMesh_Delaun::compute(IMeshData::VectorOfInteger& theVertexIndexes)
282 // Insertion of edges of super triangles in the list of free edges:
283 IMeshData::MapOfIntegerInteger aLoopEdges(10, myMeshData->Allocator());
284 const Standard_Integer(&e)[3] = mySupTrian.myEdges;
286 aLoopEdges.Bind( e[0], Standard_True );
287 aLoopEdges.Bind( e[1], Standard_True );
288 aLoopEdges.Bind( e[2], Standard_True );
290 if ( theVertexIndexes.Length() > 0 )
292 // Creation of 3 trianglers with the first node and the edges of the super triangle:
293 Standard_Integer anVertexIdx = theVertexIndexes.Lower();
294 createTriangles( theVertexIndexes( anVertexIdx ), aLoopEdges );
296 // Add other nodes to the mesh
297 createTrianglesOnNewVertices( theVertexIndexes );
300 // Destruction of triangles containing a top of the super triangle
301 BRepMesh_SelectorOfDataStructureOfDelaun aSelector( myMeshData );
302 for (Standard_Integer aSupVertId = 0; aSupVertId < 3; ++aSupVertId)
303 aSelector.NeighboursOfNode( mySupVert[aSupVertId] );
306 IMeshData::IteratorOfMapOfInteger aFreeTriangles( aSelector.Elements() );
307 for ( ; aFreeTriangles.More(); aFreeTriangles.Next() )
308 deleteTriangle( aFreeTriangles.Key(), aLoopEdges );
310 // All edges that remain free are removed from aLoopEdges;
311 // only the boundary edges of the triangulation remain there
312 IMeshData::MapOfIntegerInteger::Iterator aFreeEdges( aLoopEdges );
313 for ( ; aFreeEdges.More(); aFreeEdges.Next() )
315 if ( myMeshData->ElementsConnectedTo( aFreeEdges.Key() ).IsEmpty() )
316 myMeshData->RemoveLink( aFreeEdges.Key() );
319 // The tops of the super triangle are destroyed
320 for (Standard_Integer aSupVertId = 0; aSupVertId < 3; ++aSupVertId)
321 myMeshData->RemoveNode( mySupVert[aSupVertId] );
324 //=======================================================================
325 //function : createTriangles
326 //purpose : Creates the triangles beetween the node and the polyline.
327 //=======================================================================
328 void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex,
329 IMeshData::MapOfIntegerInteger& thePoly)
331 IMeshData::ListOfInteger aLoopEdges, anExternalEdges;
332 const gp_XY& aVertexCoord = myMeshData->GetNode( theVertexIndex ).Coord();
334 IMeshData::MapOfIntegerInteger::Iterator anEdges( thePoly );
335 for ( ; anEdges.More(); anEdges.Next() )
337 Standard_Integer anEdgeId = anEdges.Key();
338 const BRepMesh_Edge& anEdge = GetEdge( anEdgeId );
340 Standard_Boolean isPositive = thePoly( anEdgeId ) != 0;
342 Standard_Integer aNodes[3];
345 aNodes[0] = anEdge.FirstNode();
346 aNodes[2] = anEdge.LastNode();
350 aNodes[0] = anEdge.LastNode();
351 aNodes[2] = anEdge.FirstNode();
353 aNodes[1] = theVertexIndex;
355 const BRepMesh_Vertex& aFirstVertex = GetVertex( aNodes[0] );
356 const BRepMesh_Vertex& aLastVertex = GetVertex( aNodes[2] );
358 gp_XY anEdgeDir( aLastVertex.Coord() - aFirstVertex.Coord() );
359 Standard_Real anEdgeLen = anEdgeDir.Modulus();
360 if ( anEdgeLen < Precision )
363 anEdgeDir.SetCoord( anEdgeDir.X() / anEdgeLen,
364 anEdgeDir.Y() / anEdgeLen );
366 gp_XY aFirstLinkDir( aFirstVertex.Coord() - aVertexCoord );
367 gp_XY aLastLinkDir ( aVertexCoord - aLastVertex.Coord() );
369 Standard_Real aDist12 = aFirstLinkDir ^ anEdgeDir;
370 Standard_Real aDist23 = anEdgeDir ^ aLastLinkDir;
371 if ( Abs( aDist12 ) < Precision ||
372 Abs( aDist23 ) < Precision )
377 BRepMesh_Edge aFirstLink( aNodes[1], aNodes[0], BRepMesh_Free );
378 BRepMesh_Edge aLastLink ( aNodes[2], aNodes[1], BRepMesh_Free );
380 Standard_Integer anEdgesInfo[3] = {
381 myMeshData->AddLink( aFirstLink ),
382 isPositive ? anEdgeId : -anEdgeId,
383 myMeshData->AddLink( aLastLink ) };
385 Standard_Boolean isSensOK = (aDist12 > 0. && aDist23 > 0.);
388 Standard_Integer anEdgeIds[3];
389 Standard_Boolean anEdgesOri[3];
390 for ( Standard_Integer aTriLinkIt = 0; aTriLinkIt < 3; ++aTriLinkIt )
392 const Standard_Integer& anEdgeInfo = anEdgesInfo[aTriLinkIt];
393 anEdgeIds[aTriLinkIt] = Abs( anEdgeInfo );
394 anEdgesOri[aTriLinkIt] = anEdgeInfo > 0;
397 addTriangle(anEdgeIds, anEdgesOri, aNodes );
402 aLoopEdges.Append( anEdges.Key() );
404 aLoopEdges.Append( -anEdges.Key() );
406 if ( aFirstLinkDir.SquareModulus() > aLastLinkDir.SquareModulus() )
407 anExternalEdges.Append( Abs( anEdgesInfo[0] ) );
409 anExternalEdges.Append( Abs( anEdgesInfo[2] ) );
414 while ( !anExternalEdges.IsEmpty() )
416 const BRepMesh_PairOfIndex& aPair =
417 myMeshData->ElementsConnectedTo( Abs( anExternalEdges.First() ) );
420 if ( !aPair.IsEmpty() )
421 deleteTriangle( aPair.FirstIndex(), thePoly );
423 anExternalEdges.RemoveFirst();
426 for ( anEdges.Initialize( thePoly ); anEdges.More(); anEdges.Next() )
428 if ( myMeshData->ElementsConnectedTo( anEdges.Key() ).IsEmpty() )
429 myMeshData->RemoveLink( anEdges.Key() );
432 while ( !aLoopEdges.IsEmpty() )
434 const BRepMesh_Edge& anEdge = GetEdge( Abs( aLoopEdges.First() ) );
435 if ( anEdge.Movability() != BRepMesh_Deleted )
437 Standard_Integer anEdgeIdx = aLoopEdges.First();
438 meshLeftPolygonOf( Abs( anEdgeIdx ), ( anEdgeIdx > 0 ) );
441 aLoopEdges.RemoveFirst();
445 //=======================================================================
446 //function : createTrianglesOnNewVertices
447 //purpose : Creation of triangles from the new nodes
448 //=======================================================================
449 void BRepMesh_Delaun::createTrianglesOnNewVertices(
450 IMeshData::VectorOfInteger& theVertexIndexes)
452 Handle(NCollection_IncAllocator) aAllocator =
453 new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
455 Standard_Real aTolU, aTolV;
456 myMeshData->Data()->GetTolerance(aTolU, aTolV);
457 const Standard_Real aSqTol = aTolU * aTolU + aTolV * aTolV;
459 // Insertion of nodes :
460 Standard_Boolean isModify = Standard_True;
462 Standard_Integer anIndex = theVertexIndexes.Lower();
463 Standard_Integer anUpper = theVertexIndexes.Upper();
464 for( ; anIndex <= anUpper; ++anIndex )
466 aAllocator->Reset(Standard_False);
467 IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
469 Standard_Integer aVertexIdx = theVertexIndexes( anIndex );
470 const BRepMesh_Vertex& aVertex = GetVertex( aVertexIdx );
472 // Iterator in the list of indexes of circles containing the node
473 IMeshData::ListOfInteger& aCirclesList = myCircles.Select( aVertex.Coord() );
475 Standard_Integer onEgdeId = 0, aTriangleId = 0;
476 IMeshData::ListOfInteger::Iterator aCircleIt( aCirclesList );
477 for ( ; aCircleIt.More(); aCircleIt.Next() )
479 // To add a node in the mesh it is necessary to check conditions:
480 // - the node should be within the boundaries of the mesh and so in an existing triangle
481 // - all adjacent triangles should belong to a component connected with this triangle
482 if ( Contains( aCircleIt.Value(), aVertex, aSqTol, onEgdeId ) )
484 if (onEgdeId != 0 && GetEdge(onEgdeId).Movability() != BRepMesh_Free)
486 // We can skip free vertex too close to the frontier edge.
487 if (aVertex.Movability() == BRepMesh_Free)
490 // However, we should add vertex that have neighboring frontier edges.
493 // Remove triangle even if it contains frontier edge in order
494 // to prevent appearance of incorrect configurations like free
495 // edge glued with frontier #26407
496 aTriangleId = aCircleIt.Value();
497 aCirclesList.Remove( aCircleIt );
502 if ( aTriangleId > 0 )
504 deleteTriangle( aTriangleId, aLoopEdges );
506 isModify = Standard_True;
507 while ( isModify && !aCirclesList.IsEmpty() )
509 isModify = Standard_False;
510 IMeshData::ListOfInteger::Iterator aCircleIt1( aCirclesList );
511 for ( ; aCircleIt1.More(); aCircleIt1.Next() )
513 const BRepMesh_Triangle& aElement = GetTriangle(aCircleIt1.Value());
514 const Standard_Integer(&e)[3] = aElement.myEdges;
516 if ( aLoopEdges.IsBound( e[0] ) ||
517 aLoopEdges.IsBound( e[1] ) ||
518 aLoopEdges.IsBound( e[2] ) )
520 isModify = Standard_True;
521 deleteTriangle( aCircleIt1.Value(), aLoopEdges );
522 aCirclesList.Remove( aCircleIt1 );
528 // Creation of triangles with the current node and free edges
529 // and removal of these edges from the list of free edges
530 createTriangles( aVertexIdx, aLoopEdges );
534 insertInternalEdges();
536 // Adjustment of meshes to boundary edges
540 //=======================================================================
541 //function : insertInternalEdges
543 //=======================================================================
544 void BRepMesh_Delaun::insertInternalEdges()
546 Handle(IMeshData::MapOfInteger) anInternalEdges = InternalEdges();;
548 // Destruction of triancles intersecting internal edges
549 // and their replacement by makeshift triangles
550 IMeshData::IteratorOfMapOfInteger anInernalEdgesIt( *anInternalEdges );
551 for ( ; anInernalEdgesIt.More(); anInernalEdgesIt.Next() )
553 const Standard_Integer aLinkIndex = anInernalEdgesIt.Key();
554 const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo(aLinkIndex);
556 // Check both sides of link for adjusted triangle.
557 Standard_Boolean isGo[2] = { Standard_True, Standard_True };
558 for (Standard_Integer aTriangleIt = 1; aTriangleIt <= aPair.Extent(); ++aTriangleIt)
560 const BRepMesh_Triangle& aElement = GetTriangle(aPair.Index(aTriangleIt));
561 const Standard_Integer(&e)[3] = aElement.myEdges;
562 const Standard_Boolean(&o)[3] = aElement.myOrientations;
564 for (Standard_Integer i = 0; i < 3; ++i)
566 if (e[i] == aLinkIndex)
568 isGo[o[i] ? 0 : 1] = Standard_False;
576 meshLeftPolygonOf(aLinkIndex, Standard_True);
581 meshLeftPolygonOf(aLinkIndex, Standard_False);
586 //=======================================================================
587 //function : isBoundToFrontier
588 //purpose : Goes through the neighbour triangles around the given node
589 // started from the given link, returns TRUE if some triangle
590 // has a bounding frontier edge or FALSE elsewhere.
591 // Stop link is used to prevent cycles.
592 // Previous element Id is used to identify next neighbor element.
593 //=======================================================================
594 Standard_Boolean BRepMesh_Delaun::isBoundToFrontier(
595 const Standard_Integer theRefNodeId,
596 const Standard_Integer theRefLinkId,
597 const Standard_Integer theStopLinkId,
598 const Standard_Integer thePrevElementId)
600 const BRepMesh_PairOfIndex& aPair =
601 myMeshData->ElementsConnectedTo( theRefLinkId );
602 if ( aPair.IsEmpty() )
603 return Standard_False;
605 Standard_Integer aNbElements = aPair.Extent();
606 for ( Standard_Integer anElemIt = 1; anElemIt <= aNbElements; ++anElemIt )
608 const Standard_Integer aTriId = aPair.Index(anElemIt);
609 if ( aTriId < 0 || aTriId == thePrevElementId )
612 const BRepMesh_Triangle& aElement = GetTriangle(aTriId);
613 const Standard_Integer(&anEdges)[3] = aElement.myEdges;
615 for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
617 const Standard_Integer anEdgeId = anEdges[anEdgeIt];
618 if ( anEdgeId == theRefLinkId )
621 if ( anEdgeId == theStopLinkId )
622 return Standard_False;
624 const BRepMesh_Edge& anEdge = GetEdge( anEdgeId );
625 if ( anEdge.FirstNode() != theRefNodeId &&
626 anEdge.LastNode() != theRefNodeId )
631 if ( anEdge.Movability() != BRepMesh_Free )
632 return Standard_True;
634 return isBoundToFrontier( theRefNodeId, anEdgeId, theStopLinkId, aTriId );
638 return Standard_False;
641 //=======================================================================
642 //function : cleanupMesh
643 //purpose : Cleanup mesh from the free triangles
644 //=======================================================================
645 void BRepMesh_Delaun::cleanupMesh()
647 Handle(NCollection_IncAllocator) aAllocator =
648 new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
652 aAllocator->Reset(Standard_False);
653 IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
654 IMeshData::MapOfInteger aDelTriangles;
656 Handle(IMeshData::MapOfInteger) aFreeEdges = FreeEdges();
657 IMeshData::IteratorOfMapOfInteger aFreeEdgesIt( *aFreeEdges );
658 for ( ; aFreeEdgesIt.More(); aFreeEdgesIt.Next() )
660 const Standard_Integer& aFreeEdgeId = aFreeEdgesIt.Key();
661 const BRepMesh_Edge& anEdge = GetEdge( aFreeEdgeId );
662 if ( anEdge.Movability() == BRepMesh_Frontier )
665 const BRepMesh_PairOfIndex& aPair =
666 myMeshData->ElementsConnectedTo( aFreeEdgeId );
667 if ( aPair.IsEmpty() )
669 aLoopEdges.Bind( aFreeEdgeId, Standard_True );
673 Standard_Integer aTriId = aPair.FirstIndex();
675 // Check that the connected triangle is not surrounded by another triangles
676 const BRepMesh_Triangle& aElement = GetTriangle(aTriId);
677 const Standard_Integer(&anEdges)[3] = aElement.myEdges;
679 Standard_Boolean isCanNotBeRemoved = Standard_True;
680 for ( Standard_Integer aCurEdgeIdx = 0; aCurEdgeIdx < 3; ++aCurEdgeIdx )
682 if ( anEdges[aCurEdgeIdx] != aFreeEdgeId )
685 for ( Standard_Integer anOtherEdgeIt = 1; anOtherEdgeIt <= 2; ++anOtherEdgeIt )
687 Standard_Integer anOtherEdgeId = ( aCurEdgeIdx + anOtherEdgeIt ) % 3;
688 const BRepMesh_PairOfIndex& anOtherEdgePair =
689 myMeshData->ElementsConnectedTo( anEdges[anOtherEdgeId] );
691 if ( anOtherEdgePair.Extent() < 2 )
693 isCanNotBeRemoved = Standard_False;
701 if ( isCanNotBeRemoved )
704 Standard_Boolean isConnected[2] = { Standard_False, Standard_False };
705 for ( Standard_Integer aLinkNodeIt = 0; aLinkNodeIt < 2; ++aLinkNodeIt )
707 isConnected[aLinkNodeIt] = isBoundToFrontier( ( aLinkNodeIt == 0 ) ?
708 anEdge.FirstNode() : anEdge.LastNode(),
709 aFreeEdgeId, aFreeEdgeId, -1);
712 if ( !isConnected[0] || !isConnected[1] )
713 aDelTriangles.Add( aTriId );
716 // Destruction of triangles :
717 Standard_Integer aDeletedTrianglesNb = 0;
718 IMeshData::IteratorOfMapOfInteger aDelTrianglesIt( aDelTriangles );
719 for ( ; aDelTrianglesIt.More(); aDelTrianglesIt.Next() )
721 deleteTriangle( aDelTrianglesIt.Key(), aLoopEdges );
722 aDeletedTrianglesNb++;
725 // Destruction of remaining hanging edges
726 IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
727 for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
729 if ( myMeshData->ElementsConnectedTo( aLoopEdgesIt.Key() ).IsEmpty() )
730 myMeshData->RemoveLink( aLoopEdgesIt.Key() );
733 if ( aDeletedTrianglesNb == 0 )
738 //=======================================================================
739 //function : frontierAdjust
740 //purpose : Adjust the mesh on the frontier
741 //=======================================================================
742 void BRepMesh_Delaun::frontierAdjust()
744 Handle(IMeshData::MapOfInteger) aFrontier = Frontier();
746 Handle(NCollection_IncAllocator) aAllocator =
747 new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
749 IMeshData::VectorOfInteger aFailedFrontiers(256, aAllocator);
750 IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
751 Handle(IMeshData::MapOfInteger) aIntFrontierEdges = new IMeshData::MapOfInteger;
753 for ( Standard_Integer aPass = 1; aPass <= 2; ++aPass )
755 // 1 pass): find external triangles on boundary edges;
756 // 2 pass): find external triangles on boundary edges appeared
757 // during triangles replacement.
759 IMeshData::IteratorOfMapOfInteger aFrontierIt( *aFrontier );
760 for ( ; aFrontierIt.More(); aFrontierIt.Next() )
762 Standard_Integer aFrontierId = aFrontierIt.Key();
763 const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo( aFrontierId );
764 Standard_Integer aNbElem = aPair.Extent();
765 for( Standard_Integer aElemIt = 1; aElemIt <= aNbElem; ++aElemIt )
767 const Standard_Integer aPriorElemId = aPair.Index( aElemIt );
768 if( aPriorElemId < 0 )
771 const BRepMesh_Triangle& aElement = GetTriangle(aPriorElemId);
772 const Standard_Integer(&e)[3] = aElement.myEdges;
773 const Standard_Boolean(&o)[3] = aElement.myOrientations;
775 Standard_Boolean isTriangleFound = Standard_False;
776 for ( Standard_Integer n = 0; n < 3; ++n )
778 if ( aFrontierId == e[n] && !o[n] )
780 // Destruction of external triangles on boundary edges
781 isTriangleFound = Standard_True;
782 deleteTriangle( aPriorElemId, aLoopEdges );
787 if ( isTriangleFound )
792 // destrucrion of remaining hanging edges :
793 IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
794 for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
796 Standard_Integer aLoopEdgeId = aLoopEdgesIt.Key();
797 if (myMeshData->ElementsConnectedTo( aLoopEdgeId ).IsEmpty() )
798 myMeshData->RemoveLink( aLoopEdgeId );
801 // destruction of triangles crossing the boundary edges and
802 // their replacement by makeshift triangles
803 for ( aFrontierIt.Reset(); aFrontierIt.More(); aFrontierIt.Next() )
805 Standard_Integer aFrontierId = aFrontierIt.Key();
806 if ( !myMeshData->ElementsConnectedTo( aFrontierId ).IsEmpty() )
809 Standard_Boolean isSuccess =
810 meshLeftPolygonOf( aFrontierId, Standard_True, aIntFrontierEdges );
812 if ( aPass == 2 && !isSuccess )
813 aFailedFrontiers.Append( aFrontierId );
819 // When the mesh has been cleaned up, try to process frontier edges
820 // once again to fill the possible gaps that might be occured in case of "saw" -
821 // situation when frontier edge has a triangle at a right side, but its free
822 // links cross another frontieres and meshLeftPolygonOf itself can't collect
824 IMeshData::VectorOfInteger::Iterator aFailedFrontiersIt( aFailedFrontiers );
825 for ( ; aFailedFrontiersIt.More(); aFailedFrontiersIt.Next() )
827 Standard_Integer aFrontierId = aFailedFrontiersIt.Value();
828 if ( !myMeshData->ElementsConnectedTo( aFrontierId ).IsEmpty() )
831 meshLeftPolygonOf( aFrontierId, Standard_True, aIntFrontierEdges );
835 //=======================================================================
836 //function : fillBndBox
837 //purpose : Add boundig box for edge defined by start & end point to
838 // the given vector of bounding boxes for triangulation edges
839 //=======================================================================
840 void BRepMesh_Delaun::fillBndBox(IMeshData::SequenceOfBndB2d& theBoxes,
841 const BRepMesh_Vertex& theV1,
842 const BRepMesh_Vertex& theV2)
845 UpdateBndBox(theV1.Coord(), theV2.Coord(), aBox);
846 theBoxes.Append( aBox );
849 //=======================================================================
850 //function : meshLeftPolygonOf
851 //purpose : Collect the polygon at the left of the given edge (material side)
852 //=======================================================================
853 Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf(
854 const Standard_Integer theStartEdgeId,
855 const Standard_Boolean isForward,
856 Handle(IMeshData::MapOfInteger) theSkipped)
858 if ( !theSkipped.IsNull() && theSkipped->Contains( theStartEdgeId ) )
859 return Standard_True;
861 const BRepMesh_Edge& aRefEdge = GetEdge( theStartEdgeId );
863 IMeshData::SequenceOfInteger aPolygon;
864 Standard_Integer aStartNode, aPivotNode;
867 aPolygon.Append( theStartEdgeId );
868 aStartNode = aRefEdge.FirstNode();
869 aPivotNode = aRefEdge.LastNode();
873 aPolygon.Append( -theStartEdgeId );
874 aStartNode = aRefEdge.LastNode();
875 aPivotNode = aRefEdge.FirstNode();
879 const BRepMesh_Vertex& aStartEdgeVertexS = GetVertex( aStartNode );
880 BRepMesh_Vertex aPivotVertex = GetVertex( aPivotNode );
882 gp_Vec2d aRefLinkDir( aPivotVertex.Coord() -
883 aStartEdgeVertexS.Coord() );
885 if ( aRefLinkDir.SquareMagnitude() < Precision2 )
886 return Standard_True;
888 // Auxilary structures.
889 // Bounding boxes of polygon links to be used for preliminary
890 // analysis of intersections
891 IMeshData::SequenceOfBndB2d aBoxes;
892 fillBndBox( aBoxes, aStartEdgeVertexS, aPivotVertex );
895 IMeshData::MapOfInteger aDeadLinks;
897 // Links are temporarily excluded from consideration
898 IMeshData::MapOfInteger aLeprousLinks;
899 aLeprousLinks.Add( theStartEdgeId );
901 Standard_Boolean isSkipLeprous = Standard_True;
902 Standard_Integer aFirstNode = aStartNode;
903 while ( aPivotNode != aFirstNode )
905 Bnd_B2d aNextLinkBndBox;
906 gp_Vec2d aNextLinkDir;
907 Standard_Integer aNextPivotNode = 0;
909 Standard_Integer aNextLinkId = findNextPolygonLink(
911 aPivotNode, aPivotVertex, aRefLinkDir,
912 aBoxes, aPolygon, theSkipped,
913 isSkipLeprous, aLeprousLinks, aDeadLinks,
914 aNextPivotNode, aNextLinkDir, aNextLinkBndBox );
916 if ( aNextLinkId != 0 )
918 aStartNode = aPivotNode;
919 aRefLinkDir = aNextLinkDir;
921 aPivotNode = aNextPivotNode;
922 aPivotVertex = GetVertex( aNextPivotNode );
924 aBoxes.Append ( aNextLinkBndBox );
925 aPolygon.Append( aNextLinkId );
927 isSkipLeprous = Standard_True;
932 if ( aPolygon.Length() == 1 )
933 return Standard_False;
935 // Return to the previous point
936 Standard_Integer aDeadLinkId = Abs( aPolygon.Last() );
937 aDeadLinks.Add ( aDeadLinkId );
939 aLeprousLinks.Remove( aDeadLinkId );
940 aPolygon.Remove ( aPolygon.Length() );
941 aBoxes.Remove ( aBoxes.Length() );
943 Standard_Integer aPrevLinkInfo = aPolygon.Last();
944 const BRepMesh_Edge& aPrevLink = GetEdge( Abs( aPrevLinkInfo ) );
946 if( aPrevLinkInfo > 0 )
948 aStartNode = aPrevLink.FirstNode();
949 aPivotNode = aPrevLink.LastNode();
953 aStartNode = aPrevLink.LastNode();
954 aPivotNode = aPrevLink.FirstNode();
957 aPivotVertex = GetVertex( aPivotNode );
959 aPivotVertex.Coord() - GetVertex( aStartNode ).Coord();
961 isSkipLeprous = Standard_False;
965 if ( aPolygon.Length() < 3 )
966 return Standard_False;
968 cleanupPolygon( aPolygon, aBoxes );
969 meshPolygon ( aPolygon, aBoxes, theSkipped );
971 return Standard_True;
974 //=======================================================================
975 //function : findNextPolygonLink
976 //purpose : Find next link starting from the given node and has maximum
977 // angle respect the given reference link.
978 // Each time the next link is found other neighbor links at the
979 // pivot node are marked as leprous and will be excluded from
980 // consideration next time until a hanging end is occured.
981 //=======================================================================
982 Standard_Integer BRepMesh_Delaun::findNextPolygonLink(
983 const Standard_Integer& theFirstNode,
984 const Standard_Integer& thePivotNode,
985 const BRepMesh_Vertex& thePivotVertex,
986 const gp_Vec2d& theRefLinkDir,
987 const IMeshData::SequenceOfBndB2d& theBoxes,
988 const IMeshData::SequenceOfInteger& thePolygon,
989 const Handle(IMeshData::MapOfInteger) theSkipped,
990 const Standard_Boolean& isSkipLeprous,
991 IMeshData::MapOfInteger& theLeprousLinks,
992 IMeshData::MapOfInteger& theDeadLinks,
993 Standard_Integer& theNextPivotNode,
994 gp_Vec2d& theNextLinkDir,
995 Bnd_B2d& theNextLinkBndBox )
997 // Find the next link having the greatest angle
998 // respect to a direction of a reference one
999 Standard_Real aMaxAngle = RealFirst();
1001 Standard_Integer aNextLinkId = 0;
1002 IMeshData::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) );
1003 for ( ; aLinkIt.More(); aLinkIt.Next() )
1005 const Standard_Integer& aNeighbourLinkInfo = aLinkIt.Value();
1006 Standard_Integer aNeighbourLinkId = Abs( aNeighbourLinkInfo );
1008 if ( theDeadLinks.Contains( aNeighbourLinkId ) ||
1009 ( !theSkipped.IsNull() && theSkipped->Contains( aNeighbourLinkId ) ) )
1014 Standard_Boolean isLeprous = theLeprousLinks.Contains( aNeighbourLinkId );
1015 if ( isSkipLeprous && isLeprous )
1018 const BRepMesh_Edge& aNeighbourLink = GetEdge( aNeighbourLinkId );
1020 // Determine whether the link belongs to the mesh
1021 if ( aNeighbourLink.Movability() == BRepMesh_Free &&
1022 myMeshData->ElementsConnectedTo( aNeighbourLinkInfo ).IsEmpty() )
1024 theDeadLinks.Add( aNeighbourLinkId );
1028 Standard_Integer anOtherNode = aNeighbourLink.FirstNode();
1029 if ( anOtherNode == thePivotNode )
1030 anOtherNode = aNeighbourLink.LastNode();
1032 gp_Vec2d aCurLinkDir( GetVertex( anOtherNode ).Coord() -
1033 thePivotVertex.Coord() );
1035 if ( aCurLinkDir.SquareMagnitude() < Precision2 )
1037 theDeadLinks.Add( aNeighbourLinkId );
1042 theLeprousLinks.Add( aNeighbourLinkId );
1044 Standard_Real anAngle = theRefLinkDir.Angle( aCurLinkDir );
1045 Standard_Boolean isFrontier =
1046 ( aNeighbourLink.Movability() == BRepMesh_Frontier );
1048 Standard_Boolean isCheckPointOnEdge = Standard_True;
1051 if ( Abs( Abs(anAngle) - M_PI ) < Precision::Angular() )
1053 // Glued constrains - don't check intersection
1054 isCheckPointOnEdge = Standard_False;
1055 anAngle = Abs( anAngle );
1059 if (anAngle <= aMaxAngle)
1062 Standard_Boolean isCheckEndPoints = ( anOtherNode != theFirstNode );
1065 Standard_Boolean isNotIntersect =
1066 checkIntersection( aNeighbourLink, thePolygon, theBoxes,
1067 isCheckEndPoints, isCheckPointOnEdge, Standard_True, aBox );
1069 if( isNotIntersect )
1071 aMaxAngle = anAngle;
1073 theNextLinkDir = aCurLinkDir;
1074 theNextPivotNode = anOtherNode;
1075 theNextLinkBndBox = aBox;
1077 aNextLinkId = ( aNeighbourLink.FirstNode() == thePivotNode ) ?
1078 aNeighbourLinkId : -aNeighbourLinkId;
1085 //=======================================================================
1086 //function : checkIntersection
1087 //purpose : Check is the given link intersects the polygon boundaries.
1088 // Returns bounding box for the given link trough the
1089 // <theLinkBndBox> parameter.
1090 //=======================================================================
1091 Standard_Boolean BRepMesh_Delaun::checkIntersection(
1092 const BRepMesh_Edge& theLink,
1093 const IMeshData::SequenceOfInteger& thePolygon,
1094 const IMeshData::SequenceOfBndB2d& thePolyBoxes,
1095 const Standard_Boolean isConsiderEndPointTouch,
1096 const Standard_Boolean isConsiderPointOnEdge,
1097 const Standard_Boolean isSkipLastEdge,
1098 Bnd_B2d& theLinkBndBox ) const
1100 UpdateBndBox(GetVertex(theLink.FirstNode()).Coord(),
1101 GetVertex(theLink.LastNode()).Coord(), theLinkBndBox);
1103 Standard_Integer aPolyLen = thePolygon.Length();
1104 // Don't check intersection with the last link
1105 if ( isSkipLastEdge )
1108 Standard_Boolean isFrontier =
1109 ( theLink.Movability() == BRepMesh_Frontier );
1111 for ( Standard_Integer aPolyIt = 1; aPolyIt <= aPolyLen; ++aPolyIt )
1113 if ( !theLinkBndBox.IsOut( thePolyBoxes.Value( aPolyIt ) ) )
1115 // intersection is possible...
1116 Standard_Integer aPolyLinkId = Abs( thePolygon( aPolyIt ) );
1117 const BRepMesh_Edge& aPolyLink = GetEdge( aPolyLinkId );
1119 // skip intersections between frontier edges
1120 if ( aPolyLink.Movability() == BRepMesh_Frontier && isFrontier )
1124 BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( theLink, aPolyLink,
1125 isConsiderEndPointTouch, isConsiderPointOnEdge, anIntPnt );
1127 if ( aIntFlag != BRepMesh_GeomTool::NoIntersection )
1128 return Standard_False;
1132 // Ok, no intersection
1133 return Standard_True;
1136 //=======================================================================
1137 //function : addTriangle
1138 //purpose : Add a triangle based on the given oriented edges into mesh
1139 //=======================================================================
1140 inline void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3],
1141 const Standard_Boolean (&theEdgesOri)[3],
1142 const Standard_Integer (&theNodesId)[3] )
1144 Standard_Integer aNewTriangleId =
1145 myMeshData->AddElement(BRepMesh_Triangle(theEdgesId,
1146 theEdgesOri, BRepMesh_Free));
1148 Standard_Boolean isAdded = myCircles.Bind(
1150 GetVertex( theNodesId[0] ).Coord(),
1151 GetVertex( theNodesId[1] ).Coord(),
1152 GetVertex( theNodesId[2] ).Coord() );
1155 myMeshData->RemoveElement( aNewTriangleId );
1158 //=======================================================================
1159 //function : cleanupPolygon
1160 //purpose : Remove internal triangles from the given polygon
1161 //=======================================================================
1162 void BRepMesh_Delaun::cleanupPolygon(const IMeshData::SequenceOfInteger& thePolygon,
1163 const IMeshData::SequenceOfBndB2d& thePolyBoxes )
1165 Standard_Integer aPolyLen = thePolygon.Length();
1169 Handle(NCollection_IncAllocator) aAllocator =
1170 new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
1172 IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
1173 IMeshData::MapOfInteger anIgnoredEdges;
1174 IMeshData::MapOfInteger aPolyVerticesFindMap;
1175 IMeshData::VectorOfInteger aPolyVertices(256, aAllocator);
1176 // Collect boundary vertices of the polygon
1177 for ( Standard_Integer aPolyIt = 1; aPolyIt <= aPolyLen; ++aPolyIt )
1179 Standard_Integer aPolyEdgeInfo = thePolygon( aPolyIt );
1180 Standard_Integer aPolyEdgeId = Abs( aPolyEdgeInfo );
1181 anIgnoredEdges.Add( aPolyEdgeId );
1183 Standard_Boolean isForward = ( aPolyEdgeInfo > 0 );
1184 const BRepMesh_PairOfIndex& aPair =
1185 myMeshData->ElementsConnectedTo( aPolyEdgeId );
1187 Standard_Integer anElemIt = 1;
1188 for ( ; anElemIt <= aPair.Extent(); ++anElemIt )
1190 Standard_Integer anElemId = aPair.Index( anElemIt );
1194 const BRepMesh_Triangle& aElement = GetTriangle(anElemId);
1195 const Standard_Integer(&anEdges)[3] = aElement.myEdges;
1196 const Standard_Boolean(&anEdgesOri)[3] = aElement.myOrientations;
1198 Standard_Integer isTriangleFound = Standard_False;
1199 for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
1201 if ( anEdges[anEdgeIt] == aPolyEdgeId &&
1202 anEdgesOri[anEdgeIt] == isForward )
1204 isTriangleFound = Standard_True;
1205 deleteTriangle( anElemId, aLoopEdges );
1210 if ( isTriangleFound )
1214 // Skip a neighbor link to extract unique vertices each time
1217 const BRepMesh_Edge& aPolyEdge = GetEdge( aPolyEdgeId );
1218 Standard_Integer aFirstVertex = aPolyEdge.FirstNode();
1219 Standard_Integer aLastVertex = aPolyEdge.LastNode();
1221 aPolyVerticesFindMap.Add( aFirstVertex );
1222 aPolyVerticesFindMap.Add( aLastVertex );
1224 if ( aPolyEdgeInfo > 0 )
1226 aPolyVertices.Append( aFirstVertex );
1227 aPolyVertices.Append( aLastVertex );
1231 aPolyVertices.Append( aLastVertex );
1232 aPolyVertices.Append( aFirstVertex );
1237 // Make closed sequence
1238 if ( aPolyVertices.First() != aPolyVertices.Last() )
1239 aPolyVertices.Append( aPolyVertices.First() );
1241 IMeshData::MapOfInteger aSurvivedLinks( anIgnoredEdges );
1243 Standard_Integer aPolyVertIt = 0;
1244 Standard_Integer anUniqueVerticesNum = aPolyVertices.Length() - 1;
1245 for ( ; aPolyVertIt < anUniqueVerticesNum; ++aPolyVertIt )
1247 killTrianglesAroundVertex( aPolyVertices( aPolyVertIt ),
1248 aPolyVertices, aPolyVerticesFindMap, thePolygon,
1249 thePolyBoxes, aSurvivedLinks, aLoopEdges );
1252 IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
1253 for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
1255 const Standard_Integer& aLoopEdgeId = aLoopEdgesIt.Key();
1256 if ( anIgnoredEdges.Contains( aLoopEdgeId ) )
1259 if ( myMeshData->ElementsConnectedTo( aLoopEdgeId ).IsEmpty() )
1260 myMeshData->RemoveLink( aLoopEdgesIt.Key() );
1264 //=======================================================================
1265 //function : killTrianglesAroundVertex
1266 //purpose : Remove all triangles and edges that are placed
1267 // inside the polygon or crossed it.
1268 //=======================================================================
1269 void BRepMesh_Delaun::killTrianglesAroundVertex(
1270 const Standard_Integer theZombieNodeId,
1271 const IMeshData::VectorOfInteger& thePolyVertices,
1272 const IMeshData::MapOfInteger& thePolyVerticesFindMap,
1273 const IMeshData::SequenceOfInteger& thePolygon,
1274 const IMeshData::SequenceOfBndB2d& thePolyBoxes,
1275 IMeshData::MapOfInteger& theSurvivedLinks,
1276 IMeshData::MapOfIntegerInteger& theLoopEdges )
1278 IMeshData::ListOfInteger::Iterator aNeighborsIt =
1279 myMeshData->LinksConnectedTo( theZombieNodeId );
1281 // Try to infect neighbor nodes
1282 IMeshData::VectorOfInteger aVictimNodes;
1283 for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
1285 const Standard_Integer& aNeighborLinkId = aNeighborsIt.Value();
1286 if ( theSurvivedLinks.Contains( aNeighborLinkId ) )
1289 const BRepMesh_Edge& aNeighborLink = GetEdge( aNeighborLinkId );
1290 if ( aNeighborLink.Movability() == BRepMesh_Frontier )
1292 // Though, if it lies onto the polygon boundary -
1293 // take its triangles
1295 Standard_Boolean isNotIntersect =
1296 checkIntersection( aNeighborLink, thePolygon,
1297 thePolyBoxes, Standard_False, Standard_True,
1298 Standard_False, aBox );
1300 if ( isNotIntersect )
1303 theSurvivedLinks.Add( aNeighborLinkId );
1309 Standard_Integer anOtherNode = aNeighborLink.FirstNode();
1310 if ( anOtherNode == theZombieNodeId )
1311 anOtherNode = aNeighborLink.LastNode();
1313 // Possible sacrifice
1314 if ( !thePolyVerticesFindMap.Contains( anOtherNode ) )
1316 if ( isVertexInsidePolygon( anOtherNode, thePolyVertices ) )
1319 aVictimNodes.Append( anOtherNode );
1323 // Lucky. But it may intersect the polygon boundary.
1325 killTrianglesOnIntersectingLinks( aNeighborLinkId,
1326 aNeighborLink, anOtherNode, thePolygon,
1327 thePolyBoxes, theSurvivedLinks, theLoopEdges );
1334 // Add link to the survivers to avoid cycling
1335 theSurvivedLinks.Add( aNeighborLinkId );
1336 killLinkTriangles( aNeighborLinkId, theLoopEdges );
1339 // Go and do your job!
1340 IMeshData::VectorOfInteger::Iterator aVictimIt( aVictimNodes );
1341 for ( ; aVictimIt.More(); aVictimIt.Next() )
1343 killTrianglesAroundVertex( aVictimIt.Value(), thePolyVertices,
1344 thePolyVerticesFindMap, thePolygon, thePolyBoxes,
1345 theSurvivedLinks, theLoopEdges );
1349 //=======================================================================
1350 //function : isVertexInsidePolygon
1351 //purpose : Checks is the given vertex lies inside the polygon
1352 //=======================================================================
1353 Standard_Boolean BRepMesh_Delaun::isVertexInsidePolygon(
1354 const Standard_Integer& theVertexId,
1355 const IMeshData::VectorOfInteger& thePolygonVertices ) const
1357 Standard_Integer aPolyLen = thePolygonVertices.Length();
1359 return Standard_False;
1362 const gp_XY aCenterPointXY = GetVertex( theVertexId ).Coord();
1364 const BRepMesh_Vertex& aFirstVertex = GetVertex( thePolygonVertices( 0 ) );
1365 gp_Vec2d aPrevVertexDir( aFirstVertex.Coord() - aCenterPointXY );
1366 if ( aPrevVertexDir.SquareMagnitude() < Precision2 )
1367 return Standard_True;
1369 Standard_Real aTotalAng = 0.0;
1370 for ( Standard_Integer aPolyIt = 1; aPolyIt < aPolyLen; ++aPolyIt )
1372 const BRepMesh_Vertex& aPolyVertex = GetVertex( thePolygonVertices( aPolyIt ) );
1374 gp_Vec2d aCurVertexDir( aPolyVertex.Coord() - aCenterPointXY );
1375 if ( aCurVertexDir.SquareMagnitude() < Precision2 )
1376 return Standard_True;
1378 aTotalAng += aCurVertexDir.Angle( aPrevVertexDir );
1379 aPrevVertexDir = aCurVertexDir;
1382 if ( Abs( Angle2PI - aTotalAng ) > Precision::Angular() )
1383 return Standard_False;
1385 return Standard_True;
1388 //=======================================================================
1389 //function : killTrianglesOnIntersectingLinks
1390 //purpose : Checks is the given link crosses the polygon boundary.
1391 // If yes, kills its triangles and checks neighbor links on
1392 // boundary intersection. Does nothing elsewhere.
1393 //=======================================================================
1394 void BRepMesh_Delaun::killTrianglesOnIntersectingLinks(
1395 const Standard_Integer& theLinkToCheckId,
1396 const BRepMesh_Edge& theLinkToCheck,
1397 const Standard_Integer& theEndPoint,
1398 const IMeshData::SequenceOfInteger& thePolygon,
1399 const IMeshData::SequenceOfBndB2d& thePolyBoxes,
1400 IMeshData::MapOfInteger& theSurvivedLinks,
1401 IMeshData::MapOfIntegerInteger& theLoopEdges )
1403 if ( theSurvivedLinks.Contains( theLinkToCheckId ) )
1407 Standard_Boolean isNotIntersect =
1408 checkIntersection( theLinkToCheck, thePolygon,
1409 thePolyBoxes, Standard_False, Standard_False,
1410 Standard_False, aBox );
1412 theSurvivedLinks.Add( theLinkToCheckId );
1414 if ( isNotIntersect )
1417 killLinkTriangles( theLinkToCheckId, theLoopEdges );
1419 IMeshData::ListOfInteger::Iterator aNeighborsIt(
1420 myMeshData->LinksConnectedTo(theEndPoint));
1422 for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
1424 const Standard_Integer& aNeighborLinkId = aNeighborsIt.Value();
1425 const BRepMesh_Edge& aNeighborLink = GetEdge( aNeighborLinkId );
1426 Standard_Integer anOtherNode = aNeighborLink.FirstNode();
1427 if ( anOtherNode == theEndPoint )
1428 anOtherNode = aNeighborLink.LastNode();
1430 killTrianglesOnIntersectingLinks( aNeighborLinkId,
1431 aNeighborLink, anOtherNode, thePolygon,
1432 thePolyBoxes, theSurvivedLinks, theLoopEdges );
1436 //=======================================================================
1437 //function : killLinkTriangles
1438 //purpose : Kill triangles bound to the given link.
1439 //=======================================================================
1440 void BRepMesh_Delaun::killLinkTriangles(
1441 const Standard_Integer& theLinkId,
1442 IMeshData::MapOfIntegerInteger& theLoopEdges )
1444 const BRepMesh_PairOfIndex& aPair =
1445 myMeshData->ElementsConnectedTo( theLinkId );
1447 Standard_Integer anElemNb = aPair.Extent();
1448 for ( Standard_Integer aPairIt = 1; aPairIt <= anElemNb; ++aPairIt )
1450 Standard_Integer anElemId = aPair.FirstIndex();
1454 deleteTriangle( anElemId, theLoopEdges );
1458 //=======================================================================
1459 //function : getOrientedNodes
1460 //purpose : Returns start and end nodes of the given edge in respect to
1462 //=======================================================================
1463 void BRepMesh_Delaun::getOrientedNodes(const BRepMesh_Edge& theEdge,
1464 const Standard_Boolean isForward,
1465 Standard_Integer *theNodes) const
1469 theNodes[0] = theEdge.FirstNode();
1470 theNodes[1] = theEdge.LastNode();
1474 theNodes[0] = theEdge.LastNode();
1475 theNodes[1] = theEdge.FirstNode();
1479 //=======================================================================
1480 //function : processLoop
1481 //purpose : Processes loop within the given polygon formed by range of
1482 // its links specified by start and end link indices.
1483 //=======================================================================
1484 void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom,
1485 const Standard_Integer theLinkTo,
1486 const IMeshData::SequenceOfInteger& thePolygon,
1487 const IMeshData::SequenceOfBndB2d& thePolyBoxes)
1489 Standard_Integer aNbOfLinksInLoop = theLinkTo - theLinkFrom - 1;
1490 if ( aNbOfLinksInLoop < 3 )
1493 IMeshData::SequenceOfInteger aPolygon;
1494 IMeshData::SequenceOfBndB2d aPolyBoxes;
1495 for ( ; aNbOfLinksInLoop > 0; --aNbOfLinksInLoop )
1497 Standard_Integer aLoopLinkIndex = theLinkFrom + aNbOfLinksInLoop;
1498 aPolygon .Prepend( thePolygon ( aLoopLinkIndex ) );
1499 aPolyBoxes.Prepend( thePolyBoxes( aLoopLinkIndex ) );
1501 meshPolygon( aPolygon, aPolyBoxes );
1504 //=======================================================================
1505 //function : createAndReplacePolygonLink
1506 //purpose : Creates new link based on the given nodes and updates the
1508 //=======================================================================
1509 Standard_Integer BRepMesh_Delaun::createAndReplacePolygonLink(
1510 const Standard_Integer *theNodes,
1511 const gp_Pnt2d *thePnts,
1512 const Standard_Integer theRootIndex,
1513 const ReplaceFlag theReplaceFlag,
1514 IMeshData::SequenceOfInteger& thePolygon,
1515 IMeshData::SequenceOfBndB2d& thePolyBoxes )
1517 Standard_Integer aNewEdgeId =
1518 myMeshData->AddLink( BRepMesh_Edge(
1519 theNodes[0], theNodes[1], BRepMesh_Free ) );
1522 UpdateBndBox(thePnts[0].Coord(), thePnts[1].Coord(), aNewBox);
1524 switch ( theReplaceFlag )
1526 case BRepMesh_Delaun::Replace:
1527 thePolygon .SetValue( theRootIndex, aNewEdgeId );
1528 thePolyBoxes.SetValue( theRootIndex, aNewBox );
1531 case BRepMesh_Delaun::InsertAfter:
1532 thePolygon .InsertAfter( theRootIndex, aNewEdgeId );
1533 thePolyBoxes.InsertAfter( theRootIndex, aNewBox );
1536 case BRepMesh_Delaun::InsertBefore:
1537 thePolygon .InsertBefore( theRootIndex, aNewEdgeId );
1538 thePolyBoxes.InsertBefore( theRootIndex, aNewBox );
1545 //=======================================================================
1546 //function : meshPolygon
1548 //=======================================================================
1549 void BRepMesh_Delaun::meshPolygon(IMeshData::SequenceOfInteger& thePolygon,
1550 IMeshData::SequenceOfBndB2d& thePolyBoxes,
1551 Handle(IMeshData::MapOfInteger) theSkipped)
1553 // Check is the source polygon elementary
1554 if ( meshElementaryPolygon( thePolygon ) )
1557 // Check and correct boundary edges
1558 Standard_Integer aPolyLen = thePolygon.Length();
1559 const Standard_Real aPolyArea = Abs( polyArea( thePolygon, 1, aPolyLen ) );
1560 const Standard_Real aSmallLoopArea = 0.001 * aPolyArea;
1561 for ( Standard_Integer aPolyIt = 1; aPolyIt < aPolyLen; ++aPolyIt )
1563 Standard_Integer aCurEdgeInfo = thePolygon( aPolyIt );
1564 Standard_Integer aCurEdgeId = Abs( aCurEdgeInfo );
1565 const BRepMesh_Edge* aCurEdge = &GetEdge( aCurEdgeId );
1566 if ( aCurEdge->Movability() != BRepMesh_Frontier )
1569 Standard_Integer aCurNodes[2];
1570 getOrientedNodes( *aCurEdge, aCurEdgeInfo > 0, aCurNodes );
1572 gp_Pnt2d aCurPnts[2] = {
1573 GetVertex(aCurNodes[0]).Coord(),
1574 GetVertex(aCurNodes[1]).Coord()
1577 gp_Vec2d aCurVec( aCurPnts[0], aCurPnts[1] );
1579 // check further links
1580 Standard_Integer aNextPolyIt = aPolyIt + 1;
1581 for ( ; aNextPolyIt <= aPolyLen; ++aNextPolyIt )
1583 Standard_Integer aNextEdgeInfo = thePolygon( aNextPolyIt );
1584 Standard_Integer aNextEdgeId = Abs( aNextEdgeInfo );
1585 const BRepMesh_Edge* aNextEdge = &GetEdge( aNextEdgeId );
1586 if ( aNextEdge->Movability() != BRepMesh_Frontier )
1589 Standard_Integer aNextNodes[2];
1590 getOrientedNodes( *aNextEdge, aNextEdgeInfo > 0, aNextNodes );
1592 gp_Pnt2d aNextPnts[2] = {
1593 GetVertex(aNextNodes[0]).Coord(),
1594 GetVertex(aNextNodes[1]).Coord()
1598 BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge,
1599 Standard_False, Standard_True, anIntPnt );
1601 if ( aIntFlag == BRepMesh_GeomTool::NoIntersection )
1604 Standard_Boolean isRemoveFromFirst = Standard_False;
1605 Standard_Boolean isAddReplacingEdge = Standard_True;
1606 Standard_Integer aIndexToRemoveTo = aNextPolyIt;
1607 if ( aIntFlag == BRepMesh_GeomTool::Cross )
1609 Standard_Real aLoopArea = polyArea( thePolygon, aPolyIt + 1, aNextPolyIt );
1610 gp_Vec2d aVec1( anIntPnt, aCurPnts [1] );
1611 gp_Vec2d aVec2( anIntPnt, aNextPnts[0] );
1613 aLoopArea += ( aVec1 ^ aVec2 ) / 2.;
1614 if ( Abs( aLoopArea ) > aSmallLoopArea )
1616 aNextNodes[1] = aCurNodes[0];
1617 aNextPnts [1] = aCurPnts [0];
1619 aNextEdgeId = Abs( createAndReplacePolygonLink( aNextNodes, aNextPnts,
1620 aNextPolyIt, BRepMesh_Delaun::Replace, thePolygon, thePolyBoxes ) );
1622 processLoop( aPolyIt, aNextPolyIt, thePolygon, thePolyBoxes );
1626 Standard_Real aDist1 = anIntPnt.SquareDistance(aNextPnts[0]);
1627 Standard_Real aDist2 = anIntPnt.SquareDistance(aNextPnts[1]);
1629 // Choose node with lower distance
1630 const Standard_Boolean isCloseToStart = ( aDist1 < aDist2 );
1631 const Standard_Integer aEndPointIndex = isCloseToStart ? 0 : 1;
1632 aCurNodes[1] = aNextNodes[aEndPointIndex];
1633 aCurPnts [1] = aNextPnts [aEndPointIndex];
1635 if ( isCloseToStart )
1638 // In this context only intersections between frontier edges
1639 // are possible. If intersection between edges of different
1640 // types occured - treat this case as invalid (i.e. result
1641 // might not reflect the expectations).
1642 if ( !theSkipped.IsNull() )
1644 Standard_Integer aSkippedLinkIt = aPolyIt;
1645 for ( ; aSkippedLinkIt <= aIndexToRemoveTo; ++aSkippedLinkIt )
1646 theSkipped->Add( Abs( thePolygon( aSkippedLinkIt ) ) );
1649 else if ( aIntFlag == BRepMesh_GeomTool::PointOnSegment )
1651 // Indentify chopping link
1652 Standard_Boolean isFirstChopping = Standard_False;
1653 Standard_Integer aCheckPointIt = 0;
1654 for ( ; aCheckPointIt < 2; ++aCheckPointIt )
1656 gp_Pnt2d& aRefPoint = aCurPnts[aCheckPointIt];
1657 // Check is second link touches the first one
1658 gp_Vec2d aVec1( aRefPoint, aNextPnts[0] );
1659 gp_Vec2d aVec2( aRefPoint, aNextPnts[1] );
1660 if ( Abs( aVec1 ^ aVec2 ) < Precision )
1662 isFirstChopping = Standard_True;
1667 if ( isFirstChopping )
1669 // Split second link
1670 isAddReplacingEdge = Standard_False;
1671 isRemoveFromFirst = ( aCheckPointIt == 0 );
1673 Standard_Integer aSplitLink[3] = {
1675 aCurNodes [aCheckPointIt],
1679 gp_Pnt2d aSplitPnts[3] = {
1681 aCurPnts [aCheckPointIt],
1685 Standard_Integer aSplitLinkIt = 0;
1686 for ( ; aSplitLinkIt < 2; ++aSplitLinkIt )
1688 createAndReplacePolygonLink( &aSplitLink[aSplitLinkIt],
1689 &aSplitPnts[aSplitLinkIt], aNextPolyIt, ( aSplitLinkIt == 0 ) ?
1690 BRepMesh_Delaun::Replace : BRepMesh_Delaun::InsertAfter,
1691 thePolygon, thePolyBoxes );
1694 processLoop( aPolyIt + aCheckPointIt, aIndexToRemoveTo,
1695 thePolygon, thePolyBoxes );
1700 Standard_Integer aSplitLinkNodes[2] = {
1705 gp_Pnt2d aSplitLinkPnts[2] = {
1709 createAndReplacePolygonLink( aSplitLinkNodes, aSplitLinkPnts,
1710 aPolyIt, BRepMesh_Delaun::InsertAfter, thePolygon, thePolyBoxes );
1712 aCurNodes[1] = aNextNodes[1];
1713 aCurPnts [1] = aNextPnts [1];
1716 processLoop( aPolyIt + 1, aIndexToRemoveTo,
1717 thePolygon, thePolyBoxes );
1720 else if ( aIntFlag == BRepMesh_GeomTool::Glued )
1722 if ( aCurNodes[1] == aNextNodes[0] )
1724 aCurNodes[1] = aNextNodes[1];
1725 aCurPnts [1] = aNextPnts [1];
1727 // TODO: Non-adjacent glued links within the polygon
1729 else if ( aIntFlag == BRepMesh_GeomTool::Same )
1731 processLoop( aPolyIt, aNextPolyIt, thePolygon, thePolyBoxes );
1733 isRemoveFromFirst = Standard_True;
1734 isAddReplacingEdge = Standard_False;
1737 continue; // Not supported type
1739 if ( isAddReplacingEdge )
1741 aCurEdgeId = Abs( createAndReplacePolygonLink( aCurNodes, aCurPnts,
1742 aPolyIt, BRepMesh_Delaun::Replace, thePolygon, thePolyBoxes ) );
1744 aCurEdge = &GetEdge( aCurEdgeId );
1745 aCurVec = gp_Vec2d( aCurPnts[0], aCurPnts[1] );
1748 Standard_Integer aIndexToRemoveFrom =
1749 isRemoveFromFirst ? aPolyIt : aPolyIt + 1;
1751 thePolygon .Remove( aIndexToRemoveFrom, aIndexToRemoveTo );
1752 thePolyBoxes.Remove( aIndexToRemoveFrom, aIndexToRemoveTo );
1754 aPolyLen = thePolygon.Length();
1755 if ( isRemoveFromFirst )
1761 aNextPolyIt = aPolyIt;
1765 IMeshData::SequenceOfInteger* aPolygon1 = &thePolygon;
1766 IMeshData::SequenceOfBndB2d* aPolyBoxes1 = &thePolyBoxes;
1768 Handle(IMeshData::SequenceOfInteger) aPolygon2 = new IMeshData::SequenceOfInteger;
1769 Handle(IMeshData::SequenceOfBndB2d) aPolyBoxes2 = new IMeshData::SequenceOfBndB2d;
1771 NCollection_Sequence<Handle(IMeshData::SequenceOfInteger)> aPolyStack;
1772 NCollection_Sequence<Handle(IMeshData::SequenceOfBndB2d)> aPolyBoxStack;
1775 decomposeSimplePolygon(*aPolygon1, *aPolyBoxes1, *aPolygon2, *aPolyBoxes2);
1776 if (!aPolygon2->IsEmpty())
1778 aPolyStack.Append(aPolygon2);
1779 aPolyBoxStack.Append(aPolyBoxes2);
1781 aPolygon2 = new IMeshData::SequenceOfInteger;
1782 aPolyBoxes2 = new IMeshData::SequenceOfBndB2d;
1785 if (aPolygon1->IsEmpty())
1787 if (!aPolyStack.IsEmpty() && aPolygon1 == &(*aPolyStack.First()))
1789 aPolyStack.Remove(1);
1790 aPolyBoxStack.Remove(1);
1793 if (aPolyStack.IsEmpty())
1796 aPolygon1 = &(*aPolyStack.ChangeFirst());
1797 aPolyBoxes1 = &(*aPolyBoxStack.ChangeFirst());
1802 //=======================================================================
1803 //function : meshElementaryPolygon
1804 //purpose : Triangulation of closed polygon containing only three edges.
1805 //=======================================================================
1806 inline Standard_Boolean BRepMesh_Delaun::meshElementaryPolygon(
1807 const IMeshData::SequenceOfInteger& thePolygon)
1809 Standard_Integer aPolyLen = thePolygon.Length();
1811 return Standard_True;
1812 else if ( aPolyLen > 3 )
1813 return Standard_False;
1815 // Just create a triangle
1816 Standard_Integer anEdges[3];
1817 Standard_Boolean anEdgesOri[3];
1819 for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
1821 Standard_Integer anEdgeInfo = thePolygon( anEdgeIt + 1 );
1822 anEdges[anEdgeIt] = Abs( anEdgeInfo );
1823 anEdgesOri[anEdgeIt] = ( anEdgeInfo > 0 );
1826 const BRepMesh_Edge& anEdge1 = GetEdge( anEdges[0] );
1827 const BRepMesh_Edge& anEdge2 = GetEdge( anEdges[1] );
1829 Standard_Integer aNodes[3] = { anEdge1.FirstNode(),
1831 anEdge2.FirstNode() };
1832 if ( aNodes[2] == aNodes[0] ||
1833 aNodes[2] == aNodes[1] )
1835 aNodes[2] = anEdge2.LastNode();
1838 addTriangle( anEdges, anEdgesOri, aNodes );
1839 return Standard_True;
1842 //=======================================================================
1843 //function : meshSimplePolygon
1845 //=======================================================================
1846 void BRepMesh_Delaun::decomposeSimplePolygon(
1847 IMeshData::SequenceOfInteger& thePolygon,
1848 IMeshData::SequenceOfBndB2d& thePolyBoxes,
1849 IMeshData::SequenceOfInteger& thePolygonCut,
1850 IMeshData::SequenceOfBndB2d& thePolyBoxesCut)
1852 // Check is the given polygon elementary
1853 if ( meshElementaryPolygon( thePolygon ) )
1856 thePolyBoxes.Clear();
1860 // Polygon contains more than 3 links
1861 Standard_Integer aFirstEdgeInfo = thePolygon(1);
1862 const BRepMesh_Edge& aFirstEdge = GetEdge( Abs( aFirstEdgeInfo ) );
1864 Standard_Integer aNodes[3];
1865 getOrientedNodes( aFirstEdge, aFirstEdgeInfo > 0, aNodes );
1867 gp_Pnt2d aRefVertices[3];
1868 aRefVertices[0] = GetVertex( aNodes[0] ).Coord();
1869 aRefVertices[1] = GetVertex( aNodes[1] ).Coord();
1871 gp_Vec2d aRefEdgeDir( aRefVertices[0], aRefVertices[1] );
1873 Standard_Real aRefEdgeLen = aRefEdgeDir.Magnitude();
1874 if ( aRefEdgeLen < Precision )
1877 thePolyBoxes.Clear();
1881 aRefEdgeDir /= aRefEdgeLen;
1883 // Find a point with minimum distance respect
1884 // the end of reference link
1885 Standard_Integer aUsedLinkId = 0;
1886 Standard_Real aOptAngle = 0.0;
1887 Standard_Real aMinDist = RealLast();
1888 Standard_Integer aPivotNode = aNodes[1];
1889 Standard_Integer aPolyLen = thePolygon.Length();
1890 for ( Standard_Integer aLinkIt = 3; aLinkIt <= aPolyLen; ++aLinkIt )
1892 Standard_Integer aLinkInfo = thePolygon( aLinkIt );
1893 const BRepMesh_Edge& aNextEdge = GetEdge( Abs( aLinkInfo ) );
1895 aPivotNode = aLinkInfo > 0 ?
1896 aNextEdge.FirstNode() :
1897 aNextEdge.LastNode();
1899 gp_Pnt2d aPivotVertex = GetVertex( aPivotNode ).Coord();
1900 gp_Vec2d aDistanceDir( aRefVertices[1], aPivotVertex );
1902 Standard_Real aDist = aRefEdgeDir ^ aDistanceDir;
1903 Standard_Real aAngle = Abs( aRefEdgeDir.Angle(aDistanceDir) );
1904 Standard_Real anAbsDist = Abs( aDist );
1905 if (anAbsDist < Precision || aDist < 0.)
1908 if ( ( anAbsDist >= aMinDist ) &&
1909 ( aAngle <= aOptAngle || aAngle > AngDeviation90Deg ) )
1914 // Check is the test link crosses the polygon boudaries
1915 Standard_Boolean isIntersect = Standard_False;
1916 for ( Standard_Integer aRefLinkNodeIt = 0; aRefLinkNodeIt < 2; ++aRefLinkNodeIt )
1918 const Standard_Integer& aLinkFirstNode = aNodes[aRefLinkNodeIt];
1919 const gp_Pnt2d& aLinkFirstVertex = aRefVertices[aRefLinkNodeIt];
1922 UpdateBndBox(aLinkFirstVertex.Coord(), aPivotVertex.Coord(), aBox);
1924 BRepMesh_Edge aCheckLink( aLinkFirstNode, aPivotNode, BRepMesh_Free );
1926 Standard_Integer aCheckLinkIt = 2;
1927 for ( ; aCheckLinkIt <= aPolyLen; ++aCheckLinkIt )
1929 if( aCheckLinkIt == aLinkIt )
1932 if ( !aBox.IsOut( thePolyBoxes.Value( aCheckLinkIt ) ) )
1934 const BRepMesh_Edge& aPolyLink =
1935 GetEdge( Abs( thePolygon( aCheckLinkIt ) ) );
1937 if ( aCheckLink.IsEqual( aPolyLink ) )
1940 // intersection is possible...
1942 BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink,
1943 Standard_False, Standard_False, anIntPnt );
1945 if( aIntFlag != BRepMesh_GeomTool::NoIntersection )
1947 isIntersect = Standard_True;
1962 aMinDist = anAbsDist;
1963 aNodes[2] = aPivotNode;
1964 aRefVertices[2] = aPivotVertex;
1965 aUsedLinkId = aLinkIt;
1968 if ( aUsedLinkId == 0 )
1971 thePolyBoxes.Clear();
1976 BRepMesh_Edge aNewEdges[2] = {
1977 BRepMesh_Edge( aNodes[1], aNodes[2], BRepMesh_Free ),
1978 BRepMesh_Edge( aNodes[2], aNodes[0], BRepMesh_Free ) };
1980 Standard_Integer aNewEdgesInfo[3] = {
1982 myMeshData->AddLink( aNewEdges[0] ),
1983 myMeshData->AddLink( aNewEdges[1] ) };
1986 Standard_Integer anEdges[3];
1987 Standard_Boolean anEdgesOri[3];
1988 for ( Standard_Integer aTriEdgeIt = 0; aTriEdgeIt < 3; ++aTriEdgeIt )
1990 const Standard_Integer& anEdgeInfo = aNewEdgesInfo[aTriEdgeIt];
1991 anEdges[aTriEdgeIt] = Abs( anEdgeInfo );
1992 anEdgesOri[aTriEdgeIt] = anEdgeInfo > 0;
1994 addTriangle( anEdges, anEdgesOri, aNodes );
1996 // Create triangle and split the source polygon on two
1997 // parts (if possible) and mesh each part as independent
1999 if ( aUsedLinkId < aPolyLen )
2001 thePolygon.Split(aUsedLinkId, thePolygonCut);
2002 thePolygonCut.Prepend( -aNewEdgesInfo[2] );
2003 thePolyBoxes.Split(aUsedLinkId, thePolyBoxesCut);
2006 UpdateBndBox(aRefVertices[0].Coord(), aRefVertices[2].Coord(), aBox);
2007 thePolyBoxesCut.Prepend( aBox );
2011 thePolygon.Remove ( aPolyLen );
2012 thePolyBoxes.Remove( aPolyLen );
2015 if ( aUsedLinkId > 3 )
2017 thePolygon.SetValue( 1, -aNewEdgesInfo[1] );
2020 UpdateBndBox(aRefVertices[1].Coord(), aRefVertices[2].Coord(), aBox);
2021 thePolyBoxes.SetValue( 1, aBox );
2025 //=======================================================================
2026 //function : RemoveVertex
2027 //purpose : Removes a vertex from the triangulation
2028 //=======================================================================
2029 void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex )
2031 BRepMesh_SelectorOfDataStructureOfDelaun aSelector( myMeshData );
2032 aSelector.NeighboursOf( theVertex );
2034 IMeshData::MapOfIntegerInteger aLoopEdges;//( 10, myMeshData->Allocator() );
2036 // Loop on triangles to be destroyed :
2037 IMeshData::IteratorOfMapOfInteger aTriangleIt( aSelector.Elements() );
2038 for ( ; aTriangleIt.More(); aTriangleIt.Next() )
2039 deleteTriangle( aTriangleIt.Key(), aLoopEdges );
2041 IMeshData::SequenceOfBndB2d aBoxes;
2042 IMeshData::SequenceOfInteger aPolygon;
2043 Standard_Integer aLoopEdgesCount = aLoopEdges.Extent();
2044 IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
2046 if ( aLoopEdgesIt.More() )
2048 const BRepMesh_Edge& anEdge = GetEdge( aLoopEdgesIt.Key() );
2049 Standard_Integer aFirstNode = anEdge.FirstNode();
2050 Standard_Integer aLastNode;
2051 Standard_Integer aPivotNode = anEdge.LastNode();
2052 Standard_Integer anEdgeId = aLoopEdgesIt.Key();
2054 Standard_Boolean isPositive = aLoopEdges( anEdgeId ) != 0;
2057 Standard_Integer aTmp;
2059 aFirstNode = aPivotNode;
2062 aPolygon.Append( -anEdgeId );
2065 aPolygon.Append( anEdgeId );
2067 fillBndBox( aBoxes, GetVertex( aFirstNode ), GetVertex( aPivotNode ) );
2069 aLoopEdges.UnBind( anEdgeId );
2071 aLastNode = aFirstNode;
2072 while ( aPivotNode != aLastNode )
2074 IMeshData::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( aPivotNode ) );
2075 for ( ; aLinkIt.More(); aLinkIt.Next() )
2077 if ( aLinkIt.Value() != anEdgeId &&
2078 aLoopEdges.IsBound( aLinkIt.Value() ) )
2080 Standard_Integer aCurrentNode;
2081 anEdgeId = aLinkIt.Value();
2082 const BRepMesh_Edge& anEdge1 = GetEdge( anEdgeId );
2084 aCurrentNode = anEdge1.LastNode();
2085 if ( aCurrentNode != aPivotNode )
2087 aCurrentNode = anEdge1.FirstNode();
2088 aPolygon.Append( -anEdgeId );
2091 aPolygon.Append( anEdgeId );
2093 fillBndBox( aBoxes, GetVertex( aCurrentNode ), GetVertex( aPivotNode ) );
2095 aPivotNode = aCurrentNode;
2096 aLoopEdges.UnBind( anEdgeId );
2101 if ( aLoopEdgesCount <= 0 )
2106 meshPolygon( aPolygon, aBoxes );
2111 //=======================================================================
2112 //function : AddVertices
2113 //purpose : Adds some vertices in the triangulation.
2114 //=======================================================================
2115 void BRepMesh_Delaun::AddVertices(IMeshData::VectorOfInteger& theVertices)
2117 ComparatorOfIndexedVertexOfDelaun aCmp(myMeshData);
2118 std::make_heap(theVertices.begin(), theVertices.end(), aCmp);
2119 std::sort_heap(theVertices.begin(), theVertices.end(), aCmp);
2121 createTrianglesOnNewVertices(theVertices);
2124 //=======================================================================
2125 //function : UseEdge
2126 //purpose : Modify mesh to use the edge. Return True if done
2127 //=======================================================================
2128 Standard_Boolean BRepMesh_Delaun::UseEdge( const Standard_Integer /*theIndex*/ )
2131 const BRepMesh_PairOfIndex& aPair = myMeshData->ElemConnectedTo( theIndex );
2132 if ( aPair.Extent() == 0 )
2134 const BRepMesh_Edge& anEdge = GetEdge( theIndex );
2136 Standard_Integer aStartNode, aPivotNode, anOtherNode;
2137 aStartNode = anEdge.FirstNode();
2138 aPivotNode = anEdge.LastNode();
2140 const BRepMesh_ListOfInteger& aStartNodeNeighbors = myMeshData->LinkNeighboursOf( aStartNode );
2141 const BRepMesh_ListOfInteger& aPivotNodeNeighbors = myMeshData->LinkNeighboursOf( aPivotNode );
2143 if ( aStartNodeNeighbors.Extent() > 0 &&
2144 aPivotNodeNeighbors.Extent() > 0 )
2146 const BRepMesh_Vertex& aStartVertex = GetVertex( aStartNode );
2147 const BRepMesh_Vertex& aPivotVertex = GetVertex( aPivotNode );
2149 gp_XY aVEdge ( aPivotVertex.Coord() );
2150 aVEdge.Subtract( aStartVertex.Coord() );
2152 Standard_Real anAngle = 0.;
2153 Standard_Real anAngleMin = RealLast();
2154 Standard_Real anAngleMax = RealFirst();
2155 Standard_Integer aLeftEdge = 0, aRightEdge = 0;
2157 BRepMesh_ListOfInteger::Iterator aNeighborIt( aPivotNodeNeighbors );
2158 for ( ; aNeighborIt.More(); aNeighborIt.Next() )
2160 Standard_Integer anEdgeId = aNeighborIt.Value();
2161 if ( anEdgeId != theIndex )
2163 const BRepMesh_Edge& aNextEdge = GetEdge( anEdgeId );
2165 Standard_Boolean isInMesh = Standard_True;
2166 if ( aNextEdge.Movability() == BRepMesh_Free )
2168 if ( myMeshData->ElemConnectedTo( anEdgeId ).IsEmpty() )
2169 isInMesh = Standard_False;
2174 anOtherNode = aNextEdge.FirstNode();
2175 if ( anOtherNode == aPivotNode )
2176 anOtherNode = aNextEdge.LastNode();
2178 gp_XY aVEdgeCur = GetVertex( anOtherNode ).Coord();
2179 aVEdgeCur.Subtract( aPivotVertex.Coord() );
2181 anAngle = gp_Vec2d( aVEdge ).Angle( gp_Vec2d( aVEdgeCur ) );
2184 if ( anAngle > anAngleMax )
2186 anAngleMax = anAngle;
2187 aLeftEdge = anEdgeId;
2189 if ( anAngle < anAngleMin )
2191 anAngleMin = anAngle;
2192 aRightEdge = anEdgeId;
2197 if ( aLeftEdge > 0 )
2199 if (aLeftEdge==aRightEdge)
2209 return Standard_False;
2212 //=======================================================================
2213 //function : getEdgesByType
2214 //purpose : Gives the list of edges with type defined by input parameter
2215 //=======================================================================
2216 Handle(IMeshData::MapOfInteger) BRepMesh_Delaun::getEdgesByType(
2217 const BRepMesh_DegreeOfFreedom theEdgeType ) const
2219 Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
2220 Handle(IMeshData::MapOfInteger) aResult = new IMeshData::MapOfInteger;
2221 IMeshData::IteratorOfMapOfInteger anEdgeIt( myMeshData->LinksOfDomain() );
2223 for ( ; anEdgeIt.More(); anEdgeIt.Next() )
2225 Standard_Integer anEdge = anEdgeIt.Key();
2226 Standard_Boolean isToAdd = (theEdgeType == BRepMesh_Free) ?
2227 (myMeshData->ElementsConnectedTo( anEdge ).Extent() <= 1) :
2228 (GetEdge( anEdge ).Movability() == theEdgeType);
2231 aResult->Add( anEdge );
2237 //=======================================================================
2238 //function : calculateDist
2239 //purpose : Calculates distances between the given point and edges of
2241 //=======================================================================
2242 Standard_Real BRepMesh_Delaun::calculateDist( const gp_XY theVEdges[3],
2243 const gp_XY thePoints[3],
2244 const BRepMesh_Vertex& theVertex,
2245 Standard_Real theDistance[3],
2246 Standard_Real theSqModulus[3],
2247 Standard_Integer& theEdgeOn ) const
2249 Standard_Real aMinDist = RealLast();
2250 for( Standard_Integer i = 0; i < 3; ++i )
2252 theSqModulus[i] = theVEdges[i].SquareModulus();
2253 if ( theSqModulus[i] <= Precision2 )
2256 theDistance[i] = theVEdges[i] ^ ( theVertex.Coord() - thePoints[i] );
2258 Standard_Real aDist = theDistance[i] * theDistance[i];
2259 aDist /= theSqModulus[i];
2261 if ( aDist < aMinDist )
2271 //=======================================================================
2272 //function : Contains
2273 //purpose : Test if triangle of index <TrianIndex> contains geometricaly
2274 // <theVertex>. If <theEdgeOn> is != 0 then theVertex is on Edge
2275 // of index <theEdgeOn>
2276 //=======================================================================
2277 Standard_Boolean BRepMesh_Delaun::Contains( const Standard_Integer theTriangleId,
2278 const BRepMesh_Vertex& theVertex,
2279 const Standard_Real theSqTolerance,
2280 Standard_Integer& theEdgeOn) const
2284 Standard_Integer p[3];
2286 const BRepMesh_Triangle& aElement = GetTriangle( theTriangleId );
2287 const Standard_Integer(&e)[3] = aElement.myEdges;
2289 const BRepMesh_Edge* anEdges[3] = { &GetEdge( e[0] ),
2293 myMeshData->ElementNodes(aElement, p);
2296 aPoints[0] = GetVertex( p[0] ).Coord();
2297 aPoints[1] = GetVertex( p[1] ).Coord();
2298 aPoints[2] = GetVertex( p[2] ).Coord();
2301 aVEdges[0] = aPoints[1];
2302 aVEdges[0].Subtract( aPoints[0] );
2304 aVEdges[1] = aPoints[2];
2305 aVEdges[1].Subtract( aPoints[1] );
2307 aVEdges[2] = aPoints[0];
2308 aVEdges[2].Subtract( aPoints[2] );
2310 Standard_Real aDistance[3];
2311 Standard_Real aSqModulus[3];
2313 Standard_Real aSqMinDist;
2314 Standard_Integer aEdgeOnId;
2315 aSqMinDist = calculateDist( aVEdges, aPoints, theVertex, aDistance, aSqModulus, aEdgeOnId );
2316 if ( aSqMinDist < 0 )
2317 return Standard_False;
2319 const Standard_Boolean isNotFree = (anEdges[aEdgeOnId]->Movability() != BRepMesh_Free);
2320 if ( aSqMinDist > theSqTolerance )
2322 if (isNotFree && aDistance[aEdgeOnId] < ( aSqModulus[aEdgeOnId] / 5. ))
2323 theEdgeOn = e[aEdgeOnId];
2326 return Standard_False;
2328 theEdgeOn = e[aEdgeOnId];
2330 return (aDistance[0] >= 0. && aDistance[1] >= 0. && aDistance[2] >= 0.);
2333 //=============================================================================
2334 //function : intSegSeg
2335 //purpose : Checks intersection between the two segments.
2336 //=============================================================================
2337 BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg(
2338 const BRepMesh_Edge& theEdg1,
2339 const BRepMesh_Edge& theEdg2,
2340 const Standard_Boolean isConsiderEndPointTouch,
2341 const Standard_Boolean isConsiderPointOnEdge,
2342 gp_Pnt2d& theIntPnt) const
2344 gp_XY p1, p2, p3, p4;
2345 p1 = GetVertex( theEdg1.FirstNode() ).Coord();
2346 p2 = GetVertex( theEdg1.LastNode() ).Coord();
2347 p3 = GetVertex( theEdg2.FirstNode() ).Coord();
2348 p4 = GetVertex( theEdg2.LastNode() ).Coord();
2350 return BRepMesh_GeomTool::IntSegSeg(p1, p2, p3, p4,
2351 isConsiderEndPointTouch, isConsiderPointOnEdge, theIntPnt);
2354 //=============================================================================
2355 //function : polyArea
2356 //purpose : Returns area of the loop of the given polygon defined by indices
2357 // of its start and end links.
2358 //=============================================================================
2359 Standard_Real BRepMesh_Delaun::polyArea(const IMeshData::SequenceOfInteger& thePolygon,
2360 const Standard_Integer theStartIndex,
2361 const Standard_Integer theEndIndex) const
2363 Standard_Real aArea = 0.0;
2364 Standard_Integer aPolyLen = thePolygon.Length();
2365 if ( theStartIndex >= theEndIndex ||
2366 theStartIndex > aPolyLen )
2370 Standard_Integer aCurEdgeInfo = thePolygon( theStartIndex );
2371 Standard_Integer aCurEdgeId = Abs( aCurEdgeInfo );
2372 const BRepMesh_Edge* aCurEdge = &GetEdge( aCurEdgeId );
2374 Standard_Integer aNodes[2];
2375 getOrientedNodes( *aCurEdge, aCurEdgeInfo > 0, aNodes );
2377 gp_Pnt2d aRefPnt = GetVertex( aNodes[0] ).Coord();
2378 Standard_Integer aPolyIt = theStartIndex + 1;
2379 for ( ; aPolyIt <= theEndIndex; ++aPolyIt )
2381 aCurEdgeInfo = thePolygon( aPolyIt );
2382 aCurEdgeId = Abs( aCurEdgeInfo );
2383 aCurEdge = &GetEdge( aCurEdgeId );
2385 getOrientedNodes( *aCurEdge, aCurEdgeInfo > 0, aNodes );
2386 gp_Vec2d aVec1( aRefPnt, GetVertex( aNodes[0] ).Coord() );
2387 gp_Vec2d aVec2( aRefPnt, GetVertex( aNodes[1] ).Coord() );
2389 aArea += aVec1 ^ aVec2;
2396 //=======================================================================
2397 //function : BRepMesh_DumpPoly
2399 //=======================================================================
2400 #include <TopoDS_Compound.hxx>
2401 #include <BRep_Builder.hxx>
2402 #include <Standard_ErrorHandler.hxx>
2403 #include <BRepBuilderAPI_MakeEdge.hxx>
2404 #include <BRepTools.hxx>
2405 Standard_CString BRepMesh_DumpPoly(void* thePolygon,
2406 void* theMeshHandlePtr,
2407 Standard_CString theFileNameStr)
2409 if (thePolygon == 0 || theFileNameStr == 0)
2411 return "Error: file name or polygon data is null";
2414 IMeshData::SequenceOfInteger& aPolygon = *(IMeshData::SequenceOfInteger*)thePolygon;
2416 Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
2417 *(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
2419 if (aMeshData.IsNull())
2420 return "Error: mesh data is empty";
2422 TopoDS_Compound aMesh;
2423 BRep_Builder aBuilder;
2424 aBuilder.MakeCompound(aMesh);
2430 IMeshData::SequenceOfInteger::Iterator aLinksIt(aPolygon);
2431 for (; aLinksIt.More(); aLinksIt.Next())
2433 const BRepMesh_Edge& aLink = aMeshData->GetLink(Abs(aLinksIt.Value()));
2436 for (Standard_Integer i = 0; i < 2; ++i)
2438 const Standard_Integer aNodeId =
2439 (i == 0) ? aLink.FirstNode() : aLink.LastNode();
2441 const gp_XY& aNode = aMeshData->GetNode(aNodeId).Coord();
2442 aPnt[i] = gp_Pnt(aNode.X(), aNode.Y(), 0.);
2445 if (aPnt[0].SquareDistance(aPnt[1]) < Precision::SquareConfusion())
2448 aBuilder.Add(aMesh, BRepBuilderAPI_MakeEdge(aPnt[0], aPnt[1]));
2451 if (!BRepTools::Write(aMesh, theFileNameStr))
2452 return "Error: write failed";
2454 catch (Standard_Failure const& anException)
2456 return anException.GetMessageString();
2459 return theFileNameStr;