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;
72 } // anonymous namespace
74 //=======================================================================
75 //function : BRepMesh_Delaun
76 //purpose : Creates the triangulation with an empty Mesh data structure
77 //=======================================================================
78 BRepMesh_Delaun::BRepMesh_Delaun(
79 BRepMesh::Array1OfVertexOfDelaun& theVertices)
80 : myCircles( theVertices.Length(), new NCollection_IncAllocator() )
82 if ( theVertices.Length() > 2 )
84 myMeshData = new BRepMesh_DataStructureOfDelaun( new NCollection_IncAllocator(),
85 theVertices.Length() );
90 //=======================================================================
91 //function : BRepMesh_Delaun
92 //purpose : Creates the triangulation with and existent Mesh data structure
93 //=======================================================================
94 BRepMesh_Delaun::BRepMesh_Delaun(
95 const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh,
96 BRepMesh::Array1OfVertexOfDelaun& theVertices)
97 : myCircles( theVertices.Length(), theOldMesh->Allocator() )
99 myMeshData = theOldMesh;
100 if ( theVertices.Length() > 2 )
104 //=======================================================================
105 //function : BRepMesh_Delaun
106 //purpose : Creates the triangulation with and existent Mesh data structure
107 //=======================================================================
108 BRepMesh_Delaun::BRepMesh_Delaun(
109 const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh,
110 BRepMesh::Array1OfInteger& theVertexIndices)
111 : myCircles( theVertexIndices.Length(), theOldMesh->Allocator() )
113 myMeshData = theOldMesh;
114 if ( theVertexIndices.Length() > 2 )
117 Standard_Integer anIndex = theVertexIndices.Lower();
118 Standard_Integer anUpper = theVertexIndices.Upper();
119 for ( ; anIndex <= anUpper; ++anIndex )
120 aBox.Add( gp_Pnt2d( GetVertex( theVertexIndices( anIndex) ).Coord() ) );
122 perform( aBox, theVertexIndices );
126 //=======================================================================
128 //purpose : Initializes the triangulation with an Array of Vertex
129 //=======================================================================
130 void BRepMesh_Delaun::Init(BRepMesh::Array1OfVertexOfDelaun& theVertices)
133 Standard_Integer aLowerIdx = theVertices.Lower();
134 Standard_Integer anUpperIdx = theVertices.Upper();
135 BRepMesh::Array1OfInteger aVertexIndexes( aLowerIdx, anUpperIdx );
137 Standard_Integer anIndex = aLowerIdx;
138 for ( ; anIndex <= anUpperIdx; ++anIndex )
140 aBox.Add( gp_Pnt2d( theVertices( anIndex ).Coord() ) );
141 aVertexIndexes( anIndex ) = myMeshData->AddNode( theVertices( anIndex ) );
144 perform( aBox, aVertexIndexes );
147 //=======================================================================
149 //purpose : Create super mesh and run triangulation procedure
150 //=======================================================================
151 void BRepMesh_Delaun::perform(Bnd_Box2d& theBndBox,
152 BRepMesh::Array1OfInteger& theVertexIndexes)
154 theBndBox.Enlarge( Precision );
155 superMesh( theBndBox );
157 ComparatorOfIndexedVertexOfDelaun aCmp(myMeshData);
158 std::make_heap(theVertexIndexes.begin(), theVertexIndexes.end(), aCmp);
159 std::sort_heap(theVertexIndexes.begin(), theVertexIndexes.end(), aCmp);
161 compute( theVertexIndexes );
164 //=======================================================================
165 //function : superMesh
166 //purpose : Build the super mesh
167 //=======================================================================
168 void BRepMesh_Delaun::superMesh( const Bnd_Box2d& theBox )
170 Standard_Real aMinX, aMinY, aMaxX, aMaxY;
171 theBox.Get( aMinX, aMinY, aMaxX, aMaxY );
172 Standard_Real aDeltaX = aMaxX - aMinX;
173 Standard_Real aDeltaY = aMaxY - aMinY;
175 Standard_Real aDeltaMin = Min( aDeltaX, aDeltaY );
176 Standard_Real aDeltaMax = Max( aDeltaX, aDeltaY );
177 Standard_Real aDelta = aDeltaX + aDeltaY;
179 myCircles.SetMinMaxSize( gp_XY( aMinX, aMinY ), gp_XY( aMaxX, aMaxY ) );
181 Standard_Integer aScaler = 2;
182 if ( myMeshData->NbNodes() > 100 )
184 else if( myMeshData->NbNodes() > 1000 )
187 myCircles.SetCellSize( aDeltaX / aScaler,
190 mySupVert[0] = myMeshData->AddNode(
191 BRepMesh_Vertex( ( aMinX + aMaxX ) / 2, aMaxY + aDeltaMax, BRepMesh_Free ) );
193 mySupVert[1] = myMeshData->AddNode(
194 BRepMesh_Vertex( aMinX - aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
196 mySupVert[2] = myMeshData->AddNode(
197 BRepMesh_Vertex( aMaxX + aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
199 Standard_Integer e[3];
200 Standard_Boolean o[3];
201 for (Standard_Integer aNodeId = 0; aNodeId < 3; ++aNodeId)
203 Standard_Integer aFirstNode = aNodeId;
204 Standard_Integer aLastNode = (aNodeId + 1) % 3;
205 Standard_Integer aLinkIndex = myMeshData->AddLink( BRepMesh_Edge(
206 mySupVert[aFirstNode], mySupVert[aLastNode], BRepMesh_Free ) );
208 e[aNodeId] = Abs(aLinkIndex);
209 o[aNodeId] = (aLinkIndex > 0);
212 mySupTrian = BRepMesh_Triangle(e, o, BRepMesh_Free);
215 //=======================================================================
216 //function : deleteTriangle
217 //purpose : Deletes the triangle with the given index and adds the free
218 // edges into the map.
219 // When an edge is suppressed more than one time it is destroyed.
220 //=======================================================================
221 void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex,
222 BRepMesh::MapOfIntegerInteger& theLoopEdges )
224 myCircles.Delete( theIndex );
226 Standard_Integer e[3];
227 Standard_Boolean o[3];
228 GetTriangle( theIndex ).Edges( e, o );
230 myMeshData->RemoveElement( theIndex );
232 for ( Standard_Integer i = 0; i < 3; ++i )
234 if ( !theLoopEdges.Bind( e[i], o[i] ) )
236 theLoopEdges.UnBind( e[i] );
237 myMeshData->RemoveLink( e[i] );
242 //=======================================================================
244 //purpose : Computes the triangulation and add the vertices edges and
245 // triangles to the Mesh data structure
246 //=======================================================================
247 void BRepMesh_Delaun::compute(BRepMesh::Array1OfInteger& theVertexIndexes)
249 // Insertion of edges of super triangles in the list of free edges:
250 BRepMesh::MapOfIntegerInteger aLoopEdges( 10, myMeshData->Allocator() );
251 Standard_Integer e[3];
252 Standard_Boolean o[3];
253 mySupTrian.Edges( e, o );
255 aLoopEdges.Bind( e[0], Standard_True );
256 aLoopEdges.Bind( e[1], Standard_True );
257 aLoopEdges.Bind( e[2], Standard_True );
259 if ( theVertexIndexes.Length() > 0 )
261 // Creation of 3 trianglers with the first node and the edges of the super triangle:
262 Standard_Integer anVertexIdx = theVertexIndexes.Lower();
263 createTriangles( theVertexIndexes( anVertexIdx ), aLoopEdges );
265 // Add other nodes to the mesh
266 createTrianglesOnNewVertices( theVertexIndexes );
269 // Destruction of triangles containing a top of the super triangle
270 BRepMesh_SelectorOfDataStructureOfDelaun aSelector( myMeshData );
271 for (Standard_Integer aSupVertId = 0; aSupVertId < 3; ++aSupVertId)
272 aSelector.NeighboursOfNode( mySupVert[aSupVertId] );
275 BRepMesh::MapOfInteger::Iterator aFreeTriangles( aSelector.Elements() );
276 for ( ; aFreeTriangles.More(); aFreeTriangles.Next() )
277 deleteTriangle( aFreeTriangles.Key(), aLoopEdges );
279 // All edges that remain free are removed from aLoopEdges;
280 // only the boundary edges of the triangulation remain there
281 BRepMesh::MapOfIntegerInteger::Iterator aFreeEdges( aLoopEdges );
282 for ( ; aFreeEdges.More(); aFreeEdges.Next() )
284 if ( myMeshData->ElementsConnectedTo( aFreeEdges.Key() ).IsEmpty() )
285 myMeshData->RemoveLink( aFreeEdges.Key() );
288 // The tops of the super triangle are destroyed
289 for (Standard_Integer aSupVertId = 0; aSupVertId < 3; ++aSupVertId)
290 myMeshData->RemoveNode( mySupVert[aSupVertId] );
293 //=======================================================================
294 //function : createTriangles
295 //purpose : Creates the triangles beetween the node and the polyline.
296 //=======================================================================
297 void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex,
298 BRepMesh::MapOfIntegerInteger& thePoly)
300 BRepMesh::ListOfInteger aLoopEdges, anExternalEdges;
301 const gp_XY& aVertexCoord = myMeshData->GetNode( theVertexIndex ).Coord();
303 BRepMesh::MapOfIntegerInteger::Iterator anEdges( thePoly );
304 for ( ; anEdges.More(); anEdges.Next() )
306 Standard_Integer anEdgeId = anEdges.Key();
307 const BRepMesh_Edge& anEdge = GetEdge( anEdgeId );
309 Standard_Boolean isPositive = (Standard_Boolean)thePoly( anEdgeId );
311 Standard_Integer aNodes[3];
314 aNodes[0] = anEdge.FirstNode();
315 aNodes[2] = anEdge.LastNode();
319 aNodes[0] = anEdge.LastNode();
320 aNodes[2] = anEdge.FirstNode();
322 aNodes[1] = theVertexIndex;
324 const BRepMesh_Vertex& aFirstVertex = GetVertex( aNodes[0] );
325 const BRepMesh_Vertex& aLastVertex = GetVertex( aNodes[2] );
327 gp_XY anEdgeDir( aLastVertex.Coord() - aFirstVertex.Coord() );
328 Standard_Real anEdgeLen = anEdgeDir.Modulus();
329 if ( anEdgeLen < Precision )
332 anEdgeDir.SetCoord( anEdgeDir.X() / anEdgeLen,
333 anEdgeDir.Y() / anEdgeLen );
335 gp_XY aFirstLinkDir( aFirstVertex.Coord() - aVertexCoord );
336 gp_XY aLastLinkDir ( aVertexCoord - aLastVertex.Coord() );
338 Standard_Real aDist12 = aFirstLinkDir ^ anEdgeDir;
339 Standard_Real aDist23 = anEdgeDir ^ aLastLinkDir;
340 if ( Abs( aDist12 ) < Precision ||
341 Abs( aDist23 ) < Precision )
346 BRepMesh_Edge aFirstLink( aNodes[1], aNodes[0], BRepMesh_Free );
347 BRepMesh_Edge aLastLink ( aNodes[2], aNodes[1], BRepMesh_Free );
349 Standard_Integer anEdgesInfo[3] = {
350 myMeshData->AddLink( aFirstLink ),
351 isPositive ? anEdgeId : -anEdgeId,
352 myMeshData->AddLink( aLastLink ) };
354 Standard_Boolean isSensOK = (aDist12 > 0. && aDist23 > 0.);
357 Standard_Integer anEdges[3];
358 Standard_Boolean anEdgesOri[3];
359 for ( Standard_Integer aTriLinkIt = 0; aTriLinkIt < 3; ++aTriLinkIt )
361 const Standard_Integer& anEdgeInfo = anEdgesInfo[aTriLinkIt];
362 anEdges[aTriLinkIt] = Abs( anEdgeInfo );
363 anEdgesOri[aTriLinkIt] = anEdgeInfo > 0;
366 addTriangle( anEdges, anEdgesOri, aNodes );
371 aLoopEdges.Append( anEdges.Key() );
373 aLoopEdges.Append( -anEdges.Key() );
375 if ( aFirstLinkDir.SquareModulus() > aLastLinkDir.SquareModulus() )
376 anExternalEdges.Append( Abs( anEdgesInfo[0] ) );
378 anExternalEdges.Append( Abs( anEdgesInfo[2] ) );
383 while ( !anExternalEdges.IsEmpty() )
385 const BRepMesh_PairOfIndex& aPair =
386 myMeshData->ElementsConnectedTo( Abs( anExternalEdges.First() ) );
389 if ( !aPair.IsEmpty() )
390 deleteTriangle( aPair.FirstIndex(), thePoly );
392 anExternalEdges.RemoveFirst();
395 for ( anEdges.Initialize( thePoly ); anEdges.More(); anEdges.Next() )
397 if ( myMeshData->ElementsConnectedTo( anEdges.Key() ).IsEmpty() )
398 myMeshData->RemoveLink( anEdges.Key() );
401 while ( !aLoopEdges.IsEmpty() )
403 const BRepMesh_Edge& anEdge = GetEdge( Abs( aLoopEdges.First() ) );
404 if ( anEdge.Movability() != BRepMesh_Deleted )
406 Standard_Integer anEdgeIdx = aLoopEdges.First();
407 meshLeftPolygonOf( Abs( anEdgeIdx ), ( anEdgeIdx > 0 ) );
410 aLoopEdges.RemoveFirst();
414 //=======================================================================
415 //function : createTrianglesOnNewVertices
416 //purpose : Creation of triangles from the new nodes
417 //=======================================================================
418 void BRepMesh_Delaun::createTrianglesOnNewVertices(
419 BRepMesh::Array1OfInteger& theVertexIndexes)
421 BRepMesh::MapOfIntegerInteger aLoopEdges( 10, myMeshData->Allocator() );
423 // Insertion of nodes :
424 Standard_Boolean isModify = Standard_True;
426 Standard_Integer anIndex = theVertexIndexes.Lower();
427 Standard_Integer anUpper = theVertexIndexes.Upper();
428 for( ; anIndex <= anUpper; ++anIndex )
432 Standard_Integer aVertexIdx = theVertexIndexes( anIndex );
433 const BRepMesh_Vertex& aVertex = GetVertex( aVertexIdx );
435 // Iterator in the list of indexes of circles containing the node
436 BRepMesh::ListOfInteger& aCirclesList = myCircles.Select( aVertex.Coord() );
438 Standard_Integer onEgdeId = 0, aTriangleId = 0;
439 BRepMesh::ListOfInteger::Iterator aCircleIt( aCirclesList );
440 for ( ; aCircleIt.More(); aCircleIt.Next() )
442 // To add a node in the mesh it is necessary to check conditions:
443 // - the node should be within the boundaries of the mesh and so in an existing triangle
444 // - all adjacent triangles should belong to a component connected with this triangle
445 if ( Contains( aCircleIt.Value(), aVertex, onEgdeId ) )
449 aTriangleId = aCircleIt.Value();
450 aCirclesList.Remove( aCircleIt );
453 else if ( GetEdge( onEgdeId ).Movability() == BRepMesh_Free )
455 aTriangleId = aCircleIt.Value();
456 aCirclesList.Remove( aCircleIt );
462 if ( aTriangleId > 0 )
464 deleteTriangle( aTriangleId, aLoopEdges );
466 isModify = Standard_True;
467 while ( isModify && !aCirclesList.IsEmpty() )
469 isModify = Standard_False;
470 BRepMesh::ListOfInteger::Iterator aCircleIt1( aCirclesList );
471 for ( ; aCircleIt1.More(); aCircleIt1.Next() )
473 Standard_Integer e[3];
474 Standard_Boolean o[3];
475 GetTriangle( aCircleIt1.Value() ).Edges( e, o );
477 if ( aLoopEdges.IsBound( e[0] ) ||
478 aLoopEdges.IsBound( e[1] ) ||
479 aLoopEdges.IsBound( e[2] ) )
481 isModify = Standard_True;
482 deleteTriangle( aCircleIt1.Value(), aLoopEdges );
483 aCirclesList.Remove( aCircleIt1 );
489 // Creation of triangles with the current node and free edges
490 // and removal of these edges from the list of free edges
491 createTriangles( aVertexIdx, aLoopEdges );
494 // Check that internal edges are not crossed by triangles
495 BRepMesh::HMapOfInteger anInternalEdges = InternalEdges();
497 // Destruction of triancles intersecting internal edges
498 // and their replacement by makeshift triangles
499 BRepMesh::MapOfInteger::Iterator anInernalEdgesIt( *anInternalEdges );
500 for ( ; anInernalEdgesIt.More(); anInernalEdgesIt.Next() )
502 Standard_Integer aNbC;
503 aNbC = myMeshData->ElementsConnectedTo( anInernalEdgesIt.Key() ).Extent();
506 meshLeftPolygonOf( anInernalEdgesIt.Key(), Standard_True );
507 meshLeftPolygonOf( anInernalEdgesIt.Key(), Standard_False );
511 // Adjustment of meshes to boundary edges
515 //=======================================================================
516 //function : isBoundToFrontier
517 //purpose : Goes through the neighbour triangles around the given node
518 // started from the given link, returns TRUE if some triangle
519 // has a bounding frontier edge or FALSE elsewhere.
520 // Stop link is used to prevent cycles.
521 // Previous element Id is used to identify next neighbor element.
522 //=======================================================================
523 Standard_Boolean BRepMesh_Delaun::isBoundToFrontier(
524 const Standard_Integer theRefNodeId,
525 const Standard_Integer theRefLinkId,
526 const Standard_Integer theStopLinkId,
527 const Standard_Integer thePrevElementId)
529 const BRepMesh_PairOfIndex& aPair =
530 myMeshData->ElementsConnectedTo( theRefLinkId );
531 if ( aPair.IsEmpty() )
532 return Standard_False;
534 Standard_Integer aNbElements = aPair.Extent();
535 for ( Standard_Integer anElemIt = 1; anElemIt <= aNbElements; ++anElemIt )
537 const Standard_Integer aTriId = aPair.Index(anElemIt);
538 if ( aTriId < 0 || aTriId == thePrevElementId )
541 Standard_Integer anEdges[3];
542 Standard_Boolean anEdgesOri[3];
543 GetTriangle( aTriId ).Edges( anEdges, anEdgesOri );
545 for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
547 const Standard_Integer anEdgeId = anEdges[anEdgeIt];
548 if ( anEdgeId == theRefLinkId )
551 if ( anEdgeId == theStopLinkId )
552 return Standard_False;
554 const BRepMesh_Edge& anEdge = GetEdge( anEdgeId );
555 if ( anEdge.FirstNode() != theRefNodeId &&
556 anEdge.LastNode() != theRefNodeId )
561 if ( anEdge.Movability() != BRepMesh_Free )
562 return Standard_True;
564 return isBoundToFrontier( theRefNodeId, anEdgeId, theStopLinkId, aTriId );
568 return Standard_False;
571 //=======================================================================
572 //function : cleanupMesh
573 //purpose : Cleanup mesh from the free triangles
574 //=======================================================================
575 void BRepMesh_Delaun::cleanupMesh()
579 BRepMesh::MapOfIntegerInteger aLoopEdges( 10, myMeshData->Allocator() );
580 BRepMesh::MapOfInteger aDelTriangles;
582 BRepMesh::HMapOfInteger aFreeEdges = FreeEdges();
583 BRepMesh::MapOfInteger::Iterator aFreeEdgesIt( *aFreeEdges );
584 for ( ; aFreeEdgesIt.More(); aFreeEdgesIt.Next() )
586 const Standard_Integer& aFreeEdgeId = aFreeEdgesIt.Key();
587 const BRepMesh_Edge& anEdge = GetEdge( aFreeEdgeId );
588 if ( anEdge.Movability() == BRepMesh_Frontier )
591 const BRepMesh_PairOfIndex& aPair =
592 myMeshData->ElementsConnectedTo( aFreeEdgeId );
593 if ( aPair.IsEmpty() )
595 aLoopEdges.Bind( aFreeEdgeId, Standard_True );
599 Standard_Integer aTriId = aPair.FirstIndex();
601 // Check that the connected triangle is not surrounded by another triangles
602 Standard_Integer anEdges[3];
603 Standard_Boolean anEdgesOri[3];
604 GetTriangle( aTriId ).Edges( anEdges, anEdgesOri );
606 Standard_Boolean isCanNotBeRemoved = Standard_True;
607 for ( Standard_Integer aCurEdgeIdx = 0; aCurEdgeIdx < 3; ++aCurEdgeIdx )
609 if ( anEdges[aCurEdgeIdx] != aFreeEdgeId )
612 for ( Standard_Integer anOtherEdgeIt = 1; anOtherEdgeIt <= 2; ++anOtherEdgeIt )
614 Standard_Integer anOtherEdgeId = ( aCurEdgeIdx + anOtherEdgeIt ) % 3;
615 const BRepMesh_PairOfIndex& anOtherEdgePair =
616 myMeshData->ElementsConnectedTo( anEdges[anOtherEdgeId] );
618 if ( anOtherEdgePair.Extent() < 2 )
620 isCanNotBeRemoved = Standard_False;
628 if ( isCanNotBeRemoved )
631 Standard_Boolean isConnected[2] = { Standard_False, Standard_False };
632 for ( Standard_Integer aLinkNodeIt = 0; aLinkNodeIt < 2; ++aLinkNodeIt )
634 isConnected[aLinkNodeIt] = isBoundToFrontier( ( aLinkNodeIt == 0 ) ?
635 anEdge.FirstNode() : anEdge.LastNode(),
636 aFreeEdgeId, aFreeEdgeId, -1);
639 if ( !isConnected[0] || !isConnected[1] )
640 aDelTriangles.Add( aTriId );
643 // Destruction of triangles :
644 Standard_Integer aDeletedTrianglesNb = 0;
645 BRepMesh::MapOfInteger::Iterator aDelTrianglesIt( aDelTriangles );
646 for ( ; aDelTrianglesIt.More(); aDelTrianglesIt.Next() )
648 deleteTriangle( aDelTrianglesIt.Key(), aLoopEdges );
649 aDeletedTrianglesNb++;
652 // Destruction of remaining hanging edges
653 BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
654 for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
656 if ( myMeshData->ElementsConnectedTo( aLoopEdgesIt.Key() ).IsEmpty() )
657 myMeshData->RemoveLink( aLoopEdgesIt.Key() );
660 if ( aDeletedTrianglesNb == 0 )
665 //=======================================================================
666 //function : frontierAdjust
667 //purpose : Adjust the mesh on the frontier
668 //=======================================================================
669 void BRepMesh_Delaun::frontierAdjust()
671 BRepMesh::HMapOfInteger aFrontier = Frontier();
672 BRepMesh::VectorOfInteger aFailedFrontiers;
673 BRepMesh::MapOfIntegerInteger aLoopEdges( 10, myMeshData->Allocator() );
674 BRepMesh::HMapOfInteger aIntFrontierEdges = new BRepMesh::MapOfInteger;
675 for ( Standard_Integer aPass = 1; aPass <= 2; ++aPass )
677 // 1 pass): find external triangles on boundary edges;
678 // 2 pass): find external triangles on boundary edges appeared
679 // during triangles replacement.
681 BRepMesh::MapOfInteger::Iterator aFrontierIt( *aFrontier );
682 for ( ; aFrontierIt.More(); aFrontierIt.Next() )
684 Standard_Integer aFrontierId = aFrontierIt.Key();
685 const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo( aFrontierId );
686 Standard_Integer aNbElem = aPair.Extent();
687 for( Standard_Integer aElemIt = 1; aElemIt <= aNbElem; ++aElemIt )
689 const Standard_Integer aPriorElemId = aPair.Index( aElemIt );
690 if( aPriorElemId < 0 )
693 Standard_Integer e[3];
694 Standard_Boolean o[3];
695 GetTriangle( aPriorElemId ).Edges( e, o );
697 Standard_Boolean isTriangleFound = Standard_False;
698 for ( Standard_Integer n = 0; n < 3; ++n )
700 if ( aFrontierId == e[n] && !o[n] )
702 // Destruction of external triangles on boundary edges
703 isTriangleFound = Standard_True;
704 deleteTriangle( aPriorElemId, aLoopEdges );
709 if ( isTriangleFound )
714 // destrucrion of remaining hanging edges :
715 BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
716 for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
718 Standard_Integer aLoopEdgeId = aLoopEdgesIt.Key();
719 if (myMeshData->ElementsConnectedTo( aLoopEdgeId ).IsEmpty() )
720 myMeshData->RemoveLink( aLoopEdgeId );
723 // destruction of triangles crossing the boundary edges and
724 // their replacement by makeshift triangles
725 for ( aFrontierIt.Reset(); aFrontierIt.More(); aFrontierIt.Next() )
727 Standard_Integer aFrontierId = aFrontierIt.Key();
728 if ( !myMeshData->ElementsConnectedTo( aFrontierId ).IsEmpty() )
731 Standard_Boolean isSuccess =
732 meshLeftPolygonOf( aFrontierId, Standard_True, aIntFrontierEdges );
734 if ( aPass == 2 && !isSuccess )
735 aFailedFrontiers.Append( aFrontierId );
741 // When the mesh has been cleaned up, try to process frontier edges
742 // once again to fill the possible gaps that might be occured in case of "saw" -
743 // situation when frontier edge has a triangle at a right side, but its free
744 // links cross another frontieres and meshLeftPolygonOf itself can't collect
746 BRepMesh::VectorOfInteger::Iterator aFailedFrontiersIt( aFailedFrontiers );
747 for ( ; aFailedFrontiersIt.More(); aFailedFrontiersIt.Next() )
749 Standard_Integer aFrontierId = aFailedFrontiersIt.Value();
750 if ( !myMeshData->ElementsConnectedTo( aFrontierId ).IsEmpty() )
753 meshLeftPolygonOf( aFrontierId, Standard_True, aIntFrontierEdges );
757 //=======================================================================
758 //function : fillBndBox
759 //purpose : Add boundig box for edge defined by start & end point to
760 // the given vector of bounding boxes for triangulation edges
761 //=======================================================================
762 void BRepMesh_Delaun::fillBndBox(BRepMesh::SequenceOfBndB2d& theBoxes,
763 const BRepMesh_Vertex& theV1,
764 const BRepMesh_Vertex& theV2)
767 aBox.Add( theV1.Coord() );
768 aBox.Add( theV2.Coord() );
769 theBoxes.Append( aBox );
772 //=======================================================================
773 //function : meshLeftPolygonOf
774 //purpose : Collect the polygon at the left of the given edge (material side)
775 //=======================================================================
776 Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf(
777 const Standard_Integer theStartEdgeId,
778 const Standard_Boolean isForward,
779 BRepMesh::HMapOfInteger theSkipped )
781 if ( !theSkipped.IsNull() && theSkipped->Contains( theStartEdgeId ) )
782 return Standard_True;
784 const BRepMesh_Edge& aRefEdge = GetEdge( theStartEdgeId );
786 BRepMesh::SequenceOfInteger aPolygon;
787 Standard_Integer aStartNode, aPivotNode;
790 aPolygon.Append( theStartEdgeId );
791 aStartNode = aRefEdge.FirstNode();
792 aPivotNode = aRefEdge.LastNode();
796 aPolygon.Append( -theStartEdgeId );
797 aStartNode = aRefEdge.LastNode();
798 aPivotNode = aRefEdge.FirstNode();
802 const BRepMesh_Vertex& aStartEdgeVertexS = GetVertex( aStartNode );
803 BRepMesh_Vertex aPivotVertex = GetVertex( aPivotNode );
805 gp_Vec2d aRefLinkDir( aPivotVertex.Coord() -
806 aStartEdgeVertexS.Coord() );
808 if ( aRefLinkDir.SquareMagnitude() < Precision2 )
809 return Standard_True;
811 // Auxilary structures.
812 // Bounding boxes of polygon links to be used for preliminary
813 // analysis of intersections
814 BRepMesh::SequenceOfBndB2d aBoxes;
815 fillBndBox( aBoxes, aStartEdgeVertexS, aPivotVertex );
818 BRepMesh::MapOfInteger aDeadLinks;
820 // Links are temporarily excluded from consideration
821 BRepMesh::MapOfInteger aLeprousLinks;
822 aLeprousLinks.Add( theStartEdgeId );
824 Standard_Boolean isSkipLeprous = Standard_True;
825 Standard_Integer aFirstNode = aStartNode;
826 while ( aPivotNode != aFirstNode )
828 Bnd_B2d aNextLinkBndBox;
829 gp_Vec2d aNextLinkDir;
830 Standard_Integer aNextPivotNode = 0;
832 Standard_Integer aNextLinkId = findNextPolygonLink(
834 aPivotNode, aPivotVertex, aRefLinkDir,
835 aBoxes, aPolygon, theSkipped,
836 isSkipLeprous, aLeprousLinks, aDeadLinks,
837 aNextPivotNode, aNextLinkDir, aNextLinkBndBox );
839 if ( aNextLinkId != 0 )
841 aStartNode = aPivotNode;
842 aRefLinkDir = aNextLinkDir;
844 aPivotNode = aNextPivotNode;
845 aPivotVertex = GetVertex( aNextPivotNode );
847 aBoxes.Append ( aNextLinkBndBox );
848 aPolygon.Append( aNextLinkId );
850 isSkipLeprous = Standard_True;
855 if ( aPolygon.Length() == 1 )
856 return Standard_False;
858 // Return to the previous point
859 Standard_Integer aDeadLinkId = Abs( aPolygon.Last() );
860 aDeadLinks.Add ( aDeadLinkId );
862 aLeprousLinks.Remove( aDeadLinkId );
863 aPolygon.Remove ( aPolygon.Length() );
864 aBoxes.Remove ( aBoxes.Length() );
866 Standard_Integer aPrevLinkInfo = aPolygon.Last();
867 const BRepMesh_Edge& aPrevLink = GetEdge( Abs( aPrevLinkInfo ) );
869 if( aPrevLinkInfo > 0 )
871 aStartNode = aPrevLink.FirstNode();
872 aPivotNode = aPrevLink.LastNode();
876 aStartNode = aPrevLink.LastNode();
877 aPivotNode = aPrevLink.FirstNode();
880 aPivotVertex = GetVertex( aPivotNode );
882 aPivotVertex.Coord() - GetVertex( aStartNode ).Coord();
884 isSkipLeprous = Standard_False;
888 if ( aPolygon.Length() < 3 )
889 return Standard_False;
891 cleanupPolygon( aPolygon, aBoxes );
892 meshPolygon ( aPolygon, aBoxes, theSkipped );
894 return Standard_True;
897 //=======================================================================
898 //function : findNextPolygonLink
899 //purpose : Find next link starting from the given node and has maximum
900 // angle respect the given reference link.
901 // Each time the next link is found other neighbor links at the
902 // pivot node are marked as leprous and will be excluded from
903 // consideration next time until a hanging end is occured.
904 //=======================================================================
905 Standard_Integer BRepMesh_Delaun::findNextPolygonLink(
906 const Standard_Integer& theFirstNode,
907 const Standard_Integer& thePivotNode,
908 const BRepMesh_Vertex& thePivotVertex,
909 const gp_Vec2d& theRefLinkDir,
910 const BRepMesh::SequenceOfBndB2d& theBoxes,
911 const BRepMesh::SequenceOfInteger& thePolygon,
912 const BRepMesh::HMapOfInteger theSkipped,
913 const Standard_Boolean& isSkipLeprous,
914 BRepMesh::MapOfInteger& theLeprousLinks,
915 BRepMesh::MapOfInteger& theDeadLinks,
916 Standard_Integer& theNextPivotNode,
917 gp_Vec2d& theNextLinkDir,
918 Bnd_B2d& theNextLinkBndBox )
920 // Find the next link having the greatest angle
921 // respect to a direction of a reference one
922 Standard_Real aMaxAngle = RealFirst();
924 Standard_Integer aNextLinkId = 0;
925 BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) );
926 for ( ; aLinkIt.More(); aLinkIt.Next() )
928 const Standard_Integer& aNeighbourLinkInfo = aLinkIt.Value();
929 Standard_Integer aNeighbourLinkId = Abs( aNeighbourLinkInfo );
931 if ( theDeadLinks.Contains( aNeighbourLinkId ) ||
932 ( !theSkipped.IsNull() && theSkipped->Contains( aNeighbourLinkId ) ) )
937 Standard_Boolean isLeprous = theLeprousLinks.Contains( aNeighbourLinkId );
938 if ( isSkipLeprous && isLeprous )
941 const BRepMesh_Edge& aNeighbourLink = GetEdge( aNeighbourLinkId );
943 // Determine whether the link belongs to the mesh
944 if ( aNeighbourLink.Movability() == BRepMesh_Free &&
945 myMeshData->ElementsConnectedTo( aNeighbourLinkInfo ).IsEmpty() )
947 theDeadLinks.Add( aNeighbourLinkId );
951 Standard_Integer anOtherNode = aNeighbourLink.FirstNode();
952 if ( anOtherNode == thePivotNode )
953 anOtherNode = aNeighbourLink.LastNode();
955 gp_Vec2d aCurLinkDir( GetVertex( anOtherNode ).Coord() -
956 thePivotVertex.Coord() );
958 if ( aCurLinkDir.SquareMagnitude() < Precision2 )
960 theDeadLinks.Add( aNeighbourLinkId );
965 theLeprousLinks.Add( aNeighbourLinkId );
967 Standard_Real anAngle = theRefLinkDir.Angle( aCurLinkDir );
968 Standard_Boolean isFrontier =
969 ( aNeighbourLink.Movability() == BRepMesh_Frontier );
971 Standard_Boolean isCheckPointOnEdge = Standard_True;
974 if ( Abs( Abs(anAngle) - M_PI ) < Precision::Angular() )
976 // Glued constrains - don't check intersection
977 isCheckPointOnEdge = Standard_False;
978 anAngle = Abs( anAngle );
982 if (anAngle <= aMaxAngle)
985 Standard_Boolean isCheckEndPoints = ( anOtherNode != theFirstNode );
988 Standard_Boolean isNotIntersect =
989 checkIntersection( aNeighbourLink, thePolygon, theBoxes,
990 isCheckEndPoints, isCheckPointOnEdge, Standard_True, aBox );
996 theNextLinkDir = aCurLinkDir;
997 theNextPivotNode = anOtherNode;
998 theNextLinkBndBox = aBox;
1000 aNextLinkId = ( aNeighbourLink.FirstNode() == thePivotNode ) ?
1001 aNeighbourLinkId : -aNeighbourLinkId;
1008 //=======================================================================
1009 //function : checkIntersection
1010 //purpose : Check is the given link intersects the polygon boundaries.
1011 // Returns bounding box for the given link trough the
1012 // <theLinkBndBox> parameter.
1013 //=======================================================================
1014 Standard_Boolean BRepMesh_Delaun::checkIntersection(
1015 const BRepMesh_Edge& theLink,
1016 const BRepMesh::SequenceOfInteger& thePolygon,
1017 const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
1018 const Standard_Boolean isConsiderEndPointTouch,
1019 const Standard_Boolean isConsiderPointOnEdge,
1020 const Standard_Boolean isSkipLastEdge,
1021 Bnd_B2d& theLinkBndBox ) const
1023 theLinkBndBox.Add( GetVertex( theLink.FirstNode() ).Coord() );
1024 theLinkBndBox.Add( GetVertex( theLink.LastNode() ).Coord() );
1026 Standard_Integer aPolyLen = thePolygon.Length();
1027 // Don't check intersection with the last link
1028 if ( isSkipLastEdge )
1031 Standard_Boolean isFrontier =
1032 ( theLink.Movability() == BRepMesh_Frontier );
1034 for ( Standard_Integer aPolyIt = 1; aPolyIt <= aPolyLen; ++aPolyIt )
1036 if ( !theLinkBndBox.IsOut( thePolyBoxes.Value( aPolyIt ) ) )
1038 // intersection is possible...
1039 Standard_Integer aPolyLinkId = Abs( thePolygon( aPolyIt ) );
1040 const BRepMesh_Edge& aPolyLink = GetEdge( aPolyLinkId );
1042 // skip intersections between frontier edges
1043 if ( aPolyLink.Movability() == BRepMesh_Frontier && isFrontier )
1047 BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( theLink, aPolyLink,
1048 isConsiderEndPointTouch, isConsiderPointOnEdge, anIntPnt );
1050 if ( aIntFlag != BRepMesh_GeomTool::NoIntersection )
1051 return Standard_False;
1055 // Ok, no intersection
1056 return Standard_True;
1059 //=======================================================================
1060 //function : addTriangle
1061 //purpose : Add a triangle based on the given oriented edges into mesh
1062 //=======================================================================
1063 inline void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3],
1064 const Standard_Boolean (&theEdgesOri)[3],
1065 const Standard_Integer (&theNodesId)[3] )
1067 Standard_Integer aNewTriangleId =
1068 myMeshData->AddElement(BRepMesh_Triangle(theEdgesId,
1069 theEdgesOri, BRepMesh_Free));
1071 Standard_Boolean isAdded = myCircles.Bind(
1073 GetVertex( theNodesId[0] ).Coord(),
1074 GetVertex( theNodesId[1] ).Coord(),
1075 GetVertex( theNodesId[2] ).Coord() );
1078 myMeshData->RemoveElement( aNewTriangleId );
1081 //=======================================================================
1082 //function : cleanupPolygon
1083 //purpose : Remove internal triangles from the given polygon
1084 //=======================================================================
1085 void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolygon,
1086 const BRepMesh::SequenceOfBndB2d& thePolyBoxes )
1088 Standard_Integer aPolyLen = thePolygon.Length();
1092 BRepMesh::MapOfIntegerInteger aLoopEdges( 10, myMeshData->Allocator() );
1093 BRepMesh::MapOfInteger anIgnoredEdges;
1094 BRepMesh::MapOfInteger aPolyVerticesFindMap;
1095 BRepMesh::VectorOfInteger aPolyVertices;
1096 // Collect boundary vertices of the polygon
1097 for ( Standard_Integer aPolyIt = 1; aPolyIt <= aPolyLen; ++aPolyIt )
1099 Standard_Integer aPolyEdgeInfo = thePolygon( aPolyIt );
1100 Standard_Integer aPolyEdgeId = Abs( aPolyEdgeInfo );
1101 anIgnoredEdges.Add( aPolyEdgeId );
1103 Standard_Boolean isForward = ( aPolyEdgeInfo > 0 );
1104 const BRepMesh_PairOfIndex& aPair =
1105 myMeshData->ElementsConnectedTo( aPolyEdgeId );
1107 Standard_Integer anElemIt = 1;
1108 for ( ; anElemIt <= aPair.Extent(); ++anElemIt )
1110 Standard_Integer anElemId = aPair.Index( anElemIt );
1114 Standard_Integer anEdges[3];
1115 Standard_Boolean anEdgesOri[3];
1116 GetTriangle( anElemId ).Edges(anEdges, anEdgesOri);
1118 Standard_Integer isTriangleFound = Standard_False;
1119 for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
1121 if ( anEdges[anEdgeIt] == aPolyEdgeId &&
1122 anEdgesOri[anEdgeIt] == isForward )
1124 isTriangleFound = Standard_True;
1125 deleteTriangle( anElemId, aLoopEdges );
1130 if ( isTriangleFound )
1134 // Skip a neighbor link to extract unique vertices each time
1137 const BRepMesh_Edge& aPolyEdge = GetEdge( aPolyEdgeId );
1138 Standard_Integer aFirstVertex = aPolyEdge.FirstNode();
1139 Standard_Integer aLastVertex = aPolyEdge.LastNode();
1141 aPolyVerticesFindMap.Add( aFirstVertex );
1142 aPolyVerticesFindMap.Add( aLastVertex );
1144 if ( aPolyEdgeInfo > 0 )
1146 aPolyVertices.Append( aFirstVertex );
1147 aPolyVertices.Append( aLastVertex );
1151 aPolyVertices.Append( aLastVertex );
1152 aPolyVertices.Append( aFirstVertex );
1157 // Make closed sequence
1158 if ( aPolyVertices.First() != aPolyVertices.Last() )
1159 aPolyVertices.Append( aPolyVertices.First() );
1161 BRepMesh::MapOfInteger aSurvivedLinks( anIgnoredEdges );
1163 Standard_Integer aPolyVertIt = 0;
1164 Standard_Integer anUniqueVerticesNum = aPolyVertices.Length() - 1;
1165 for ( ; aPolyVertIt < anUniqueVerticesNum; ++aPolyVertIt )
1167 killTrianglesAroundVertex( aPolyVertices( aPolyVertIt ),
1168 aPolyVertices, aPolyVerticesFindMap, thePolygon,
1169 thePolyBoxes, aSurvivedLinks, aLoopEdges );
1172 BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
1173 for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
1175 const Standard_Integer& aLoopEdgeId = aLoopEdgesIt.Key();
1176 if ( anIgnoredEdges.Contains( aLoopEdgeId ) )
1179 if ( myMeshData->ElementsConnectedTo( aLoopEdgeId ).IsEmpty() )
1180 myMeshData->RemoveLink( aLoopEdgesIt.Key() );
1184 //=======================================================================
1185 //function : killTrianglesAroundVertex
1186 //purpose : Remove all triangles and edges that are placed
1187 // inside the polygon or crossed it.
1188 //=======================================================================
1189 void BRepMesh_Delaun::killTrianglesAroundVertex(
1190 const Standard_Integer theZombieNodeId,
1191 const BRepMesh::VectorOfInteger& thePolyVertices,
1192 const BRepMesh::MapOfInteger& thePolyVerticesFindMap,
1193 const BRepMesh::SequenceOfInteger& thePolygon,
1194 const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
1195 BRepMesh::MapOfInteger& theSurvivedLinks,
1196 BRepMesh::MapOfIntegerInteger& theLoopEdges )
1198 BRepMesh::ListOfInteger::Iterator aNeighborsIt =
1199 myMeshData->LinksConnectedTo( theZombieNodeId );
1201 // Try to infect neighbor nodes
1202 BRepMesh::VectorOfInteger aVictimNodes;
1203 for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
1205 const Standard_Integer& aNeighborLinkId = aNeighborsIt.Value();
1206 if ( theSurvivedLinks.Contains( aNeighborLinkId ) )
1209 const BRepMesh_Edge& aNeighborLink = GetEdge( aNeighborLinkId );
1210 if ( aNeighborLink.Movability() == BRepMesh_Frontier )
1212 // Though, if it lies onto the polygon boundary -
1213 // take its triangles
1215 Standard_Boolean isNotIntersect =
1216 checkIntersection( aNeighborLink, thePolygon,
1217 thePolyBoxes, Standard_False, Standard_True,
1218 Standard_False, aBox );
1220 if ( isNotIntersect )
1223 theSurvivedLinks.Add( aNeighborLinkId );
1229 Standard_Integer anOtherNode = aNeighborLink.FirstNode();
1230 if ( anOtherNode == theZombieNodeId )
1231 anOtherNode = aNeighborLink.LastNode();
1233 // Possible sacrifice
1234 if ( !thePolyVerticesFindMap.Contains( anOtherNode ) )
1236 if ( isVertexInsidePolygon( anOtherNode, thePolyVertices ) )
1239 aVictimNodes.Append( anOtherNode );
1243 // Lucky. But it may intersect the polygon boundary.
1245 killTrianglesOnIntersectingLinks( aNeighborLinkId,
1246 aNeighborLink, anOtherNode, thePolygon,
1247 thePolyBoxes, theSurvivedLinks, theLoopEdges );
1254 // Add link to the survivers to avoid cycling
1255 theSurvivedLinks.Add( aNeighborLinkId );
1256 killLinkTriangles( aNeighborLinkId, theLoopEdges );
1259 // Go and do your job!
1260 BRepMesh::VectorOfInteger::Iterator aVictimIt( aVictimNodes );
1261 for ( ; aVictimIt.More(); aVictimIt.Next() )
1263 killTrianglesAroundVertex( aVictimIt.Value(), thePolyVertices,
1264 thePolyVerticesFindMap, thePolygon, thePolyBoxes,
1265 theSurvivedLinks, theLoopEdges );
1269 //=======================================================================
1270 //function : isVertexInsidePolygon
1271 //purpose : Checks is the given vertex lies inside the polygon
1272 //=======================================================================
1273 Standard_Boolean BRepMesh_Delaun::isVertexInsidePolygon(
1274 const Standard_Integer& theVertexId,
1275 const BRepMesh::VectorOfInteger& thePolygonVertices ) const
1277 Standard_Integer aPolyLen = thePolygonVertices.Length();
1279 return Standard_False;
1282 const gp_XY aCenterPointXY = GetVertex( theVertexId ).Coord();
1284 const BRepMesh_Vertex& aFirstVertex = GetVertex( thePolygonVertices( 0 ) );
1285 gp_Vec2d aPrevVertexDir( aFirstVertex.Coord() - aCenterPointXY );
1286 if ( aPrevVertexDir.SquareMagnitude() < Precision2 )
1287 return Standard_True;
1289 Standard_Real aTotalAng = 0.0;
1290 for ( Standard_Integer aPolyIt = 1; aPolyIt < aPolyLen; ++aPolyIt )
1292 const BRepMesh_Vertex& aPolyVertex = GetVertex( thePolygonVertices( aPolyIt ) );
1294 gp_Vec2d aCurVertexDir( aPolyVertex.Coord() - aCenterPointXY );
1295 if ( aCurVertexDir.SquareMagnitude() < Precision2 )
1296 return Standard_True;
1298 aTotalAng += aCurVertexDir.Angle( aPrevVertexDir );
1299 aPrevVertexDir = aCurVertexDir;
1302 if ( Abs( Angle2PI - aTotalAng ) > Precision::Angular() )
1303 return Standard_False;
1305 return Standard_True;
1308 //=======================================================================
1309 //function : killTrianglesOnIntersectingLinks
1310 //purpose : Checks is the given link crosses the polygon boundary.
1311 // If yes, kills its triangles and checks neighbor links on
1312 // boundary intersection. Does nothing elsewhere.
1313 //=======================================================================
1314 void BRepMesh_Delaun::killTrianglesOnIntersectingLinks(
1315 const Standard_Integer& theLinkToCheckId,
1316 const BRepMesh_Edge& theLinkToCheck,
1317 const Standard_Integer& theEndPoint,
1318 const BRepMesh::SequenceOfInteger& thePolygon,
1319 const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
1320 BRepMesh::MapOfInteger& theSurvivedLinks,
1321 BRepMesh::MapOfIntegerInteger& theLoopEdges )
1323 if ( theSurvivedLinks.Contains( theLinkToCheckId ) )
1327 Standard_Boolean isNotIntersect =
1328 checkIntersection( theLinkToCheck, thePolygon,
1329 thePolyBoxes, Standard_False, Standard_False,
1330 Standard_False, aBox );
1332 theSurvivedLinks.Add( theLinkToCheckId );
1334 if ( isNotIntersect )
1337 killLinkTriangles( theLinkToCheckId, theLoopEdges );
1339 BRepMesh::ListOfInteger::Iterator aNeighborsIt =
1340 myMeshData->LinksConnectedTo( theEndPoint );
1342 for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
1344 const Standard_Integer& aNeighborLinkId = aNeighborsIt.Value();
1345 const BRepMesh_Edge& aNeighborLink = GetEdge( aNeighborLinkId );
1346 Standard_Integer anOtherNode = aNeighborLink.FirstNode();
1347 if ( anOtherNode == theEndPoint )
1348 anOtherNode = aNeighborLink.LastNode();
1350 killTrianglesOnIntersectingLinks( aNeighborLinkId,
1351 aNeighborLink, anOtherNode, thePolygon,
1352 thePolyBoxes, theSurvivedLinks, theLoopEdges );
1356 //=======================================================================
1357 //function : killLinkTriangles
1358 //purpose : Kill triangles bound to the given link.
1359 //=======================================================================
1360 void BRepMesh_Delaun::killLinkTriangles(
1361 const Standard_Integer& theLinkId,
1362 BRepMesh::MapOfIntegerInteger& theLoopEdges )
1364 const BRepMesh_PairOfIndex& aPair =
1365 myMeshData->ElementsConnectedTo( theLinkId );
1367 Standard_Integer anElemNb = aPair.Extent();
1368 for ( Standard_Integer aPairIt = 1; aPairIt <= anElemNb; ++aPairIt )
1370 Standard_Integer anElemId = aPair.FirstIndex();
1374 deleteTriangle( anElemId, theLoopEdges );
1378 //=======================================================================
1379 //function : getOrientedNodes
1380 //purpose : Returns start and end nodes of the given edge in respect to
1382 //=======================================================================
1383 void BRepMesh_Delaun::getOrientedNodes(const BRepMesh_Edge& theEdge,
1384 const Standard_Boolean isForward,
1385 Standard_Integer *theNodes) const
1389 theNodes[0] = theEdge.FirstNode();
1390 theNodes[1] = theEdge.LastNode();
1394 theNodes[0] = theEdge.LastNode();
1395 theNodes[1] = theEdge.FirstNode();
1399 //=======================================================================
1400 //function : processLoop
1401 //purpose : Processes loop within the given polygon formed by range of
1402 // its links specified by start and end link indices.
1403 //=======================================================================
1404 void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom,
1405 const Standard_Integer theLinkTo,
1406 const BRepMesh::SequenceOfInteger& thePolygon,
1407 const BRepMesh::SequenceOfBndB2d& thePolyBoxes)
1409 Standard_Integer aNbOfLinksInLoop = theLinkTo - theLinkFrom - 1;
1410 if ( aNbOfLinksInLoop < 3 )
1413 BRepMesh::SequenceOfInteger aPolygon;
1414 BRepMesh::SequenceOfBndB2d aPolyBoxes;
1415 for ( ; aNbOfLinksInLoop > 0; --aNbOfLinksInLoop )
1417 Standard_Integer aLoopLinkIndex = theLinkFrom + aNbOfLinksInLoop;
1418 aPolygon .Prepend( thePolygon ( aLoopLinkIndex ) );
1419 aPolyBoxes.Prepend( thePolyBoxes( aLoopLinkIndex ) );
1421 meshPolygon( aPolygon, aPolyBoxes );
1424 //=======================================================================
1425 //function : createAndReplacePolygonLink
1426 //purpose : Creates new link based on the given nodes and updates the
1428 //=======================================================================
1429 Standard_Integer BRepMesh_Delaun::createAndReplacePolygonLink(
1430 const Standard_Integer *theNodes,
1431 const gp_Pnt2d *thePnts,
1432 const Standard_Integer theRootIndex,
1433 const ReplaceFlag theReplaceFlag,
1434 BRepMesh::SequenceOfInteger& thePolygon,
1435 BRepMesh::SequenceOfBndB2d& thePolyBoxes )
1437 Standard_Integer aNewEdgeId =
1438 myMeshData->AddLink( BRepMesh_Edge(
1439 theNodes[0], theNodes[1], BRepMesh_Free ) );
1442 aNewBox.Add( thePnts[0] );
1443 aNewBox.Add( thePnts[1] );
1445 switch ( theReplaceFlag )
1447 case BRepMesh_Delaun::Replace:
1448 thePolygon .SetValue( theRootIndex, aNewEdgeId );
1449 thePolyBoxes.SetValue( theRootIndex, aNewBox );
1452 case BRepMesh_Delaun::InsertAfter:
1453 thePolygon .InsertAfter( theRootIndex, aNewEdgeId );
1454 thePolyBoxes.InsertAfter( theRootIndex, aNewBox );
1457 case BRepMesh_Delaun::InsertBefore:
1458 thePolygon .InsertBefore( theRootIndex, aNewEdgeId );
1459 thePolyBoxes.InsertBefore( theRootIndex, aNewBox );
1466 //=======================================================================
1467 //function : meshPolygon
1469 //=======================================================================
1470 void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon,
1471 BRepMesh::SequenceOfBndB2d& thePolyBoxes,
1472 BRepMesh::HMapOfInteger theSkipped )
1474 // Check is the source polygon elementary
1475 if ( meshElementaryPolygon( thePolygon ) )
1478 // Check and correct boundary edges
1479 Standard_Integer aPolyLen = thePolygon.Length();
1480 const Standard_Real aPolyArea = Abs( polyArea( thePolygon, 1, aPolyLen ) );
1481 const Standard_Real aSmallLoopArea = 0.001 * aPolyArea;
1482 for ( Standard_Integer aPolyIt = 1; aPolyIt < aPolyLen; ++aPolyIt )
1484 Standard_Integer aCurEdgeInfo = thePolygon( aPolyIt );
1485 Standard_Integer aCurEdgeId = Abs( aCurEdgeInfo );
1486 const BRepMesh_Edge* aCurEdge = &GetEdge( aCurEdgeId );
1487 if ( aCurEdge->Movability() != BRepMesh_Frontier )
1490 Standard_Integer aCurNodes[2];
1491 getOrientedNodes( *aCurEdge, aCurEdgeInfo > 0, aCurNodes );
1493 gp_Pnt2d aCurPnts[2] = {
1494 GetVertex(aCurNodes[0]).Coord(),
1495 GetVertex(aCurNodes[1]).Coord()
1498 gp_Vec2d aCurVec( aCurPnts[0], aCurPnts[1] );
1500 // check further links
1501 Standard_Integer aNextPolyIt = aPolyIt + 1;
1502 for ( ; aNextPolyIt <= aPolyLen; ++aNextPolyIt )
1504 Standard_Integer aNextEdgeInfo = thePolygon( aNextPolyIt );
1505 Standard_Integer aNextEdgeId = Abs( aNextEdgeInfo );
1506 const BRepMesh_Edge* aNextEdge = &GetEdge( aNextEdgeId );
1507 if ( aNextEdge->Movability() != BRepMesh_Frontier )
1510 Standard_Integer aNextNodes[2];
1511 getOrientedNodes( *aNextEdge, aNextEdgeInfo > 0, aNextNodes );
1513 gp_Pnt2d aNextPnts[2] = {
1514 GetVertex(aNextNodes[0]).Coord(),
1515 GetVertex(aNextNodes[1]).Coord()
1519 BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge,
1520 Standard_False, Standard_True, anIntPnt );
1522 if ( aIntFlag == BRepMesh_GeomTool::NoIntersection )
1525 Standard_Boolean isRemoveFromFirst = Standard_False;
1526 Standard_Boolean isAddReplacingEdge = Standard_True;
1527 Standard_Integer aIndexToRemoveTo = aNextPolyIt;
1528 if ( aIntFlag == BRepMesh_GeomTool::Cross )
1530 Standard_Real aLoopArea = polyArea( thePolygon, aPolyIt + 1, aNextPolyIt );
1531 gp_Vec2d aVec1( anIntPnt, aCurPnts [1] );
1532 gp_Vec2d aVec2( anIntPnt, aNextPnts[0] );
1534 aLoopArea += ( aVec1 ^ aVec2 ) / 2.;
1535 if ( Abs( aLoopArea ) > aSmallLoopArea )
1537 aNextNodes[1] = aCurNodes[0];
1538 aNextPnts [1] = aCurPnts [0];
1540 aNextEdgeId = Abs( createAndReplacePolygonLink( aNextNodes, aNextPnts,
1541 aNextPolyIt, BRepMesh_Delaun::Replace, thePolygon, thePolyBoxes ) );
1543 processLoop( aPolyIt, aNextPolyIt, thePolygon, thePolyBoxes );
1547 Standard_Real aDist1 = anIntPnt.SquareDistance(aNextPnts[0]);
1548 Standard_Real aDist2 = anIntPnt.SquareDistance(aNextPnts[1]);
1550 // Choose node with lower distance
1551 const Standard_Boolean isCloseToStart = ( aDist1 < aDist2 );
1552 const Standard_Integer aEndPointIndex = isCloseToStart ? 0 : 1;
1553 aCurNodes[1] = aNextNodes[aEndPointIndex];
1554 aCurPnts [1] = aNextPnts [aEndPointIndex];
1556 if ( isCloseToStart )
1559 // In this context only intersections between frontier edges
1560 // are possible. If intersection between edges of different
1561 // types occured - treat this case as invalid (i.e. result
1562 // might not reflect the expectations).
1563 if ( !theSkipped.IsNull() )
1565 Standard_Integer aSkippedLinkIt = aPolyIt;
1566 for ( ; aSkippedLinkIt <= aIndexToRemoveTo; ++aSkippedLinkIt )
1567 theSkipped->Add( Abs( thePolygon( aSkippedLinkIt ) ) );
1570 else if ( aIntFlag == BRepMesh_GeomTool::PointOnSegment )
1572 // Indentify chopping link
1573 Standard_Boolean isFirstChopping = Standard_False;
1574 Standard_Integer aCheckPointIt = 0;
1575 for ( ; aCheckPointIt < 2; ++aCheckPointIt )
1577 gp_Pnt2d& aRefPoint = aCurPnts[aCheckPointIt];
1578 // Check is second link touches the first one
1579 gp_Vec2d aVec1( aRefPoint, aNextPnts[0] );
1580 gp_Vec2d aVec2( aRefPoint, aNextPnts[1] );
1581 if ( Abs( aVec1 ^ aVec2 ) < Precision )
1583 isFirstChopping = Standard_True;
1588 if ( isFirstChopping )
1590 // Split second link
1591 isAddReplacingEdge = Standard_False;
1592 isRemoveFromFirst = ( aCheckPointIt == 0 );
1594 Standard_Integer aSplitLink[3] = {
1596 aCurNodes [aCheckPointIt],
1600 gp_Pnt2d aSplitPnts[3] = {
1602 aCurPnts [aCheckPointIt],
1606 Standard_Integer aSplitLinkIt = 0;
1607 for ( ; aSplitLinkIt < 2; ++aSplitLinkIt )
1609 createAndReplacePolygonLink( &aSplitLink[aSplitLinkIt],
1610 &aSplitPnts[aSplitLinkIt], aNextPolyIt, ( aSplitLinkIt == 0 ) ?
1611 BRepMesh_Delaun::Replace : BRepMesh_Delaun::InsertAfter,
1612 thePolygon, thePolyBoxes );
1615 processLoop( aPolyIt + aCheckPointIt, aIndexToRemoveTo,
1616 thePolygon, thePolyBoxes );
1621 Standard_Integer aSplitLinkNodes[2] = {
1626 gp_Pnt2d aSplitLinkPnts[2] = {
1630 createAndReplacePolygonLink( aSplitLinkNodes, aSplitLinkPnts,
1631 aPolyIt, BRepMesh_Delaun::InsertAfter, thePolygon, thePolyBoxes );
1633 aCurNodes[1] = aNextNodes[1];
1634 aCurPnts [1] = aNextPnts [1];
1637 processLoop( aPolyIt + 1, aIndexToRemoveTo,
1638 thePolygon, thePolyBoxes );
1641 else if ( aIntFlag == BRepMesh_GeomTool::Glued )
1643 if ( aCurNodes[1] == aNextNodes[0] )
1645 aCurNodes[1] = aNextNodes[1];
1646 aCurPnts [1] = aNextPnts [1];
1648 // TODO: Non-adjacent glued links within the polygon
1650 else if ( aIntFlag == BRepMesh_GeomTool::Same )
1652 processLoop( aPolyIt, aNextPolyIt, thePolygon, thePolyBoxes );
1654 isRemoveFromFirst = Standard_True;
1655 isAddReplacingEdge = Standard_False;
1658 continue; // Not supported type
1660 if ( isAddReplacingEdge )
1662 aCurEdgeId = Abs( createAndReplacePolygonLink( aCurNodes, aCurPnts,
1663 aPolyIt, BRepMesh_Delaun::Replace, thePolygon, thePolyBoxes ) );
1665 aCurEdge = &GetEdge( aCurEdgeId );
1666 aCurVec = gp_Vec2d( aCurPnts[0], aCurPnts[1] );
1669 Standard_Integer aIndexToRemoveFrom =
1670 isRemoveFromFirst ? aPolyIt : aPolyIt + 1;
1672 thePolygon .Remove( aIndexToRemoveFrom, aIndexToRemoveTo );
1673 thePolyBoxes.Remove( aIndexToRemoveFrom, aIndexToRemoveTo );
1675 aPolyLen = thePolygon.Length();
1676 if ( isRemoveFromFirst )
1682 aNextPolyIt = aPolyIt;
1686 meshSimplePolygon( thePolygon, thePolyBoxes );
1689 //=======================================================================
1690 //function : meshElementaryPolygon
1691 //purpose : Triangulation of closed polygon containing only three edges.
1692 //=======================================================================
1693 inline Standard_Boolean BRepMesh_Delaun::meshElementaryPolygon(
1694 const BRepMesh::SequenceOfInteger& thePolygon)
1696 Standard_Integer aPolyLen = thePolygon.Length();
1698 return Standard_True;
1699 else if ( aPolyLen > 3 )
1700 return Standard_False;
1702 // Just create a triangle
1703 Standard_Integer anEdges[3];
1704 Standard_Boolean anEdgesOri[3];
1706 for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
1708 Standard_Integer anEdgeInfo = thePolygon( anEdgeIt + 1 );
1709 anEdges[anEdgeIt] = Abs( anEdgeInfo );
1710 anEdgesOri[anEdgeIt] = ( anEdgeInfo > 0 );
1713 const BRepMesh_Edge& anEdge1 = GetEdge( anEdges[0] );
1714 const BRepMesh_Edge& anEdge2 = GetEdge( anEdges[1] );
1716 Standard_Integer aNodes[3] = { anEdge1.FirstNode(),
1718 anEdge2.FirstNode() };
1719 if ( aNodes[2] == aNodes[0] ||
1720 aNodes[2] == aNodes[1] )
1722 aNodes[2] = anEdge2.LastNode();
1725 addTriangle( anEdges, anEdgesOri, aNodes );
1726 return Standard_True;
1729 //=======================================================================
1730 //function : meshSimplePolygon
1731 //purpose : Triangulatiion of a closed simple polygon (polygon without
1732 // glued edges and loops) described by the list of indexes of
1733 // its edges in the structure.
1734 // (negative index means reversed edge)
1735 //=======================================================================
1736 void BRepMesh_Delaun::meshSimplePolygon(BRepMesh::SequenceOfInteger& thePolygon,
1737 BRepMesh::SequenceOfBndB2d& thePolyBoxes )
1739 // Check is the given polygon elementary
1740 if ( meshElementaryPolygon( thePolygon ) )
1744 // Polygon contains more than 3 links
1745 Standard_Integer aFirstEdgeInfo = thePolygon(1);
1746 const BRepMesh_Edge& aFirstEdge = GetEdge( Abs( aFirstEdgeInfo ) );
1748 Standard_Integer aNodes[3];
1749 getOrientedNodes( aFirstEdge, aFirstEdgeInfo > 0, aNodes );
1751 gp_Pnt2d aRefVertices[3];
1752 aRefVertices[0] = GetVertex( aNodes[0] ).Coord();
1753 aRefVertices[1] = GetVertex( aNodes[1] ).Coord();
1755 gp_Vec2d aRefEdgeDir( aRefVertices[0], aRefVertices[1] );
1757 Standard_Real aRefEdgeLen = aRefEdgeDir.Magnitude();
1758 if ( aRefEdgeLen < Precision )
1761 aRefEdgeDir /= aRefEdgeLen;
1763 // Find a point with minimum distance respect
1764 // the end of reference link
1765 Standard_Integer aUsedLinkId = 0;
1766 Standard_Real aOptAngle = 0.0;
1767 Standard_Real aMinDist = RealLast();
1768 Standard_Integer aPivotNode = aNodes[1];
1769 Standard_Integer aPolyLen = thePolygon.Length();
1770 for ( Standard_Integer aLinkIt = 3; aLinkIt <= aPolyLen; ++aLinkIt )
1772 Standard_Integer aLinkInfo = thePolygon( aLinkIt );
1773 const BRepMesh_Edge& aNextEdge = GetEdge( Abs( aLinkInfo ) );
1775 aPivotNode = aLinkInfo > 0 ?
1776 aNextEdge.FirstNode() :
1777 aNextEdge.LastNode();
1779 gp_Pnt2d aPivotVertex = GetVertex( aPivotNode ).Coord();
1780 gp_Vec2d aDistanceDir( aRefVertices[1], aPivotVertex );
1782 Standard_Real aDist = aRefEdgeDir ^ aDistanceDir;
1783 Standard_Real aAngle = Abs( aRefEdgeDir.Angle(aDistanceDir) );
1784 Standard_Real anAbsDist = Abs( aDist );
1785 if (anAbsDist < Precision || aDist < 0.)
1788 if ( ( anAbsDist >= aMinDist ) &&
1789 ( aAngle <= aOptAngle || aAngle > AngDeviation90Deg ) )
1794 // Check is the test link crosses the polygon boudaries
1795 Standard_Boolean isIntersect = Standard_False;
1796 for ( Standard_Integer aRefLinkNodeIt = 0; aRefLinkNodeIt < 2; ++aRefLinkNodeIt )
1798 const Standard_Integer& aLinkFirstNode = aNodes[aRefLinkNodeIt];
1799 const gp_Pnt2d& aLinkFirstVertex = aRefVertices[aRefLinkNodeIt];
1802 aBox.Add( aLinkFirstVertex );
1803 aBox.Add( aPivotVertex );
1805 BRepMesh_Edge aCheckLink( aLinkFirstNode, aPivotNode, BRepMesh_Free );
1807 Standard_Integer aCheckLinkIt = 2;
1808 for ( ; aCheckLinkIt <= aPolyLen; ++aCheckLinkIt )
1810 if( aCheckLinkIt == aLinkIt )
1813 if ( !aBox.IsOut( thePolyBoxes.Value( aCheckLinkIt ) ) )
1815 const BRepMesh_Edge& aPolyLink =
1816 GetEdge( Abs( thePolygon( aCheckLinkIt ) ) );
1818 if ( aCheckLink.IsEqual( aPolyLink ) )
1821 // intersection is possible...
1823 BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink,
1824 Standard_False, Standard_False, anIntPnt );
1826 if( aIntFlag != BRepMesh_GeomTool::NoIntersection )
1828 isIntersect = Standard_True;
1843 aMinDist = anAbsDist;
1844 aNodes[2] = aPivotNode;
1845 aRefVertices[2] = aPivotVertex;
1846 aUsedLinkId = aLinkIt;
1849 if ( aUsedLinkId == 0 )
1853 BRepMesh_Edge aNewEdges[2] = {
1854 BRepMesh_Edge( aNodes[1], aNodes[2], BRepMesh_Free ),
1855 BRepMesh_Edge( aNodes[2], aNodes[0], BRepMesh_Free ) };
1857 Standard_Integer aNewEdgesInfo[3] = {
1859 myMeshData->AddLink( aNewEdges[0] ),
1860 myMeshData->AddLink( aNewEdges[1] ) };
1863 Standard_Integer anEdges[3];
1864 Standard_Boolean anEdgesOri[3];
1865 for ( Standard_Integer aTriEdgeIt = 0; aTriEdgeIt < 3; ++aTriEdgeIt )
1867 const Standard_Integer& anEdgeInfo = aNewEdgesInfo[aTriEdgeIt];
1868 anEdges[aTriEdgeIt] = Abs( anEdgeInfo );
1869 anEdgesOri[aTriEdgeIt] = anEdgeInfo > 0;
1871 addTriangle( anEdges, anEdgesOri, aNodes );
1873 // Create triangle and split the source polygon on two
1874 // parts (if possible) and mesh each part as independent
1876 if ( aUsedLinkId < aPolyLen )
1878 BRepMesh::SequenceOfInteger aRightPolygon;
1879 thePolygon.Split( aUsedLinkId, aRightPolygon );
1880 aRightPolygon.Prepend( -aNewEdgesInfo[2] );
1882 BRepMesh::SequenceOfBndB2d aRightPolyBoxes;
1883 thePolyBoxes.Split( aUsedLinkId, aRightPolyBoxes );
1886 aBox.Add( aRefVertices[0] );
1887 aBox.Add( aRefVertices[2] );
1888 aRightPolyBoxes.Prepend( aBox );
1890 meshSimplePolygon( aRightPolygon, aRightPolyBoxes );
1894 thePolygon.Remove ( aPolyLen );
1895 thePolyBoxes.Remove( aPolyLen );
1898 if ( aUsedLinkId > 3 )
1900 thePolygon.SetValue( 1, -aNewEdgesInfo[1] );
1903 aBox.Add( aRefVertices[1] );
1904 aBox.Add( aRefVertices[2] );
1906 thePolyBoxes.SetValue( 1, aBox );
1908 meshSimplePolygon( thePolygon, thePolyBoxes );
1912 //=======================================================================
1913 //function : RemoveVertex
1914 //purpose : Removes a vertex from the triangulation
1915 //=======================================================================
1916 void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex )
1918 BRepMesh_SelectorOfDataStructureOfDelaun aSelector( myMeshData );
1919 aSelector.NeighboursOf( theVertex );
1921 BRepMesh::MapOfIntegerInteger aLoopEdges( 10, myMeshData->Allocator() );
1923 // Loop on triangles to be destroyed :
1924 BRepMesh::MapOfInteger::Iterator aTriangleIt( aSelector.Elements() );
1925 for ( ; aTriangleIt.More(); aTriangleIt.Next() )
1926 deleteTriangle( aTriangleIt.Key(), aLoopEdges );
1928 BRepMesh::SequenceOfBndB2d aBoxes;
1929 BRepMesh::SequenceOfInteger aPolygon;
1930 Standard_Integer aLoopEdgesCount = aLoopEdges.Extent();
1931 BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
1933 if ( aLoopEdgesIt.More() )
1935 const BRepMesh_Edge& anEdge = GetEdge( aLoopEdgesIt.Key() );
1936 Standard_Integer aFirstNode = anEdge.FirstNode();
1937 Standard_Integer aLastNode;
1938 Standard_Integer aPivotNode = anEdge.LastNode();
1939 Standard_Integer anEdgeId = aLoopEdgesIt.Key();
1941 Standard_Boolean isPositive = (Standard_Boolean)aLoopEdges( anEdgeId );
1944 Standard_Integer aTmp;
1946 aFirstNode = aPivotNode;
1949 aPolygon.Append( -anEdgeId );
1952 aPolygon.Append( anEdgeId );
1954 fillBndBox( aBoxes, GetVertex( aFirstNode ), GetVertex( aPivotNode ) );
1956 aLoopEdges.UnBind( anEdgeId );
1958 aLastNode = aFirstNode;
1959 while ( aPivotNode != aLastNode )
1961 BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( aPivotNode ) );
1962 for ( ; aLinkIt.More(); aLinkIt.Next() )
1964 if ( aLinkIt.Value() != anEdgeId &&
1965 aLoopEdges.IsBound( aLinkIt.Value() ) )
1967 Standard_Integer aCurrentNode;
1968 anEdgeId = aLinkIt.Value();
1969 const BRepMesh_Edge& anEdge1 = GetEdge( anEdgeId );
1971 aCurrentNode = anEdge1.LastNode();
1972 if ( aCurrentNode != aPivotNode )
1974 aCurrentNode = anEdge1.FirstNode();
1975 aPolygon.Append( -anEdgeId );
1978 aPolygon.Append( anEdgeId );
1980 fillBndBox( aBoxes, GetVertex( aCurrentNode ), GetVertex( aPivotNode ) );
1982 aPivotNode = aCurrentNode;
1983 aLoopEdges.UnBind( anEdgeId );
1988 if ( aLoopEdgesCount <= 0 )
1993 meshPolygon( aPolygon, aBoxes );
1998 //=======================================================================
1999 //function : AddVertices
2000 //purpose : Adds some vertices in the triangulation.
2001 //=======================================================================
2002 void BRepMesh_Delaun::AddVertices(BRepMesh::Array1OfVertexOfDelaun& theVertices)
2004 std::make_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun());
2005 std::sort_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun());
2007 Standard_Integer aLower = theVertices.Lower();
2008 Standard_Integer anUpper = theVertices.Upper();
2010 BRepMesh::Array1OfInteger aVertexIndexes( aLower, anUpper );
2011 for ( Standard_Integer i = aLower; i <= anUpper; ++i )
2012 aVertexIndexes(i) = myMeshData->AddNode( theVertices(i) );
2014 createTrianglesOnNewVertices( aVertexIndexes );
2017 //=======================================================================
2018 //function : UseEdge
2019 //purpose : Modify mesh to use the edge. Return True if done
2020 //=======================================================================
2021 Standard_Boolean BRepMesh_Delaun::UseEdge( const Standard_Integer /*theIndex*/ )
2024 const BRepMesh_PairOfIndex& aPair = myMeshData->ElemConnectedTo( theIndex );
2025 if ( aPair.Extent() == 0 )
2027 const BRepMesh_Edge& anEdge = GetEdge( theIndex );
2029 Standard_Integer aStartNode, aPivotNode, anOtherNode;
2030 aStartNode = anEdge.FirstNode();
2031 aPivotNode = anEdge.LastNode();
2033 const BRepMesh_ListOfInteger& aStartNodeNeighbors = myMeshData->LinkNeighboursOf( aStartNode );
2034 const BRepMesh_ListOfInteger& aPivotNodeNeighbors = myMeshData->LinkNeighboursOf( aPivotNode );
2036 if ( aStartNodeNeighbors.Extent() > 0 &&
2037 aPivotNodeNeighbors.Extent() > 0 )
2039 const BRepMesh_Vertex& aStartVertex = GetVertex( aStartNode );
2040 const BRepMesh_Vertex& aPivotVertex = GetVertex( aPivotNode );
2042 gp_XY aVEdge ( aPivotVertex.Coord() );
2043 aVEdge.Subtract( aStartVertex.Coord() );
2045 Standard_Real anAngle = 0.;
2046 Standard_Real anAngleMin = RealLast();
2047 Standard_Real anAngleMax = RealFirst();
2048 Standard_Integer aLeftEdge = 0, aRightEdge = 0;
2050 BRepMesh_ListOfInteger::Iterator aNeighborIt( aPivotNodeNeighbors );
2051 for ( ; aNeighborIt.More(); aNeighborIt.Next() )
2053 Standard_Integer anEdgeId = aNeighborIt.Value();
2054 if ( anEdgeId != theIndex )
2056 const BRepMesh_Edge& aNextEdge = GetEdge( anEdgeId );
2058 Standard_Boolean isInMesh = Standard_True;
2059 if ( aNextEdge.Movability() == BRepMesh_Free )
2061 if ( myMeshData->ElemConnectedTo( anEdgeId ).IsEmpty() )
2062 isInMesh = Standard_False;
2067 anOtherNode = aNextEdge.FirstNode();
2068 if ( anOtherNode == aPivotNode )
2069 anOtherNode = aNextEdge.LastNode();
2071 gp_XY aVEdgeCur = GetVertex( anOtherNode ).Coord();
2072 aVEdgeCur.Subtract( aPivotVertex.Coord() );
2074 anAngle = gp_Vec2d( aVEdge ).Angle( gp_Vec2d( aVEdgeCur ) );
2077 if ( anAngle > anAngleMax )
2079 anAngleMax = anAngle;
2080 aLeftEdge = anEdgeId;
2082 if ( anAngle < anAngleMin )
2084 anAngleMin = anAngle;
2085 aRightEdge = anEdgeId;
2090 if ( aLeftEdge > 0 )
2092 if (aLeftEdge==aRightEdge)
2102 return Standard_False;
2105 //=======================================================================
2106 //function : getEdgesByType
2107 //purpose : Gives the list of edges with type defined by input parameter
2108 //=======================================================================
2109 BRepMesh::HMapOfInteger BRepMesh_Delaun::getEdgesByType(
2110 const BRepMesh_DegreeOfFreedom theEdgeType ) const
2112 BRepMesh::HMapOfInteger aResult = new BRepMesh::MapOfInteger;
2113 BRepMesh::MapOfInteger::Iterator anEdgeIt( myMeshData->LinksOfDomain() );
2115 for ( ; anEdgeIt.More(); anEdgeIt.Next() )
2117 Standard_Integer anEdge = anEdgeIt.Key();
2118 Standard_Boolean isToAdd = (theEdgeType == BRepMesh_Free) ?
2119 (myMeshData->ElementsConnectedTo( anEdge ).Extent() <= 1) :
2120 (GetEdge( anEdge ).Movability() == theEdgeType);
2123 aResult->Add( anEdge );
2129 //=======================================================================
2130 //function : calculateDist
2131 //purpose : Calculates distances between the given point and edges of
2133 //=======================================================================
2134 Standard_Real BRepMesh_Delaun::calculateDist( const gp_XY theVEdges[3],
2135 const gp_XY thePoints[3],
2136 const Standard_Integer theEdgesId[3],
2137 const BRepMesh_Vertex& theVertex,
2138 Standard_Real theDistance[3],
2139 Standard_Real theSqModulus[3],
2140 Standard_Integer& theEdgeOn ) const
2142 Standard_Real aMinDist = -1;
2143 if ( !theVEdges || !thePoints || !theEdgesId ||
2144 !theDistance || !theSqModulus )
2147 for( Standard_Integer i = 0; i < 3; ++i )
2149 theSqModulus[i] = theVEdges[i].SquareModulus();
2150 if ( theSqModulus[i] <= Precision2 )
2153 theDistance[i] = theVEdges[i] ^ ( theVertex.Coord() - thePoints[i] );
2155 Standard_Real aDist = theDistance[i] * theDistance[i];
2156 aDist /= theSqModulus[i];
2158 if ( aMinDist < 0 || aDist < aMinDist )
2160 theEdgeOn = theEdgesId[i];
2168 //=======================================================================
2169 //function : Contains
2170 //purpose : Test if triangle of index <TrianIndex> contains geometricaly
2171 // <theVertex>. If <theEdgeOn> is != 0 then theVertex is on Edge
2172 // of index <theEdgeOn>
2173 //=======================================================================
2174 Standard_Boolean BRepMesh_Delaun::Contains( const Standard_Integer theTriangleId,
2175 const BRepMesh_Vertex& theVertex,
2176 Standard_Integer& theEdgeOn ) const
2180 Standard_Integer e[3];
2181 Standard_Boolean o[3];
2182 Standard_Integer p[3];
2184 const BRepMesh_Triangle& aElement = GetTriangle( theTriangleId );
2185 aElement.Edges(e, o);
2187 const BRepMesh_Edge* anEdges[3] = { &GetEdge( e[0] ),
2191 myMeshData->ElementNodes(aElement, p);
2194 aPoints[0] = GetVertex( p[0] ).Coord();
2195 aPoints[1] = GetVertex( p[1] ).Coord();
2196 aPoints[2] = GetVertex( p[2] ).Coord();
2199 aVEdges[0] = aPoints[1];
2200 aVEdges[0].Subtract( aPoints[0] );
2202 aVEdges[1] = aPoints[2];
2203 aVEdges[1].Subtract( aPoints[1] );
2205 aVEdges[2] = aPoints[0];
2206 aVEdges[2].Subtract( aPoints[2] );
2208 Standard_Real aDistance[3];
2209 Standard_Real aSqModulus[3];
2211 Standard_Real aMinDist;
2212 aMinDist = calculateDist( aVEdges, aPoints, e, theVertex, aDistance, aSqModulus, theEdgeOn );
2214 return Standard_False;
2216 if ( aMinDist > Precision2 )
2218 Standard_Integer anEdgeId = theEdgeOn;
2221 if ( anEdgeId != 0 )
2223 Standard_Integer i = 0;
2224 for ( ; i < 3; ++i )
2226 if( e[i] == anEdgeId )
2230 if( anEdges[i]->Movability() != BRepMesh_Free )
2231 if ( aDistance[i] < ( aSqModulus[i] / 5. ) )
2236 return ( aDistance[0] + aDistance[1] + aDistance[2] != 0. &&
2237 ( ( aDistance[0] >= 0. && aDistance[1] >= 0. && aDistance[2] >= 0. ) ||
2238 ( aDistance[0] <= 0. && aDistance[1] <= 0. && aDistance[2] <= 0. ) ) );
2241 //=============================================================================
2242 //function : intSegSeg
2243 //purpose : Checks intersection between the two segments.
2244 //=============================================================================
2245 BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg(
2246 const BRepMesh_Edge& theEdg1,
2247 const BRepMesh_Edge& theEdg2,
2248 const Standard_Boolean isConsiderEndPointTouch,
2249 const Standard_Boolean isConsiderPointOnEdge,
2250 gp_Pnt2d& theIntPnt) const
2252 gp_XY p1, p2, p3, p4;
2253 p1 = GetVertex( theEdg1.FirstNode() ).Coord();
2254 p2 = GetVertex( theEdg1.LastNode() ).Coord();
2255 p3 = GetVertex( theEdg2.FirstNode() ).Coord();
2256 p4 = GetVertex( theEdg2.LastNode() ).Coord();
2258 return BRepMesh_GeomTool::IntSegSeg(p1, p2, p3, p4,
2259 isConsiderEndPointTouch, isConsiderPointOnEdge, theIntPnt);
2262 //=============================================================================
2263 //function : polyArea
2264 //purpose : Returns area of the loop of the given polygon defined by indices
2265 // of its start and end links.
2266 //=============================================================================
2267 Standard_Real BRepMesh_Delaun::polyArea(const BRepMesh::SequenceOfInteger& thePolygon,
2268 const Standard_Integer theStartIndex,
2269 const Standard_Integer theEndIndex) const
2271 Standard_Real aArea = 0.0;
2272 Standard_Integer aPolyLen = thePolygon.Length();
2273 if ( theStartIndex >= theEndIndex ||
2274 theStartIndex > aPolyLen )
2278 Standard_Integer aCurEdgeInfo = thePolygon( theStartIndex );
2279 Standard_Integer aCurEdgeId = Abs( aCurEdgeInfo );
2280 const BRepMesh_Edge* aCurEdge = &GetEdge( aCurEdgeId );
2282 Standard_Integer aNodes[2];
2283 getOrientedNodes( *aCurEdge, aCurEdgeInfo > 0, aNodes );
2285 gp_Pnt2d aRefPnt = GetVertex( aNodes[0] ).Coord();
2286 Standard_Integer aPolyIt = theStartIndex + 1;
2287 for ( ; aPolyIt <= theEndIndex; ++aPolyIt )
2289 aCurEdgeInfo = thePolygon( aPolyIt );
2290 aCurEdgeId = Abs( aCurEdgeInfo );
2291 aCurEdge = &GetEdge( aCurEdgeId );
2293 getOrientedNodes( *aCurEdge, aCurEdgeInfo > 0, aNodes );
2294 gp_Vec2d aVec1( aRefPnt, GetVertex( aNodes[0] ).Coord() );
2295 gp_Vec2d aVec2( aRefPnt, GetVertex( aNodes[1] ).Coord() );
2297 aArea += aVec1 ^ aVec2;