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(BRepMesh::Array1OfVertexOfDelaun& theVertices)
86 : myCircles (theVertices.Length(), new NCollection_IncAllocator(
87 BRepMesh::MEMORY_BLOCK_SIZE_HUGE))
89 if ( theVertices.Length() > 2 )
91 myMeshData = new BRepMesh_DataStructureOfDelaun(
92 new NCollection_IncAllocator(BRepMesh::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 BRepMesh::Array1OfVertexOfDelaun& theVertices)
105 : myMeshData( theOldMesh ),
106 myCircles ( theVertices.Length(), theOldMesh->Allocator() )
108 if ( theVertices.Length() > 2 )
112 //=======================================================================
113 //function : BRepMesh_Delaun
114 //purpose : Creates the triangulation with and existent Mesh data structure
115 //=======================================================================
116 BRepMesh_Delaun::BRepMesh_Delaun(
117 const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh,
118 BRepMesh::Array1OfInteger& theVertexIndices)
119 : myMeshData( theOldMesh ),
120 myCircles ( theVertexIndices.Length(), theOldMesh->Allocator() )
122 if ( theVertexIndices.Length() > 2 )
125 Standard_Integer anIndex = theVertexIndices.Lower();
126 Standard_Integer anUpper = theVertexIndices.Upper();
127 for ( ; anIndex <= anUpper; ++anIndex )
128 aBox.Add( gp_Pnt2d( GetVertex( theVertexIndices( anIndex) ).Coord() ) );
130 perform( aBox, theVertexIndices );
134 //=======================================================================
136 //purpose : Initializes the triangulation with an Array of Vertex
137 //=======================================================================
138 void BRepMesh_Delaun::Init(BRepMesh::Array1OfVertexOfDelaun& theVertices)
141 Standard_Integer aLowerIdx = theVertices.Lower();
142 Standard_Integer anUpperIdx = theVertices.Upper();
143 BRepMesh::Array1OfInteger aVertexIndexes( aLowerIdx, anUpperIdx );
145 Standard_Integer anIndex = aLowerIdx;
146 for ( ; anIndex <= anUpperIdx; ++anIndex )
148 aBox.Add( gp_Pnt2d( theVertices( anIndex ).Coord() ) );
149 aVertexIndexes( anIndex ) = myMeshData->AddNode( theVertices( anIndex ) );
152 perform( aBox, aVertexIndexes );
155 //=======================================================================
157 //purpose : Create super mesh and run triangulation procedure
158 //=======================================================================
159 void BRepMesh_Delaun::perform(Bnd_Box2d& theBndBox,
160 BRepMesh::Array1OfInteger& theVertexIndexes)
162 theBndBox.Enlarge( Precision );
163 superMesh( theBndBox );
165 ComparatorOfIndexedVertexOfDelaun aCmp(myMeshData);
166 std::make_heap(theVertexIndexes.begin(), theVertexIndexes.end(), aCmp);
167 std::sort_heap(theVertexIndexes.begin(), theVertexIndexes.end(), aCmp);
169 compute( theVertexIndexes );
172 //=======================================================================
173 //function : superMesh
174 //purpose : Build the super mesh
175 //=======================================================================
176 void BRepMesh_Delaun::superMesh( const Bnd_Box2d& theBox )
178 Standard_Real aMinX, aMinY, aMaxX, aMaxY;
179 theBox.Get( aMinX, aMinY, aMaxX, aMaxY );
180 Standard_Real aDeltaX = aMaxX - aMinX;
181 Standard_Real aDeltaY = aMaxY - aMinY;
183 Standard_Real aDeltaMin = Min( aDeltaX, aDeltaY );
184 Standard_Real aDeltaMax = Max( aDeltaX, aDeltaY );
185 Standard_Real aDelta = aDeltaX + aDeltaY;
187 myCircles.SetMinMaxSize( gp_XY( aMinX, aMinY ), gp_XY( aMaxX, aMaxY ) );
189 Standard_Integer aScaler = 2;
190 if ( myMeshData->NbNodes() > 100 )
192 else if( myMeshData->NbNodes() > 1000 )
195 myCircles.SetCellSize( aDeltaX / aScaler,
198 mySupVert[0] = myMeshData->AddNode(
199 BRepMesh_Vertex( ( aMinX + aMaxX ) / 2, aMaxY + aDeltaMax, BRepMesh_Free ) );
201 mySupVert[1] = myMeshData->AddNode(
202 BRepMesh_Vertex( aMinX - aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
204 mySupVert[2] = myMeshData->AddNode(
205 BRepMesh_Vertex( aMaxX + aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
207 Standard_Integer e[3];
208 Standard_Boolean o[3];
209 for (Standard_Integer aNodeId = 0; aNodeId < 3; ++aNodeId)
211 Standard_Integer aFirstNode = aNodeId;
212 Standard_Integer aLastNode = (aNodeId + 1) % 3;
213 Standard_Integer aLinkIndex = myMeshData->AddLink( BRepMesh_Edge(
214 mySupVert[aFirstNode], mySupVert[aLastNode], BRepMesh_Free ) );
216 e[aNodeId] = Abs(aLinkIndex);
217 o[aNodeId] = (aLinkIndex > 0);
220 mySupTrian = BRepMesh_Triangle(e, o, BRepMesh_Free);
223 //=======================================================================
224 //function : deleteTriangle
225 //purpose : Deletes the triangle with the given index and adds the free
226 // edges into the map.
227 // When an edge is suppressed more than one time it is destroyed.
228 //=======================================================================
229 void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex,
230 BRepMesh::MapOfIntegerInteger& theLoopEdges )
232 myCircles.Delete( theIndex );
234 Standard_Integer e[3];
235 Standard_Boolean o[3];
236 GetTriangle( theIndex ).Edges( e, o );
238 myMeshData->RemoveElement( theIndex );
240 for ( Standard_Integer i = 0; i < 3; ++i )
242 if ( !theLoopEdges.Bind( e[i], o[i] ) )
244 theLoopEdges.UnBind( e[i] );
245 myMeshData->RemoveLink( e[i] );
250 //=======================================================================
252 //purpose : Computes the triangulation and add the vertices edges and
253 // triangles to the Mesh data structure
254 //=======================================================================
255 void BRepMesh_Delaun::compute(BRepMesh::Array1OfInteger& theVertexIndexes)
257 // Insertion of edges of super triangles in the list of free edges:
258 BRepMesh::MapOfIntegerInteger aLoopEdges(10, myMeshData->Allocator());
259 Standard_Integer e[3];
260 Standard_Boolean o[3];
261 mySupTrian.Edges( e, o );
263 aLoopEdges.Bind( e[0], Standard_True );
264 aLoopEdges.Bind( e[1], Standard_True );
265 aLoopEdges.Bind( e[2], Standard_True );
267 if ( theVertexIndexes.Length() > 0 )
269 // Creation of 3 trianglers with the first node and the edges of the super triangle:
270 Standard_Integer anVertexIdx = theVertexIndexes.Lower();
271 createTriangles( theVertexIndexes( anVertexIdx ), aLoopEdges );
273 // Add other nodes to the mesh
274 createTrianglesOnNewVertices( theVertexIndexes );
277 // Destruction of triangles containing a top of the super triangle
278 BRepMesh_SelectorOfDataStructureOfDelaun aSelector( myMeshData );
279 for (Standard_Integer aSupVertId = 0; aSupVertId < 3; ++aSupVertId)
280 aSelector.NeighboursOfNode( mySupVert[aSupVertId] );
283 BRepMesh::MapOfInteger::Iterator aFreeTriangles( aSelector.Elements() );
284 for ( ; aFreeTriangles.More(); aFreeTriangles.Next() )
285 deleteTriangle( aFreeTriangles.Key(), aLoopEdges );
287 // All edges that remain free are removed from aLoopEdges;
288 // only the boundary edges of the triangulation remain there
289 BRepMesh::MapOfIntegerInteger::Iterator aFreeEdges( aLoopEdges );
290 for ( ; aFreeEdges.More(); aFreeEdges.Next() )
292 if ( myMeshData->ElementsConnectedTo( aFreeEdges.Key() ).IsEmpty() )
293 myMeshData->RemoveLink( aFreeEdges.Key() );
296 // The tops of the super triangle are destroyed
297 for (Standard_Integer aSupVertId = 0; aSupVertId < 3; ++aSupVertId)
298 myMeshData->RemoveNode( mySupVert[aSupVertId] );
301 //=======================================================================
302 //function : createTriangles
303 //purpose : Creates the triangles beetween the node and the polyline.
304 //=======================================================================
305 void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex,
306 BRepMesh::MapOfIntegerInteger& thePoly)
308 BRepMesh::ListOfInteger aLoopEdges, anExternalEdges;
309 const gp_XY& aVertexCoord = myMeshData->GetNode( theVertexIndex ).Coord();
311 BRepMesh::MapOfIntegerInteger::Iterator anEdges( thePoly );
312 for ( ; anEdges.More(); anEdges.Next() )
314 Standard_Integer anEdgeId = anEdges.Key();
315 const BRepMesh_Edge& anEdge = GetEdge( anEdgeId );
317 const Standard_Boolean isPositive = thePoly (anEdgeId) != 0;
319 Standard_Integer aNodes[3];
322 aNodes[0] = anEdge.FirstNode();
323 aNodes[2] = anEdge.LastNode();
327 aNodes[0] = anEdge.LastNode();
328 aNodes[2] = anEdge.FirstNode();
330 aNodes[1] = theVertexIndex;
332 const BRepMesh_Vertex& aFirstVertex = GetVertex( aNodes[0] );
333 const BRepMesh_Vertex& aLastVertex = GetVertex( aNodes[2] );
335 gp_XY anEdgeDir( aLastVertex.Coord() - aFirstVertex.Coord() );
336 Standard_Real anEdgeLen = anEdgeDir.Modulus();
337 if ( anEdgeLen < Precision )
340 anEdgeDir.SetCoord( anEdgeDir.X() / anEdgeLen,
341 anEdgeDir.Y() / anEdgeLen );
343 gp_XY aFirstLinkDir( aFirstVertex.Coord() - aVertexCoord );
344 gp_XY aLastLinkDir ( aVertexCoord - aLastVertex.Coord() );
346 Standard_Real aDist12 = aFirstLinkDir ^ anEdgeDir;
347 Standard_Real aDist23 = anEdgeDir ^ aLastLinkDir;
348 if ( Abs( aDist12 ) < Precision ||
349 Abs( aDist23 ) < Precision )
354 BRepMesh_Edge aFirstLink( aNodes[1], aNodes[0], BRepMesh_Free );
355 BRepMesh_Edge aLastLink ( aNodes[2], aNodes[1], BRepMesh_Free );
357 Standard_Integer anEdgesInfo[3] = {
358 myMeshData->AddLink( aFirstLink ),
359 isPositive ? anEdgeId : -anEdgeId,
360 myMeshData->AddLink( aLastLink ) };
362 Standard_Boolean isSensOK = (aDist12 > 0. && aDist23 > 0.);
365 Standard_Integer anEdgeIds[3];
366 Standard_Boolean anEdgesOri[3];
367 for ( Standard_Integer aTriLinkIt = 0; aTriLinkIt < 3; ++aTriLinkIt )
369 const Standard_Integer& anEdgeInfo = anEdgesInfo[aTriLinkIt];
370 anEdgeIds[aTriLinkIt] = Abs( anEdgeInfo );
371 anEdgesOri[aTriLinkIt] = anEdgeInfo > 0;
374 addTriangle(anEdgeIds, anEdgesOri, aNodes );
379 aLoopEdges.Append( anEdges.Key() );
381 aLoopEdges.Append( -anEdges.Key() );
383 if ( aFirstLinkDir.SquareModulus() > aLastLinkDir.SquareModulus() )
384 anExternalEdges.Append( Abs( anEdgesInfo[0] ) );
386 anExternalEdges.Append( Abs( anEdgesInfo[2] ) );
391 while ( !anExternalEdges.IsEmpty() )
393 const BRepMesh_PairOfIndex& aPair =
394 myMeshData->ElementsConnectedTo( Abs( anExternalEdges.First() ) );
397 if ( !aPair.IsEmpty() )
398 deleteTriangle( aPair.FirstIndex(), thePoly );
400 anExternalEdges.RemoveFirst();
403 for ( anEdges.Initialize( thePoly ); anEdges.More(); anEdges.Next() )
405 if ( myMeshData->ElementsConnectedTo( anEdges.Key() ).IsEmpty() )
406 myMeshData->RemoveLink( anEdges.Key() );
409 while ( !aLoopEdges.IsEmpty() )
411 const BRepMesh_Edge& anEdge = GetEdge( Abs( aLoopEdges.First() ) );
412 if ( anEdge.Movability() != BRepMesh_Deleted )
414 Standard_Integer anEdgeIdx = aLoopEdges.First();
415 meshLeftPolygonOf( Abs( anEdgeIdx ), ( anEdgeIdx > 0 ) );
418 aLoopEdges.RemoveFirst();
422 //=======================================================================
423 //function : createTrianglesOnNewVertices
424 //purpose : Creation of triangles from the new nodes
425 //=======================================================================
426 void BRepMesh_Delaun::createTrianglesOnNewVertices(
427 BRepMesh::Array1OfInteger& theVertexIndexes)
429 Handle(NCollection_IncAllocator) aAllocator =
430 new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
432 Standard_Real aTolU, aTolV;
433 myMeshData->Data()->GetTolerance(aTolU, aTolV);
434 const Standard_Real aSqTol = aTolU * aTolU + aTolV * aTolV;
436 // Insertion of nodes :
437 Standard_Boolean isModify = Standard_True;
439 Standard_Integer anIndex = theVertexIndexes.Lower();
440 Standard_Integer anUpper = theVertexIndexes.Upper();
441 for( ; anIndex <= anUpper; ++anIndex )
443 aAllocator->Reset(Standard_False);
444 BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
446 Standard_Integer aVertexIdx = theVertexIndexes( anIndex );
447 const BRepMesh_Vertex& aVertex = GetVertex( aVertexIdx );
449 // Iterator in the list of indexes of circles containing the node
450 BRepMesh::ListOfInteger& aCirclesList = myCircles.Select( aVertex.Coord() );
452 Standard_Integer onEgdeId = 0, aTriangleId = 0;
453 BRepMesh::ListOfInteger::Iterator aCircleIt( aCirclesList );
454 for ( ; aCircleIt.More(); aCircleIt.Next() )
456 // To add a node in the mesh it is necessary to check conditions:
457 // - the node should be within the boundaries of the mesh and so in an existing triangle
458 // - all adjacent triangles should belong to a component connected with this triangle
459 if ( Contains( aCircleIt.Value(), aVertex, aSqTol, onEgdeId ) )
461 if (onEgdeId != 0 && GetEdge(onEgdeId).Movability() != BRepMesh_Free)
463 // We can skip free vertex too close to the frontier edge.
464 if (aVertex.Movability() == BRepMesh_Free)
467 // However, we should add vertex that have neighboring frontier edges.
470 // Remove triangle even if it contains frontier edge in order
471 // to prevent appearance of incorrect configurations like free
472 // edge glued with frontier #26407
473 aTriangleId = aCircleIt.Value();
474 aCirclesList.Remove( aCircleIt );
479 if ( aTriangleId > 0 )
481 deleteTriangle( aTriangleId, aLoopEdges );
483 isModify = Standard_True;
484 while ( isModify && !aCirclesList.IsEmpty() )
486 isModify = Standard_False;
487 BRepMesh::ListOfInteger::Iterator aCircleIt1( aCirclesList );
488 for ( ; aCircleIt1.More(); aCircleIt1.Next() )
490 Standard_Integer e[3];
491 Standard_Boolean o[3];
492 GetTriangle( aCircleIt1.Value() ).Edges( e, o );
494 if ( aLoopEdges.IsBound( e[0] ) ||
495 aLoopEdges.IsBound( e[1] ) ||
496 aLoopEdges.IsBound( e[2] ) )
498 isModify = Standard_True;
499 deleteTriangle( aCircleIt1.Value(), aLoopEdges );
500 aCirclesList.Remove( aCircleIt1 );
506 // Creation of triangles with the current node and free edges
507 // and removal of these edges from the list of free edges
508 createTriangles( aVertexIdx, aLoopEdges );
512 insertInternalEdges();
514 // Adjustment of meshes to boundary edges
518 //=======================================================================
519 //function : insertInternalEdges
521 //=======================================================================
522 void BRepMesh_Delaun::insertInternalEdges()
524 BRepMesh::HMapOfInteger anInternalEdges = InternalEdges();
526 // Destruction of triancles intersecting internal edges
527 // and their replacement by makeshift triangles
528 Standard_Integer e[3];
529 Standard_Boolean o[3];
530 BRepMesh::MapOfInteger::Iterator anInernalEdgesIt( *anInternalEdges );
531 for ( ; anInernalEdgesIt.More(); anInernalEdgesIt.Next() )
533 const Standard_Integer aLinkIndex = anInernalEdgesIt.Key();
534 const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo(aLinkIndex);
536 // Check both sides of link for adjusted triangle.
537 Standard_Boolean isGo[2] = { Standard_True, Standard_True };
538 for (Standard_Integer aTriangleIt = 1; aTriangleIt <= aPair.Extent(); ++aTriangleIt)
540 GetTriangle(aPair.Index(aTriangleIt)).Edges(e, o);
541 for (Standard_Integer i = 0; i < 3; ++i)
543 if (e[i] == aLinkIndex)
545 isGo[o[i] ? 0 : 1] = Standard_False;
553 meshLeftPolygonOf(aLinkIndex, Standard_True);
558 meshLeftPolygonOf(aLinkIndex, Standard_False);
563 //=======================================================================
564 //function : isBoundToFrontier
565 //purpose : Goes through the neighbour triangles around the given node
566 // started from the given link, returns TRUE if some triangle
567 // has a bounding frontier edge or FALSE elsewhere.
568 // Stop link is used to prevent cycles.
569 // Previous element Id is used to identify next neighbor element.
570 //=======================================================================
571 Standard_Boolean BRepMesh_Delaun::isBoundToFrontier(
572 const Standard_Integer theRefNodeId,
573 const Standard_Integer theRefLinkId,
574 const Standard_Integer theStopLinkId,
575 const Standard_Integer thePrevElementId)
577 const BRepMesh_PairOfIndex& aPair =
578 myMeshData->ElementsConnectedTo( theRefLinkId );
579 if ( aPair.IsEmpty() )
580 return Standard_False;
582 Standard_Integer aNbElements = aPair.Extent();
583 for ( Standard_Integer anElemIt = 1; anElemIt <= aNbElements; ++anElemIt )
585 const Standard_Integer aTriId = aPair.Index(anElemIt);
586 if ( aTriId < 0 || aTriId == thePrevElementId )
589 Standard_Integer anEdges[3];
590 Standard_Boolean anEdgesOri[3];
591 GetTriangle( aTriId ).Edges( anEdges, anEdgesOri );
593 for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
595 const Standard_Integer anEdgeId = anEdges[anEdgeIt];
596 if ( anEdgeId == theRefLinkId )
599 if ( anEdgeId == theStopLinkId )
600 return Standard_False;
602 const BRepMesh_Edge& anEdge = GetEdge( anEdgeId );
603 if ( anEdge.FirstNode() != theRefNodeId &&
604 anEdge.LastNode() != theRefNodeId )
609 if ( anEdge.Movability() != BRepMesh_Free )
610 return Standard_True;
612 return isBoundToFrontier( theRefNodeId, anEdgeId, theStopLinkId, aTriId );
616 return Standard_False;
619 //=======================================================================
620 //function : cleanupMesh
621 //purpose : Cleanup mesh from the free triangles
622 //=======================================================================
623 void BRepMesh_Delaun::cleanupMesh()
625 Handle(NCollection_IncAllocator) aAllocator =
626 new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
630 aAllocator->Reset(Standard_False);
631 BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
632 BRepMesh::MapOfInteger aDelTriangles(10, aAllocator);
634 BRepMesh::HMapOfInteger aFreeEdges = FreeEdges();
635 BRepMesh::MapOfInteger::Iterator aFreeEdgesIt( *aFreeEdges );
636 for ( ; aFreeEdgesIt.More(); aFreeEdgesIt.Next() )
638 const Standard_Integer& aFreeEdgeId = aFreeEdgesIt.Key();
639 const BRepMesh_Edge& anEdge = GetEdge( aFreeEdgeId );
640 if ( anEdge.Movability() == BRepMesh_Frontier )
643 const BRepMesh_PairOfIndex& aPair =
644 myMeshData->ElementsConnectedTo( aFreeEdgeId );
645 if ( aPair.IsEmpty() )
647 aLoopEdges.Bind( aFreeEdgeId, Standard_True );
651 Standard_Integer aTriId = aPair.FirstIndex();
653 // Check that the connected triangle is not surrounded by another triangles
654 Standard_Integer anEdges[3];
655 Standard_Boolean anEdgesOri[3];
656 GetTriangle( aTriId ).Edges( anEdges, anEdgesOri );
658 Standard_Boolean isCanNotBeRemoved = Standard_True;
659 for ( Standard_Integer aCurEdgeIdx = 0; aCurEdgeIdx < 3; ++aCurEdgeIdx )
661 if ( anEdges[aCurEdgeIdx] != aFreeEdgeId )
664 for ( Standard_Integer anOtherEdgeIt = 1; anOtherEdgeIt <= 2; ++anOtherEdgeIt )
666 Standard_Integer anOtherEdgeId = ( aCurEdgeIdx + anOtherEdgeIt ) % 3;
667 const BRepMesh_PairOfIndex& anOtherEdgePair =
668 myMeshData->ElementsConnectedTo( anEdges[anOtherEdgeId] );
670 if ( anOtherEdgePair.Extent() < 2 )
672 isCanNotBeRemoved = Standard_False;
680 if ( isCanNotBeRemoved )
683 Standard_Boolean isConnected[2] = { Standard_False, Standard_False };
684 for ( Standard_Integer aLinkNodeIt = 0; aLinkNodeIt < 2; ++aLinkNodeIt )
686 isConnected[aLinkNodeIt] = isBoundToFrontier( ( aLinkNodeIt == 0 ) ?
687 anEdge.FirstNode() : anEdge.LastNode(),
688 aFreeEdgeId, aFreeEdgeId, -1);
691 if ( !isConnected[0] || !isConnected[1] )
692 aDelTriangles.Add( aTriId );
695 // Destruction of triangles :
696 Standard_Integer aDeletedTrianglesNb = 0;
697 BRepMesh::MapOfInteger::Iterator aDelTrianglesIt( aDelTriangles );
698 for ( ; aDelTrianglesIt.More(); aDelTrianglesIt.Next() )
700 deleteTriangle( aDelTrianglesIt.Key(), aLoopEdges );
701 aDeletedTrianglesNb++;
704 // Destruction of remaining hanging edges
705 BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
706 for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
708 if ( myMeshData->ElementsConnectedTo( aLoopEdgesIt.Key() ).IsEmpty() )
709 myMeshData->RemoveLink( aLoopEdgesIt.Key() );
712 if ( aDeletedTrianglesNb == 0 )
717 //=======================================================================
718 //function : frontierAdjust
719 //purpose : Adjust the mesh on the frontier
720 //=======================================================================
721 void BRepMesh_Delaun::frontierAdjust()
723 BRepMesh::HMapOfInteger aFrontier = Frontier();
725 Handle(NCollection_IncAllocator) aAllocator =
726 new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
728 BRepMesh::VectorOfInteger aFailedFrontiers(256, aAllocator);
729 BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
730 BRepMesh::HMapOfInteger aIntFrontierEdges =
731 new BRepMesh::MapOfInteger(10, aAllocator);
733 for ( Standard_Integer aPass = 1; aPass <= 2; ++aPass )
735 // 1 pass): find external triangles on boundary edges;
736 // 2 pass): find external triangles on boundary edges appeared
737 // during triangles replacement.
739 BRepMesh::MapOfInteger::Iterator aFrontierIt( *aFrontier );
740 for ( ; aFrontierIt.More(); aFrontierIt.Next() )
742 Standard_Integer aFrontierId = aFrontierIt.Key();
743 const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo( aFrontierId );
744 Standard_Integer aNbElem = aPair.Extent();
745 for( Standard_Integer aElemIt = 1; aElemIt <= aNbElem; ++aElemIt )
747 const Standard_Integer aPriorElemId = aPair.Index( aElemIt );
748 if( aPriorElemId < 0 )
751 Standard_Integer e[3];
752 Standard_Boolean o[3];
753 GetTriangle( aPriorElemId ).Edges( e, o );
755 Standard_Boolean isTriangleFound = Standard_False;
756 for ( Standard_Integer n = 0; n < 3; ++n )
758 if ( aFrontierId == e[n] && !o[n] )
760 // Destruction of external triangles on boundary edges
761 isTriangleFound = Standard_True;
762 deleteTriangle( aPriorElemId, aLoopEdges );
767 if ( isTriangleFound )
772 // destrucrion of remaining hanging edges :
773 BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
774 for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
776 Standard_Integer aLoopEdgeId = aLoopEdgesIt.Key();
777 if (myMeshData->ElementsConnectedTo( aLoopEdgeId ).IsEmpty() )
778 myMeshData->RemoveLink( aLoopEdgeId );
781 // destruction of triangles crossing the boundary edges and
782 // their replacement by makeshift triangles
783 for ( aFrontierIt.Reset(); aFrontierIt.More(); aFrontierIt.Next() )
785 Standard_Integer aFrontierId = aFrontierIt.Key();
786 if ( !myMeshData->ElementsConnectedTo( aFrontierId ).IsEmpty() )
789 Standard_Boolean isSuccess =
790 meshLeftPolygonOf( aFrontierId, Standard_True, aIntFrontierEdges );
792 if ( aPass == 2 && !isSuccess )
793 aFailedFrontiers.Append( aFrontierId );
799 // When the mesh has been cleaned up, try to process frontier edges
800 // once again to fill the possible gaps that might be occured in case of "saw" -
801 // situation when frontier edge has a triangle at a right side, but its free
802 // links cross another frontieres and meshLeftPolygonOf itself can't collect
804 BRepMesh::VectorOfInteger::Iterator aFailedFrontiersIt( aFailedFrontiers );
805 for ( ; aFailedFrontiersIt.More(); aFailedFrontiersIt.Next() )
807 Standard_Integer aFrontierId = aFailedFrontiersIt.Value();
808 if ( !myMeshData->ElementsConnectedTo( aFrontierId ).IsEmpty() )
811 meshLeftPolygonOf( aFrontierId, Standard_True, aIntFrontierEdges );
815 //=======================================================================
816 //function : fillBndBox
817 //purpose : Add boundig box for edge defined by start & end point to
818 // the given vector of bounding boxes for triangulation edges
819 //=======================================================================
820 void BRepMesh_Delaun::fillBndBox(BRepMesh::SequenceOfBndB2d& theBoxes,
821 const BRepMesh_Vertex& theV1,
822 const BRepMesh_Vertex& theV2)
825 UpdateBndBox(theV1.Coord(), theV2.Coord(), aBox);
826 theBoxes.Append( aBox );
829 //=======================================================================
830 //function : meshLeftPolygonOf
831 //purpose : Collect the polygon at the left of the given edge (material side)
832 //=======================================================================
833 Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf(
834 const Standard_Integer theStartEdgeId,
835 const Standard_Boolean isForward,
836 BRepMesh::HMapOfInteger theSkipped )
838 if ( !theSkipped.IsNull() && theSkipped->Contains( theStartEdgeId ) )
839 return Standard_True;
841 const BRepMesh_Edge& aRefEdge = GetEdge( theStartEdgeId );
843 BRepMesh::SequenceOfInteger aPolygon;
844 Standard_Integer aStartNode, aPivotNode;
847 aPolygon.Append( theStartEdgeId );
848 aStartNode = aRefEdge.FirstNode();
849 aPivotNode = aRefEdge.LastNode();
853 aPolygon.Append( -theStartEdgeId );
854 aStartNode = aRefEdge.LastNode();
855 aPivotNode = aRefEdge.FirstNode();
859 const BRepMesh_Vertex& aStartEdgeVertexS = GetVertex( aStartNode );
860 BRepMesh_Vertex aPivotVertex = GetVertex( aPivotNode );
862 gp_Vec2d aRefLinkDir( aPivotVertex.Coord() -
863 aStartEdgeVertexS.Coord() );
865 if ( aRefLinkDir.SquareMagnitude() < Precision2 )
866 return Standard_True;
868 // Auxilary structures.
869 // Bounding boxes of polygon links to be used for preliminary
870 // analysis of intersections
871 BRepMesh::SequenceOfBndB2d aBoxes;
872 fillBndBox( aBoxes, aStartEdgeVertexS, aPivotVertex );
875 BRepMesh::MapOfInteger aDeadLinks;
877 // Links are temporarily excluded from consideration
878 BRepMesh::MapOfInteger aLeprousLinks;
879 aLeprousLinks.Add( theStartEdgeId );
881 Standard_Boolean isSkipLeprous = Standard_True;
882 Standard_Integer aFirstNode = aStartNode;
883 while ( aPivotNode != aFirstNode )
885 Bnd_B2d aNextLinkBndBox;
886 gp_Vec2d aNextLinkDir;
887 Standard_Integer aNextPivotNode = 0;
889 Standard_Integer aNextLinkId = findNextPolygonLink(
891 aPivotNode, aPivotVertex, aRefLinkDir,
892 aBoxes, aPolygon, theSkipped,
893 isSkipLeprous, aLeprousLinks, aDeadLinks,
894 aNextPivotNode, aNextLinkDir, aNextLinkBndBox );
896 if ( aNextLinkId != 0 )
898 aStartNode = aPivotNode;
899 aRefLinkDir = aNextLinkDir;
901 aPivotNode = aNextPivotNode;
902 aPivotVertex = GetVertex( aNextPivotNode );
904 aBoxes.Append ( aNextLinkBndBox );
905 aPolygon.Append( aNextLinkId );
907 isSkipLeprous = Standard_True;
912 if ( aPolygon.Length() == 1 )
913 return Standard_False;
915 // Return to the previous point
916 Standard_Integer aDeadLinkId = Abs( aPolygon.Last() );
917 aDeadLinks.Add ( aDeadLinkId );
919 aLeprousLinks.Remove( aDeadLinkId );
920 aPolygon.Remove ( aPolygon.Length() );
921 aBoxes.Remove ( aBoxes.Length() );
923 Standard_Integer aPrevLinkInfo = aPolygon.Last();
924 const BRepMesh_Edge& aPrevLink = GetEdge( Abs( aPrevLinkInfo ) );
926 if( aPrevLinkInfo > 0 )
928 aStartNode = aPrevLink.FirstNode();
929 aPivotNode = aPrevLink.LastNode();
933 aStartNode = aPrevLink.LastNode();
934 aPivotNode = aPrevLink.FirstNode();
937 aPivotVertex = GetVertex( aPivotNode );
939 aPivotVertex.Coord() - GetVertex( aStartNode ).Coord();
941 isSkipLeprous = Standard_False;
945 if ( aPolygon.Length() < 3 )
946 return Standard_False;
948 cleanupPolygon( aPolygon, aBoxes );
949 meshPolygon ( aPolygon, aBoxes, theSkipped );
951 return Standard_True;
954 //=======================================================================
955 //function : findNextPolygonLink
956 //purpose : Find next link starting from the given node and has maximum
957 // angle respect the given reference link.
958 // Each time the next link is found other neighbor links at the
959 // pivot node are marked as leprous and will be excluded from
960 // consideration next time until a hanging end is occured.
961 //=======================================================================
962 Standard_Integer BRepMesh_Delaun::findNextPolygonLink(
963 const Standard_Integer& theFirstNode,
964 const Standard_Integer& thePivotNode,
965 const BRepMesh_Vertex& thePivotVertex,
966 const gp_Vec2d& theRefLinkDir,
967 const BRepMesh::SequenceOfBndB2d& theBoxes,
968 const BRepMesh::SequenceOfInteger& thePolygon,
969 const BRepMesh::HMapOfInteger theSkipped,
970 const Standard_Boolean& isSkipLeprous,
971 BRepMesh::MapOfInteger& theLeprousLinks,
972 BRepMesh::MapOfInteger& theDeadLinks,
973 Standard_Integer& theNextPivotNode,
974 gp_Vec2d& theNextLinkDir,
975 Bnd_B2d& theNextLinkBndBox )
977 // Find the next link having the greatest angle
978 // respect to a direction of a reference one
979 Standard_Real aMaxAngle = RealFirst();
981 Standard_Integer aNextLinkId = 0;
982 BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) );
983 for ( ; aLinkIt.More(); aLinkIt.Next() )
985 const Standard_Integer& aNeighbourLinkInfo = aLinkIt.Value();
986 Standard_Integer aNeighbourLinkId = Abs( aNeighbourLinkInfo );
988 if ( theDeadLinks.Contains( aNeighbourLinkId ) ||
989 ( !theSkipped.IsNull() && theSkipped->Contains( aNeighbourLinkId ) ) )
994 Standard_Boolean isLeprous = theLeprousLinks.Contains( aNeighbourLinkId );
995 if ( isSkipLeprous && isLeprous )
998 const BRepMesh_Edge& aNeighbourLink = GetEdge( aNeighbourLinkId );
1000 // Determine whether the link belongs to the mesh
1001 if ( aNeighbourLink.Movability() == BRepMesh_Free &&
1002 myMeshData->ElementsConnectedTo( aNeighbourLinkInfo ).IsEmpty() )
1004 theDeadLinks.Add( aNeighbourLinkId );
1008 Standard_Integer anOtherNode = aNeighbourLink.FirstNode();
1009 if ( anOtherNode == thePivotNode )
1010 anOtherNode = aNeighbourLink.LastNode();
1012 gp_Vec2d aCurLinkDir( GetVertex( anOtherNode ).Coord() -
1013 thePivotVertex.Coord() );
1015 if ( aCurLinkDir.SquareMagnitude() < Precision2 )
1017 theDeadLinks.Add( aNeighbourLinkId );
1022 theLeprousLinks.Add( aNeighbourLinkId );
1024 Standard_Real anAngle = theRefLinkDir.Angle( aCurLinkDir );
1025 Standard_Boolean isFrontier =
1026 ( aNeighbourLink.Movability() == BRepMesh_Frontier );
1028 Standard_Boolean isCheckPointOnEdge = Standard_True;
1031 if ( Abs( Abs(anAngle) - M_PI ) < Precision::Angular() )
1033 // Glued constrains - don't check intersection
1034 isCheckPointOnEdge = Standard_False;
1035 anAngle = Abs( anAngle );
1039 if (anAngle <= aMaxAngle)
1042 Standard_Boolean isCheckEndPoints = ( anOtherNode != theFirstNode );
1045 Standard_Boolean isNotIntersect =
1046 checkIntersection( aNeighbourLink, thePolygon, theBoxes,
1047 isCheckEndPoints, isCheckPointOnEdge, Standard_True, aBox );
1049 if( isNotIntersect )
1051 aMaxAngle = anAngle;
1053 theNextLinkDir = aCurLinkDir;
1054 theNextPivotNode = anOtherNode;
1055 theNextLinkBndBox = aBox;
1057 aNextLinkId = ( aNeighbourLink.FirstNode() == thePivotNode ) ?
1058 aNeighbourLinkId : -aNeighbourLinkId;
1065 //=======================================================================
1066 //function : checkIntersection
1067 //purpose : Check is the given link intersects the polygon boundaries.
1068 // Returns bounding box for the given link trough the
1069 // <theLinkBndBox> parameter.
1070 //=======================================================================
1071 Standard_Boolean BRepMesh_Delaun::checkIntersection(
1072 const BRepMesh_Edge& theLink,
1073 const BRepMesh::SequenceOfInteger& thePolygon,
1074 const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
1075 const Standard_Boolean isConsiderEndPointTouch,
1076 const Standard_Boolean isConsiderPointOnEdge,
1077 const Standard_Boolean isSkipLastEdge,
1078 Bnd_B2d& theLinkBndBox ) const
1080 UpdateBndBox(GetVertex(theLink.FirstNode()).Coord(),
1081 GetVertex(theLink.LastNode()).Coord(), theLinkBndBox);
1083 Standard_Integer aPolyLen = thePolygon.Length();
1084 // Don't check intersection with the last link
1085 if ( isSkipLastEdge )
1088 Standard_Boolean isFrontier =
1089 ( theLink.Movability() == BRepMesh_Frontier );
1091 for ( Standard_Integer aPolyIt = 1; aPolyIt <= aPolyLen; ++aPolyIt )
1093 if ( !theLinkBndBox.IsOut( thePolyBoxes.Value( aPolyIt ) ) )
1095 // intersection is possible...
1096 Standard_Integer aPolyLinkId = Abs( thePolygon( aPolyIt ) );
1097 const BRepMesh_Edge& aPolyLink = GetEdge( aPolyLinkId );
1099 // skip intersections between frontier edges
1100 if ( aPolyLink.Movability() == BRepMesh_Frontier && isFrontier )
1104 BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( theLink, aPolyLink,
1105 isConsiderEndPointTouch, isConsiderPointOnEdge, anIntPnt );
1107 if ( aIntFlag != BRepMesh_GeomTool::NoIntersection )
1108 return Standard_False;
1112 // Ok, no intersection
1113 return Standard_True;
1116 //=======================================================================
1117 //function : addTriangle
1118 //purpose : Add a triangle based on the given oriented edges into mesh
1119 //=======================================================================
1120 void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3],
1121 const Standard_Boolean (&theEdgesOri)[3],
1122 const Standard_Integer (&theNodesId)[3])
1124 for (Standard_Integer i = 0; i < 3; ++i)
1126 const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo(theEdgesId[i]);
1127 if (aPair.Extent() == 2)
1128 // it is forbidden to have more than two triangles connected to the same link
1131 Standard_Integer aNewTriangleId =
1132 myMeshData->AddElement(BRepMesh_Triangle(theEdgesId,
1133 theEdgesOri, BRepMesh_Free));
1135 Standard_Boolean isAdded = myCircles.Bind(
1137 GetVertex( theNodesId[0] ).Coord(),
1138 GetVertex( theNodesId[1] ).Coord(),
1139 GetVertex( theNodesId[2] ).Coord() );
1142 myMeshData->RemoveElement( aNewTriangleId );
1145 //=======================================================================
1146 //function : cleanupPolygon
1147 //purpose : Remove internal triangles from the given polygon
1148 //=======================================================================
1149 void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolygon,
1150 const BRepMesh::SequenceOfBndB2d& thePolyBoxes )
1152 Standard_Integer aPolyLen = thePolygon.Length();
1156 Handle(NCollection_IncAllocator) aAllocator =
1157 new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
1159 BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
1160 BRepMesh::MapOfInteger anIgnoredEdges(10, aAllocator);
1161 BRepMesh::MapOfInteger aPolyVerticesFindMap(10, aAllocator);
1162 BRepMesh::VectorOfInteger aPolyVertices(256, aAllocator);
1163 // Collect boundary vertices of the polygon
1164 for ( Standard_Integer aPolyIt = 1; aPolyIt <= aPolyLen; ++aPolyIt )
1166 Standard_Integer aPolyEdgeInfo = thePolygon( aPolyIt );
1167 Standard_Integer aPolyEdgeId = Abs( aPolyEdgeInfo );
1168 anIgnoredEdges.Add( aPolyEdgeId );
1170 Standard_Boolean isForward = ( aPolyEdgeInfo > 0 );
1171 const BRepMesh_PairOfIndex& aPair =
1172 myMeshData->ElementsConnectedTo( aPolyEdgeId );
1174 Standard_Integer anElemIt = 1;
1175 for ( ; anElemIt <= aPair.Extent(); ++anElemIt )
1177 Standard_Integer anElemId = aPair.Index( anElemIt );
1181 Standard_Integer anEdges[3];
1182 Standard_Boolean anEdgesOri[3];
1183 GetTriangle( anElemId ).Edges(anEdges, anEdgesOri);
1185 Standard_Integer isTriangleFound = Standard_False;
1186 for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
1188 if ( anEdges[anEdgeIt] == aPolyEdgeId &&
1189 anEdgesOri[anEdgeIt] == isForward )
1191 isTriangleFound = Standard_True;
1192 deleteTriangle( anElemId, aLoopEdges );
1197 if ( isTriangleFound )
1201 // Skip a neighbor link to extract unique vertices each time
1204 const BRepMesh_Edge& aPolyEdge = GetEdge( aPolyEdgeId );
1205 Standard_Integer aFirstVertex = aPolyEdge.FirstNode();
1206 Standard_Integer aLastVertex = aPolyEdge.LastNode();
1208 aPolyVerticesFindMap.Add( aFirstVertex );
1209 aPolyVerticesFindMap.Add( aLastVertex );
1211 if ( aPolyEdgeInfo > 0 )
1213 aPolyVertices.Append( aFirstVertex );
1214 aPolyVertices.Append( aLastVertex );
1218 aPolyVertices.Append( aLastVertex );
1219 aPolyVertices.Append( aFirstVertex );
1224 // Make closed sequence
1225 if ( aPolyVertices.First() != aPolyVertices.Last() )
1226 aPolyVertices.Append( aPolyVertices.First() );
1228 BRepMesh::MapOfInteger aSurvivedLinks( anIgnoredEdges );
1230 Standard_Integer aPolyVertIt = 0;
1231 Standard_Integer anUniqueVerticesNum = aPolyVertices.Length() - 1;
1232 for ( ; aPolyVertIt < anUniqueVerticesNum; ++aPolyVertIt )
1234 killTrianglesAroundVertex( aPolyVertices( aPolyVertIt ),
1235 aPolyVertices, aPolyVerticesFindMap, thePolygon,
1236 thePolyBoxes, aSurvivedLinks, aLoopEdges );
1239 BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
1240 for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
1242 const Standard_Integer& aLoopEdgeId = aLoopEdgesIt.Key();
1243 if ( anIgnoredEdges.Contains( aLoopEdgeId ) )
1246 if ( myMeshData->ElementsConnectedTo( aLoopEdgeId ).IsEmpty() )
1247 myMeshData->RemoveLink( aLoopEdgesIt.Key() );
1251 //=======================================================================
1252 //function : killTrianglesAroundVertex
1253 //purpose : Remove all triangles and edges that are placed
1254 // inside the polygon or crossed it.
1255 //=======================================================================
1256 void BRepMesh_Delaun::killTrianglesAroundVertex(
1257 const Standard_Integer theZombieNodeId,
1258 const BRepMesh::VectorOfInteger& thePolyVertices,
1259 const BRepMesh::MapOfInteger& thePolyVerticesFindMap,
1260 const BRepMesh::SequenceOfInteger& thePolygon,
1261 const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
1262 BRepMesh::MapOfInteger& theSurvivedLinks,
1263 BRepMesh::MapOfIntegerInteger& theLoopEdges )
1265 BRepMesh::ListOfInteger::Iterator aNeighborsIt =
1266 myMeshData->LinksConnectedTo( theZombieNodeId );
1268 // Try to infect neighbor nodes
1269 BRepMesh::VectorOfInteger aVictimNodes;
1270 for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
1272 const Standard_Integer& aNeighborLinkId = aNeighborsIt.Value();
1273 if ( theSurvivedLinks.Contains( aNeighborLinkId ) )
1276 const BRepMesh_Edge& aNeighborLink = GetEdge( aNeighborLinkId );
1277 if ( aNeighborLink.Movability() == BRepMesh_Frontier )
1279 // Though, if it lies onto the polygon boundary -
1280 // take its triangles
1282 Standard_Boolean isNotIntersect =
1283 checkIntersection( aNeighborLink, thePolygon,
1284 thePolyBoxes, Standard_False, Standard_True,
1285 Standard_False, aBox );
1287 if ( isNotIntersect )
1290 theSurvivedLinks.Add( aNeighborLinkId );
1296 Standard_Integer anOtherNode = aNeighborLink.FirstNode();
1297 if ( anOtherNode == theZombieNodeId )
1298 anOtherNode = aNeighborLink.LastNode();
1300 // Possible sacrifice
1301 if ( !thePolyVerticesFindMap.Contains( anOtherNode ) )
1303 if ( isVertexInsidePolygon( anOtherNode, thePolyVertices ) )
1306 aVictimNodes.Append( anOtherNode );
1310 // Lucky. But it may intersect the polygon boundary.
1312 killTrianglesOnIntersectingLinks( aNeighborLinkId,
1313 aNeighborLink, anOtherNode, thePolygon,
1314 thePolyBoxes, theSurvivedLinks, theLoopEdges );
1321 // Add link to the survivers to avoid cycling
1322 theSurvivedLinks.Add( aNeighborLinkId );
1323 killLinkTriangles( aNeighborLinkId, theLoopEdges );
1326 // Go and do your job!
1327 BRepMesh::VectorOfInteger::Iterator aVictimIt( aVictimNodes );
1328 for ( ; aVictimIt.More(); aVictimIt.Next() )
1330 killTrianglesAroundVertex( aVictimIt.Value(), thePolyVertices,
1331 thePolyVerticesFindMap, thePolygon, thePolyBoxes,
1332 theSurvivedLinks, theLoopEdges );
1336 //=======================================================================
1337 //function : isVertexInsidePolygon
1338 //purpose : Checks is the given vertex lies inside the polygon
1339 //=======================================================================
1340 Standard_Boolean BRepMesh_Delaun::isVertexInsidePolygon(
1341 const Standard_Integer& theVertexId,
1342 const BRepMesh::VectorOfInteger& thePolygonVertices ) const
1344 Standard_Integer aPolyLen = thePolygonVertices.Length();
1346 return Standard_False;
1349 const gp_XY aCenterPointXY = GetVertex( theVertexId ).Coord();
1351 const BRepMesh_Vertex& aFirstVertex = GetVertex( thePolygonVertices( 0 ) );
1352 gp_Vec2d aPrevVertexDir( aFirstVertex.Coord() - aCenterPointXY );
1353 if ( aPrevVertexDir.SquareMagnitude() < Precision2 )
1354 return Standard_True;
1356 Standard_Real aTotalAng = 0.0;
1357 for ( Standard_Integer aPolyIt = 1; aPolyIt < aPolyLen; ++aPolyIt )
1359 const BRepMesh_Vertex& aPolyVertex = GetVertex( thePolygonVertices( aPolyIt ) );
1361 gp_Vec2d aCurVertexDir( aPolyVertex.Coord() - aCenterPointXY );
1362 if ( aCurVertexDir.SquareMagnitude() < Precision2 )
1363 return Standard_True;
1365 aTotalAng += aCurVertexDir.Angle( aPrevVertexDir );
1366 aPrevVertexDir = aCurVertexDir;
1369 if ( Abs( Angle2PI - aTotalAng ) > Precision::Angular() )
1370 return Standard_False;
1372 return Standard_True;
1375 //=======================================================================
1376 //function : killTrianglesOnIntersectingLinks
1377 //purpose : Checks is the given link crosses the polygon boundary.
1378 // If yes, kills its triangles and checks neighbor links on
1379 // boundary intersection. Does nothing elsewhere.
1380 //=======================================================================
1381 void BRepMesh_Delaun::killTrianglesOnIntersectingLinks(
1382 const Standard_Integer& theLinkToCheckId,
1383 const BRepMesh_Edge& theLinkToCheck,
1384 const Standard_Integer& theEndPoint,
1385 const BRepMesh::SequenceOfInteger& thePolygon,
1386 const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
1387 BRepMesh::MapOfInteger& theSurvivedLinks,
1388 BRepMesh::MapOfIntegerInteger& theLoopEdges )
1390 if ( theSurvivedLinks.Contains( theLinkToCheckId ) )
1394 Standard_Boolean isNotIntersect =
1395 checkIntersection( theLinkToCheck, thePolygon,
1396 thePolyBoxes, Standard_False, Standard_False,
1397 Standard_False, aBox );
1399 theSurvivedLinks.Add( theLinkToCheckId );
1401 if ( isNotIntersect )
1404 killLinkTriangles( theLinkToCheckId, theLoopEdges );
1406 BRepMesh::ListOfInteger::Iterator aNeighborsIt(
1407 myMeshData->LinksConnectedTo(theEndPoint));
1409 for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
1411 const Standard_Integer& aNeighborLinkId = aNeighborsIt.Value();
1412 const BRepMesh_Edge& aNeighborLink = GetEdge( aNeighborLinkId );
1413 Standard_Integer anOtherNode = aNeighborLink.FirstNode();
1414 if ( anOtherNode == theEndPoint )
1415 anOtherNode = aNeighborLink.LastNode();
1417 killTrianglesOnIntersectingLinks( aNeighborLinkId,
1418 aNeighborLink, anOtherNode, thePolygon,
1419 thePolyBoxes, theSurvivedLinks, theLoopEdges );
1423 //=======================================================================
1424 //function : killLinkTriangles
1425 //purpose : Kill triangles bound to the given link.
1426 //=======================================================================
1427 void BRepMesh_Delaun::killLinkTriangles(
1428 const Standard_Integer& theLinkId,
1429 BRepMesh::MapOfIntegerInteger& theLoopEdges )
1431 const BRepMesh_PairOfIndex& aPair =
1432 myMeshData->ElementsConnectedTo( theLinkId );
1434 Standard_Integer anElemNb = aPair.Extent();
1435 for ( Standard_Integer aPairIt = 1; aPairIt <= anElemNb; ++aPairIt )
1437 Standard_Integer anElemId = aPair.FirstIndex();
1441 deleteTriangle( anElemId, theLoopEdges );
1445 //=======================================================================
1446 //function : getOrientedNodes
1447 //purpose : Returns start and end nodes of the given edge in respect to
1449 //=======================================================================
1450 void BRepMesh_Delaun::getOrientedNodes(const BRepMesh_Edge& theEdge,
1451 const Standard_Boolean isForward,
1452 Standard_Integer *theNodes) const
1456 theNodes[0] = theEdge.FirstNode();
1457 theNodes[1] = theEdge.LastNode();
1461 theNodes[0] = theEdge.LastNode();
1462 theNodes[1] = theEdge.FirstNode();
1466 //=======================================================================
1467 //function : processLoop
1468 //purpose : Processes loop within the given polygon formed by range of
1469 // its links specified by start and end link indices.
1470 //=======================================================================
1471 void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom,
1472 const Standard_Integer theLinkTo,
1473 const BRepMesh::SequenceOfInteger& thePolygon,
1474 const BRepMesh::SequenceOfBndB2d& thePolyBoxes)
1476 Standard_Integer aNbOfLinksInLoop = theLinkTo - theLinkFrom - 1;
1477 if ( aNbOfLinksInLoop < 3 )
1480 BRepMesh::SequenceOfInteger aPolygon;
1481 BRepMesh::SequenceOfBndB2d aPolyBoxes;
1482 for ( ; aNbOfLinksInLoop > 0; --aNbOfLinksInLoop )
1484 Standard_Integer aLoopLinkIndex = theLinkFrom + aNbOfLinksInLoop;
1485 aPolygon .Prepend( thePolygon ( aLoopLinkIndex ) );
1486 aPolyBoxes.Prepend( thePolyBoxes( aLoopLinkIndex ) );
1488 meshPolygon( aPolygon, aPolyBoxes );
1491 //=======================================================================
1492 //function : createAndReplacePolygonLink
1493 //purpose : Creates new link based on the given nodes and updates the
1495 //=======================================================================
1496 Standard_Integer BRepMesh_Delaun::createAndReplacePolygonLink(
1497 const Standard_Integer *theNodes,
1498 const gp_Pnt2d *thePnts,
1499 const Standard_Integer theRootIndex,
1500 const ReplaceFlag theReplaceFlag,
1501 BRepMesh::SequenceOfInteger& thePolygon,
1502 BRepMesh::SequenceOfBndB2d& thePolyBoxes )
1504 Standard_Integer aNewEdgeId =
1505 myMeshData->AddLink( BRepMesh_Edge(
1506 theNodes[0], theNodes[1], BRepMesh_Free ) );
1509 UpdateBndBox(thePnts[0].Coord(), thePnts[1].Coord(), aNewBox);
1511 switch ( theReplaceFlag )
1513 case BRepMesh_Delaun::Replace:
1514 thePolygon .SetValue( theRootIndex, aNewEdgeId );
1515 thePolyBoxes.SetValue( theRootIndex, aNewBox );
1518 case BRepMesh_Delaun::InsertAfter:
1519 thePolygon .InsertAfter( theRootIndex, aNewEdgeId );
1520 thePolyBoxes.InsertAfter( theRootIndex, aNewBox );
1523 case BRepMesh_Delaun::InsertBefore:
1524 thePolygon .InsertBefore( theRootIndex, aNewEdgeId );
1525 thePolyBoxes.InsertBefore( theRootIndex, aNewBox );
1532 //=======================================================================
1533 //function : meshPolygon
1535 //=======================================================================
1536 void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon,
1537 BRepMesh::SequenceOfBndB2d& thePolyBoxes,
1538 BRepMesh::HMapOfInteger theSkipped )
1540 // Check is the source polygon elementary
1541 if ( meshElementaryPolygon( thePolygon ) )
1544 // Check and correct boundary edges
1545 Standard_Integer aPolyLen = thePolygon.Length();
1546 const Standard_Real aPolyArea = Abs( polyArea( thePolygon, 1, aPolyLen ) );
1547 const Standard_Real aSmallLoopArea = 0.001 * aPolyArea;
1548 for ( Standard_Integer aPolyIt = 1; aPolyIt < aPolyLen; ++aPolyIt )
1550 Standard_Integer aCurEdgeInfo = thePolygon( aPolyIt );
1551 Standard_Integer aCurEdgeId = Abs( aCurEdgeInfo );
1552 const BRepMesh_Edge* aCurEdge = &GetEdge( aCurEdgeId );
1553 if ( aCurEdge->Movability() != BRepMesh_Frontier )
1556 Standard_Integer aCurNodes[2];
1557 getOrientedNodes( *aCurEdge, aCurEdgeInfo > 0, aCurNodes );
1559 gp_Pnt2d aCurPnts[2] = {
1560 GetVertex(aCurNodes[0]).Coord(),
1561 GetVertex(aCurNodes[1]).Coord()
1564 gp_Vec2d aCurVec( aCurPnts[0], aCurPnts[1] );
1566 // check further links
1567 Standard_Integer aNextPolyIt = aPolyIt + 1;
1568 for ( ; aNextPolyIt <= aPolyLen; ++aNextPolyIt )
1570 Standard_Integer aNextEdgeInfo = thePolygon( aNextPolyIt );
1571 Standard_Integer aNextEdgeId = Abs( aNextEdgeInfo );
1572 const BRepMesh_Edge* aNextEdge = &GetEdge( aNextEdgeId );
1573 if ( aNextEdge->Movability() != BRepMesh_Frontier )
1576 Standard_Integer aNextNodes[2];
1577 getOrientedNodes( *aNextEdge, aNextEdgeInfo > 0, aNextNodes );
1579 gp_Pnt2d aNextPnts[2] = {
1580 GetVertex(aNextNodes[0]).Coord(),
1581 GetVertex(aNextNodes[1]).Coord()
1585 BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge,
1586 Standard_False, Standard_True, anIntPnt );
1588 if ( aIntFlag == BRepMesh_GeomTool::NoIntersection )
1591 Standard_Boolean isRemoveFromFirst = Standard_False;
1592 Standard_Boolean isAddReplacingEdge = Standard_True;
1593 Standard_Integer aIndexToRemoveTo = aNextPolyIt;
1594 if ( aIntFlag == BRepMesh_GeomTool::Cross )
1596 Standard_Real aLoopArea = polyArea( thePolygon, aPolyIt + 1, aNextPolyIt );
1597 gp_Vec2d aVec1( anIntPnt, aCurPnts [1] );
1598 gp_Vec2d aVec2( anIntPnt, aNextPnts[0] );
1600 aLoopArea += ( aVec1 ^ aVec2 ) / 2.;
1601 if ( Abs( aLoopArea ) > aSmallLoopArea )
1603 aNextNodes[1] = aCurNodes[0];
1604 aNextPnts [1] = aCurPnts [0];
1606 aNextEdgeId = Abs( createAndReplacePolygonLink( aNextNodes, aNextPnts,
1607 aNextPolyIt, BRepMesh_Delaun::Replace, thePolygon, thePolyBoxes ) );
1609 processLoop( aPolyIt, aNextPolyIt, thePolygon, thePolyBoxes );
1613 Standard_Real aDist1 = anIntPnt.SquareDistance(aNextPnts[0]);
1614 Standard_Real aDist2 = anIntPnt.SquareDistance(aNextPnts[1]);
1616 // Choose node with lower distance
1617 const Standard_Boolean isCloseToStart = ( aDist1 < aDist2 );
1618 const Standard_Integer aEndPointIndex = isCloseToStart ? 0 : 1;
1619 aCurNodes[1] = aNextNodes[aEndPointIndex];
1620 aCurPnts [1] = aNextPnts [aEndPointIndex];
1622 if ( isCloseToStart )
1625 // In this context only intersections between frontier edges
1626 // are possible. If intersection between edges of different
1627 // types occured - treat this case as invalid (i.e. result
1628 // might not reflect the expectations).
1629 if ( !theSkipped.IsNull() )
1631 Standard_Integer aSkippedLinkIt = aPolyIt;
1632 for ( ; aSkippedLinkIt <= aIndexToRemoveTo; ++aSkippedLinkIt )
1633 theSkipped->Add( Abs( thePolygon( aSkippedLinkIt ) ) );
1636 else if ( aIntFlag == BRepMesh_GeomTool::PointOnSegment )
1638 // Indentify chopping link
1639 Standard_Boolean isFirstChopping = Standard_False;
1640 Standard_Integer aCheckPointIt = 0;
1641 for ( ; aCheckPointIt < 2; ++aCheckPointIt )
1643 gp_Pnt2d& aRefPoint = aCurPnts[aCheckPointIt];
1644 // Check is second link touches the first one
1645 gp_Vec2d aVec1( aRefPoint, aNextPnts[0] );
1646 gp_Vec2d aVec2( aRefPoint, aNextPnts[1] );
1647 if ( Abs( aVec1 ^ aVec2 ) < Precision )
1649 isFirstChopping = Standard_True;
1654 if ( isFirstChopping )
1656 // Split second link
1657 isAddReplacingEdge = Standard_False;
1658 isRemoveFromFirst = ( aCheckPointIt == 0 );
1660 Standard_Integer aSplitLink[3] = {
1662 aCurNodes [aCheckPointIt],
1666 gp_Pnt2d aSplitPnts[3] = {
1668 aCurPnts [aCheckPointIt],
1672 Standard_Integer aSplitLinkIt = 0;
1673 for ( ; aSplitLinkIt < 2; ++aSplitLinkIt )
1675 createAndReplacePolygonLink( &aSplitLink[aSplitLinkIt],
1676 &aSplitPnts[aSplitLinkIt], aNextPolyIt, ( aSplitLinkIt == 0 ) ?
1677 BRepMesh_Delaun::Replace : BRepMesh_Delaun::InsertAfter,
1678 thePolygon, thePolyBoxes );
1681 processLoop( aPolyIt + aCheckPointIt, aIndexToRemoveTo,
1682 thePolygon, thePolyBoxes );
1687 Standard_Integer aSplitLinkNodes[2] = {
1692 gp_Pnt2d aSplitLinkPnts[2] = {
1696 createAndReplacePolygonLink( aSplitLinkNodes, aSplitLinkPnts,
1697 aPolyIt, BRepMesh_Delaun::InsertAfter, thePolygon, thePolyBoxes );
1699 aCurNodes[1] = aNextNodes[1];
1700 aCurPnts [1] = aNextPnts [1];
1703 processLoop( aPolyIt + 1, aIndexToRemoveTo,
1704 thePolygon, thePolyBoxes );
1707 else if ( aIntFlag == BRepMesh_GeomTool::Glued )
1709 if ( aCurNodes[1] == aNextNodes[0] )
1711 aCurNodes[1] = aNextNodes[1];
1712 aCurPnts [1] = aNextPnts [1];
1714 // TODO: Non-adjacent glued links within the polygon
1716 else if ( aIntFlag == BRepMesh_GeomTool::Same )
1718 processLoop( aPolyIt, aNextPolyIt, thePolygon, thePolyBoxes );
1720 isRemoveFromFirst = Standard_True;
1721 isAddReplacingEdge = Standard_False;
1724 continue; // Not supported type
1726 if ( isAddReplacingEdge )
1728 aCurEdgeId = Abs( createAndReplacePolygonLink( aCurNodes, aCurPnts,
1729 aPolyIt, BRepMesh_Delaun::Replace, thePolygon, thePolyBoxes ) );
1731 aCurEdge = &GetEdge( aCurEdgeId );
1732 aCurVec = gp_Vec2d( aCurPnts[0], aCurPnts[1] );
1735 Standard_Integer aIndexToRemoveFrom =
1736 isRemoveFromFirst ? aPolyIt : aPolyIt + 1;
1738 thePolygon .Remove( aIndexToRemoveFrom, aIndexToRemoveTo );
1739 thePolyBoxes.Remove( aIndexToRemoveFrom, aIndexToRemoveTo );
1741 aPolyLen = thePolygon.Length();
1742 if ( isRemoveFromFirst )
1748 aNextPolyIt = aPolyIt;
1752 BRepMesh::SequenceOfInteger* aPolygon1 = &thePolygon;
1753 BRepMesh::SequenceOfBndB2d* aPolyBoxes1 = &thePolyBoxes;
1755 BRepMesh::HSequenceOfInteger aPolygon2 = new BRepMesh::SequenceOfInteger;
1756 BRepMesh::HSequenceOfBndB2d aPolyBoxes2 = new BRepMesh::SequenceOfBndB2d;
1758 NCollection_Sequence<BRepMesh::HSequenceOfInteger> aPolyStack;
1759 NCollection_Sequence<BRepMesh::HSequenceOfBndB2d> aPolyBoxStack;
1762 decomposeSimplePolygon(*aPolygon1, *aPolyBoxes1, *aPolygon2, *aPolyBoxes2);
1763 if (!aPolygon2->IsEmpty())
1765 aPolyStack.Append(aPolygon2);
1766 aPolyBoxStack.Append(aPolyBoxes2);
1768 aPolygon2 = new BRepMesh::SequenceOfInteger;
1769 aPolyBoxes2 = new BRepMesh::SequenceOfBndB2d;
1772 if (aPolygon1->IsEmpty())
1774 if (!aPolyStack.IsEmpty() && aPolygon1 == &(*aPolyStack.First()))
1776 aPolyStack.Remove(1);
1777 aPolyBoxStack.Remove(1);
1780 if (aPolyStack.IsEmpty())
1783 aPolygon1 = &(*aPolyStack.ChangeFirst());
1784 aPolyBoxes1 = &(*aPolyBoxStack.ChangeFirst());
1789 //=======================================================================
1790 //function : meshElementaryPolygon
1791 //purpose : Triangulation of closed polygon containing only three edges.
1792 //=======================================================================
1793 inline Standard_Boolean BRepMesh_Delaun::meshElementaryPolygon(
1794 const BRepMesh::SequenceOfInteger& thePolygon)
1796 Standard_Integer aPolyLen = thePolygon.Length();
1798 return Standard_True;
1799 else if ( aPolyLen > 3 )
1800 return Standard_False;
1802 // Just create a triangle
1803 Standard_Integer anEdges[3];
1804 Standard_Boolean anEdgesOri[3];
1806 for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
1808 Standard_Integer anEdgeInfo = thePolygon( anEdgeIt + 1 );
1809 anEdges[anEdgeIt] = Abs( anEdgeInfo );
1810 anEdgesOri[anEdgeIt] = ( anEdgeInfo > 0 );
1813 const BRepMesh_Edge& anEdge1 = GetEdge( anEdges[0] );
1814 const BRepMesh_Edge& anEdge2 = GetEdge( anEdges[1] );
1816 Standard_Integer aNodes[3] = { anEdge1.FirstNode(),
1818 anEdge2.FirstNode() };
1819 if ( aNodes[2] == aNodes[0] ||
1820 aNodes[2] == aNodes[1] )
1822 aNodes[2] = anEdge2.LastNode();
1825 addTriangle( anEdges, anEdgesOri, aNodes );
1826 return Standard_True;
1829 //=======================================================================
1830 //function : meshSimplePolygon
1832 //=======================================================================
1833 void BRepMesh_Delaun::decomposeSimplePolygon(
1834 BRepMesh::SequenceOfInteger& thePolygon,
1835 BRepMesh::SequenceOfBndB2d& thePolyBoxes,
1836 BRepMesh::SequenceOfInteger& thePolygonCut,
1837 BRepMesh::SequenceOfBndB2d& thePolyBoxesCut)
1839 // Check is the given polygon elementary
1840 if ( meshElementaryPolygon( thePolygon ) )
1843 thePolyBoxes.Clear();
1847 // Polygon contains more than 3 links
1848 Standard_Integer aFirstEdgeInfo = thePolygon(1);
1849 const BRepMesh_Edge& aFirstEdge = GetEdge( Abs( aFirstEdgeInfo ) );
1851 Standard_Integer aNodes[3];
1852 getOrientedNodes( aFirstEdge, aFirstEdgeInfo > 0, aNodes );
1854 gp_Pnt2d aRefVertices[3];
1855 aRefVertices[0] = GetVertex( aNodes[0] ).Coord();
1856 aRefVertices[1] = GetVertex( aNodes[1] ).Coord();
1858 gp_Vec2d aRefEdgeDir( aRefVertices[0], aRefVertices[1] );
1860 Standard_Real aRefEdgeLen = aRefEdgeDir.Magnitude();
1861 if ( aRefEdgeLen < Precision )
1864 thePolyBoxes.Clear();
1868 aRefEdgeDir /= aRefEdgeLen;
1870 // Find a point with minimum distance respect
1871 // the end of reference link
1872 Standard_Integer aUsedLinkId = 0;
1873 Standard_Real aOptAngle = 0.0;
1874 Standard_Real aMinDist = RealLast();
1875 Standard_Integer aPivotNode = aNodes[1];
1876 Standard_Integer aPolyLen = thePolygon.Length();
1877 for ( Standard_Integer aLinkIt = 3; aLinkIt <= aPolyLen; ++aLinkIt )
1879 Standard_Integer aLinkInfo = thePolygon( aLinkIt );
1880 const BRepMesh_Edge& aNextEdge = GetEdge( Abs( aLinkInfo ) );
1882 aPivotNode = aLinkInfo > 0 ?
1883 aNextEdge.FirstNode() :
1884 aNextEdge.LastNode();
1886 gp_Pnt2d aPivotVertex = GetVertex( aPivotNode ).Coord();
1887 gp_Vec2d aDistanceDir( aRefVertices[1], aPivotVertex );
1889 Standard_Real aDist = aRefEdgeDir ^ aDistanceDir;
1890 Standard_Real aAngle = Abs( aRefEdgeDir.Angle(aDistanceDir) );
1891 Standard_Real anAbsDist = Abs( aDist );
1892 if (anAbsDist < Precision || aDist < 0.)
1895 if ( ( anAbsDist >= aMinDist ) &&
1896 ( aAngle <= aOptAngle || aAngle > AngDeviation90Deg ) )
1901 // Check is the test link crosses the polygon boudaries
1902 Standard_Boolean isIntersect = Standard_False;
1903 for ( Standard_Integer aRefLinkNodeIt = 0; aRefLinkNodeIt < 2; ++aRefLinkNodeIt )
1905 const Standard_Integer& aLinkFirstNode = aNodes[aRefLinkNodeIt];
1906 const gp_Pnt2d& aLinkFirstVertex = aRefVertices[aRefLinkNodeIt];
1909 UpdateBndBox(aLinkFirstVertex.Coord(), aPivotVertex.Coord(), aBox);
1911 BRepMesh_Edge aCheckLink( aLinkFirstNode, aPivotNode, BRepMesh_Free );
1913 Standard_Integer aCheckLinkIt = 2;
1914 for ( ; aCheckLinkIt <= aPolyLen; ++aCheckLinkIt )
1916 if( aCheckLinkIt == aLinkIt )
1919 if ( !aBox.IsOut( thePolyBoxes.Value( aCheckLinkIt ) ) )
1921 const BRepMesh_Edge& aPolyLink =
1922 GetEdge( Abs( thePolygon( aCheckLinkIt ) ) );
1924 if ( aCheckLink.IsEqual( aPolyLink ) )
1927 // intersection is possible...
1929 BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink,
1930 Standard_False, Standard_False, anIntPnt );
1932 if( aIntFlag != BRepMesh_GeomTool::NoIntersection )
1934 isIntersect = Standard_True;
1949 aMinDist = anAbsDist;
1950 aNodes[2] = aPivotNode;
1951 aRefVertices[2] = aPivotVertex;
1952 aUsedLinkId = aLinkIt;
1955 if ( aUsedLinkId == 0 )
1958 thePolyBoxes.Clear();
1963 BRepMesh_Edge aNewEdges[2] = {
1964 BRepMesh_Edge( aNodes[1], aNodes[2], BRepMesh_Free ),
1965 BRepMesh_Edge( aNodes[2], aNodes[0], BRepMesh_Free ) };
1967 Standard_Integer aNewEdgesInfo[3] = {
1969 myMeshData->AddLink( aNewEdges[0] ),
1970 myMeshData->AddLink( aNewEdges[1] ) };
1973 Standard_Integer anEdges[3];
1974 Standard_Boolean anEdgesOri[3];
1975 for ( Standard_Integer aTriEdgeIt = 0; aTriEdgeIt < 3; ++aTriEdgeIt )
1977 const Standard_Integer& anEdgeInfo = aNewEdgesInfo[aTriEdgeIt];
1978 anEdges[aTriEdgeIt] = Abs( anEdgeInfo );
1979 anEdgesOri[aTriEdgeIt] = anEdgeInfo > 0;
1981 addTriangle( anEdges, anEdgesOri, aNodes );
1983 // Create triangle and split the source polygon on two
1984 // parts (if possible) and mesh each part as independent
1986 if ( aUsedLinkId < aPolyLen )
1988 thePolygon.Split(aUsedLinkId, thePolygonCut);
1989 thePolygonCut.Prepend( -aNewEdgesInfo[2] );
1990 thePolyBoxes.Split(aUsedLinkId, thePolyBoxesCut);
1993 UpdateBndBox(aRefVertices[0].Coord(), aRefVertices[2].Coord(), aBox);
1994 thePolyBoxesCut.Prepend( aBox );
1998 thePolygon.Remove ( aPolyLen );
1999 thePolyBoxes.Remove( aPolyLen );
2002 if ( aUsedLinkId > 3 )
2004 thePolygon.SetValue( 1, -aNewEdgesInfo[1] );
2007 UpdateBndBox(aRefVertices[1].Coord(), aRefVertices[2].Coord(), aBox);
2008 thePolyBoxes.SetValue( 1, aBox );
2012 //=======================================================================
2013 //function : RemoveVertex
2014 //purpose : Removes a vertex from the triangulation
2015 //=======================================================================
2016 void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex )
2018 BRepMesh_SelectorOfDataStructureOfDelaun aSelector( myMeshData );
2019 aSelector.NeighboursOf( theVertex );
2021 BRepMesh::MapOfIntegerInteger aLoopEdges;//( 10, myMeshData->Allocator() );
2023 // Loop on triangles to be destroyed :
2024 BRepMesh::MapOfInteger::Iterator aTriangleIt( aSelector.Elements() );
2025 for ( ; aTriangleIt.More(); aTriangleIt.Next() )
2026 deleteTriangle( aTriangleIt.Key(), aLoopEdges );
2028 BRepMesh::SequenceOfBndB2d aBoxes;
2029 BRepMesh::SequenceOfInteger aPolygon;
2030 Standard_Integer aLoopEdgesCount = aLoopEdges.Extent();
2031 BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
2033 if ( aLoopEdgesIt.More() )
2035 const BRepMesh_Edge& anEdge = GetEdge( aLoopEdgesIt.Key() );
2036 Standard_Integer aFirstNode = anEdge.FirstNode();
2037 Standard_Integer aLastNode;
2038 Standard_Integer aPivotNode = anEdge.LastNode();
2039 Standard_Integer anEdgeId = aLoopEdgesIt.Key();
2041 Standard_Boolean isPositive = (aLoopEdges (anEdgeId) != 0);
2044 Standard_Integer aTmp;
2046 aFirstNode = aPivotNode;
2049 aPolygon.Append( -anEdgeId );
2052 aPolygon.Append( anEdgeId );
2054 fillBndBox( aBoxes, GetVertex( aFirstNode ), GetVertex( aPivotNode ) );
2056 aLoopEdges.UnBind( anEdgeId );
2058 aLastNode = aFirstNode;
2059 while ( aPivotNode != aLastNode )
2061 BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( aPivotNode ) );
2062 for ( ; aLinkIt.More(); aLinkIt.Next() )
2064 if ( aLinkIt.Value() != anEdgeId &&
2065 aLoopEdges.IsBound( aLinkIt.Value() ) )
2067 Standard_Integer aCurrentNode;
2068 anEdgeId = aLinkIt.Value();
2069 const BRepMesh_Edge& anEdge1 = GetEdge( anEdgeId );
2071 aCurrentNode = anEdge1.LastNode();
2072 if ( aCurrentNode != aPivotNode )
2074 aCurrentNode = anEdge1.FirstNode();
2075 aPolygon.Append( -anEdgeId );
2078 aPolygon.Append( anEdgeId );
2080 fillBndBox( aBoxes, GetVertex( aCurrentNode ), GetVertex( aPivotNode ) );
2082 aPivotNode = aCurrentNode;
2083 aLoopEdges.UnBind( anEdgeId );
2088 if ( aLoopEdgesCount <= 0 )
2093 meshPolygon( aPolygon, aBoxes );
2098 //=======================================================================
2099 //function : AddVertices
2100 //purpose : Adds some vertices in the triangulation.
2101 //=======================================================================
2102 void BRepMesh_Delaun::AddVertices(BRepMesh::Array1OfVertexOfDelaun& theVertices)
2104 std::make_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun());
2105 std::sort_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun());
2107 Standard_Integer aLower = theVertices.Lower();
2108 Standard_Integer anUpper = theVertices.Upper();
2110 BRepMesh::Array1OfInteger aVertexIndexes( aLower, anUpper );
2111 for ( Standard_Integer i = aLower; i <= anUpper; ++i )
2112 aVertexIndexes(i) = myMeshData->AddNode( theVertices(i) );
2114 createTrianglesOnNewVertices( aVertexIndexes );
2117 //=======================================================================
2118 //function : UseEdge
2119 //purpose : Modify mesh to use the edge. Return True if done
2120 //=======================================================================
2121 Standard_Boolean BRepMesh_Delaun::UseEdge( const Standard_Integer /*theIndex*/ )
2124 const BRepMesh_PairOfIndex& aPair = myMeshData->ElemConnectedTo( theIndex );
2125 if ( aPair.Extent() == 0 )
2127 const BRepMesh_Edge& anEdge = GetEdge( theIndex );
2129 Standard_Integer aStartNode, aPivotNode, anOtherNode;
2130 aStartNode = anEdge.FirstNode();
2131 aPivotNode = anEdge.LastNode();
2133 const BRepMesh_ListOfInteger& aStartNodeNeighbors = myMeshData->LinkNeighboursOf( aStartNode );
2134 const BRepMesh_ListOfInteger& aPivotNodeNeighbors = myMeshData->LinkNeighboursOf( aPivotNode );
2136 if ( aStartNodeNeighbors.Extent() > 0 &&
2137 aPivotNodeNeighbors.Extent() > 0 )
2139 const BRepMesh_Vertex& aStartVertex = GetVertex( aStartNode );
2140 const BRepMesh_Vertex& aPivotVertex = GetVertex( aPivotNode );
2142 gp_XY aVEdge ( aPivotVertex.Coord() );
2143 aVEdge.Subtract( aStartVertex.Coord() );
2145 Standard_Real anAngle = 0.;
2146 Standard_Real anAngleMin = RealLast();
2147 Standard_Real anAngleMax = RealFirst();
2148 Standard_Integer aLeftEdge = 0, aRightEdge = 0;
2150 BRepMesh_ListOfInteger::Iterator aNeighborIt( aPivotNodeNeighbors );
2151 for ( ; aNeighborIt.More(); aNeighborIt.Next() )
2153 Standard_Integer anEdgeId = aNeighborIt.Value();
2154 if ( anEdgeId != theIndex )
2156 const BRepMesh_Edge& aNextEdge = GetEdge( anEdgeId );
2158 Standard_Boolean isInMesh = Standard_True;
2159 if ( aNextEdge.Movability() == BRepMesh_Free )
2161 if ( myMeshData->ElemConnectedTo( anEdgeId ).IsEmpty() )
2162 isInMesh = Standard_False;
2167 anOtherNode = aNextEdge.FirstNode();
2168 if ( anOtherNode == aPivotNode )
2169 anOtherNode = aNextEdge.LastNode();
2171 gp_XY aVEdgeCur = GetVertex( anOtherNode ).Coord();
2172 aVEdgeCur.Subtract( aPivotVertex.Coord() );
2174 anAngle = gp_Vec2d( aVEdge ).Angle( gp_Vec2d( aVEdgeCur ) );
2177 if ( anAngle > anAngleMax )
2179 anAngleMax = anAngle;
2180 aLeftEdge = anEdgeId;
2182 if ( anAngle < anAngleMin )
2184 anAngleMin = anAngle;
2185 aRightEdge = anEdgeId;
2190 if ( aLeftEdge > 0 )
2192 if (aLeftEdge==aRightEdge)
2202 return Standard_False;
2205 //=======================================================================
2206 //function : getEdgesByType
2207 //purpose : Gives the list of edges with type defined by input parameter
2208 //=======================================================================
2209 BRepMesh::HMapOfInteger BRepMesh_Delaun::getEdgesByType(
2210 const BRepMesh_DegreeOfFreedom theEdgeType ) const
2212 Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
2213 BRepMesh::HMapOfInteger aResult = new BRepMesh::MapOfInteger(1, anAlloc);
2214 BRepMesh::MapOfInteger::Iterator anEdgeIt( myMeshData->LinksOfDomain() );
2216 for ( ; anEdgeIt.More(); anEdgeIt.Next() )
2218 Standard_Integer anEdge = anEdgeIt.Key();
2219 Standard_Boolean isToAdd = (theEdgeType == BRepMesh_Free) ?
2220 (myMeshData->ElementsConnectedTo( anEdge ).Extent() <= 1) :
2221 (GetEdge( anEdge ).Movability() == theEdgeType);
2224 aResult->Add( anEdge );
2230 //=======================================================================
2231 //function : calculateDist
2232 //purpose : Calculates distances between the given point and edges of
2234 //=======================================================================
2235 Standard_Real BRepMesh_Delaun::calculateDist( const gp_XY theVEdges[3],
2236 const gp_XY thePoints[3],
2237 const BRepMesh_Vertex& theVertex,
2238 Standard_Real theDistance[3],
2239 Standard_Real theSqModulus[3],
2240 Standard_Integer& theEdgeOn ) const
2242 Standard_Real aMinDist = RealLast();
2243 for( Standard_Integer i = 0; i < 3; ++i )
2245 theSqModulus[i] = theVEdges[i].SquareModulus();
2246 if ( theSqModulus[i] <= Precision2 )
2249 theDistance[i] = theVEdges[i] ^ ( theVertex.Coord() - thePoints[i] );
2251 Standard_Real aDist = theDistance[i] * theDistance[i];
2252 aDist /= theSqModulus[i];
2254 if ( aDist < aMinDist )
2264 //=======================================================================
2265 //function : Contains
2266 //purpose : Test if triangle of index <TrianIndex> contains geometricaly
2267 // <theVertex>. If <theEdgeOn> is != 0 then theVertex is on Edge
2268 // of index <theEdgeOn>
2269 //=======================================================================
2270 Standard_Boolean BRepMesh_Delaun::Contains( const Standard_Integer theTriangleId,
2271 const BRepMesh_Vertex& theVertex,
2272 const Standard_Real theSqTolerance,
2273 Standard_Integer& theEdgeOn) const
2277 Standard_Integer e[3];
2278 Standard_Boolean o[3];
2279 Standard_Integer p[3];
2281 const BRepMesh_Triangle& aElement = GetTriangle( theTriangleId );
2282 aElement.Edges(e, o);
2284 const BRepMesh_Edge* anEdges[3] = { &GetEdge( e[0] ),
2288 myMeshData->ElementNodes(aElement, p);
2291 aPoints[0] = GetVertex( p[0] ).Coord();
2292 aPoints[1] = GetVertex( p[1] ).Coord();
2293 aPoints[2] = GetVertex( p[2] ).Coord();
2296 aVEdges[0] = aPoints[1];
2297 aVEdges[0].Subtract( aPoints[0] );
2299 aVEdges[1] = aPoints[2];
2300 aVEdges[1].Subtract( aPoints[1] );
2302 aVEdges[2] = aPoints[0];
2303 aVEdges[2].Subtract( aPoints[2] );
2305 Standard_Real aDistance[3];
2306 Standard_Real aSqModulus[3];
2308 Standard_Real aSqMinDist;
2309 Standard_Integer aEdgeOnId;
2310 aSqMinDist = calculateDist( aVEdges, aPoints, theVertex, aDistance, aSqModulus, aEdgeOnId );
2311 if ( aSqMinDist < 0 )
2312 return Standard_False;
2314 const Standard_Boolean isNotFree = (anEdges[aEdgeOnId]->Movability() != BRepMesh_Free);
2315 if ( aSqMinDist > theSqTolerance )
2317 if (isNotFree && aDistance[aEdgeOnId] < ( aSqModulus[aEdgeOnId] / 5. ))
2318 theEdgeOn = e[aEdgeOnId];
2321 return Standard_False;
2323 theEdgeOn = e[aEdgeOnId];
2325 return (aDistance[0] >= 0. && aDistance[1] >= 0. && aDistance[2] >= 0.);
2328 //=============================================================================
2329 //function : intSegSeg
2330 //purpose : Checks intersection between the two segments.
2331 //=============================================================================
2332 BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg(
2333 const BRepMesh_Edge& theEdg1,
2334 const BRepMesh_Edge& theEdg2,
2335 const Standard_Boolean isConsiderEndPointTouch,
2336 const Standard_Boolean isConsiderPointOnEdge,
2337 gp_Pnt2d& theIntPnt) const
2339 gp_XY p1, p2, p3, p4;
2340 p1 = GetVertex( theEdg1.FirstNode() ).Coord();
2341 p2 = GetVertex( theEdg1.LastNode() ).Coord();
2342 p3 = GetVertex( theEdg2.FirstNode() ).Coord();
2343 p4 = GetVertex( theEdg2.LastNode() ).Coord();
2345 return BRepMesh_GeomTool::IntSegSeg(p1, p2, p3, p4,
2346 isConsiderEndPointTouch, isConsiderPointOnEdge, theIntPnt);
2349 //=============================================================================
2350 //function : polyArea
2351 //purpose : Returns area of the loop of the given polygon defined by indices
2352 // of its start and end links.
2353 //=============================================================================
2354 Standard_Real BRepMesh_Delaun::polyArea(const BRepMesh::SequenceOfInteger& thePolygon,
2355 const Standard_Integer theStartIndex,
2356 const Standard_Integer theEndIndex) const
2358 Standard_Real aArea = 0.0;
2359 Standard_Integer aPolyLen = thePolygon.Length();
2360 if ( theStartIndex >= theEndIndex ||
2361 theStartIndex > aPolyLen )
2365 Standard_Integer aCurEdgeInfo = thePolygon( theStartIndex );
2366 Standard_Integer aCurEdgeId = Abs( aCurEdgeInfo );
2367 const BRepMesh_Edge* aCurEdge = &GetEdge( aCurEdgeId );
2369 Standard_Integer aNodes[2];
2370 getOrientedNodes( *aCurEdge, aCurEdgeInfo > 0, aNodes );
2372 gp_Pnt2d aRefPnt = GetVertex( aNodes[0] ).Coord();
2373 Standard_Integer aPolyIt = theStartIndex + 1;
2374 for ( ; aPolyIt <= theEndIndex; ++aPolyIt )
2376 aCurEdgeInfo = thePolygon( aPolyIt );
2377 aCurEdgeId = Abs( aCurEdgeInfo );
2378 aCurEdge = &GetEdge( aCurEdgeId );
2380 getOrientedNodes( *aCurEdge, aCurEdgeInfo > 0, aNodes );
2381 gp_Vec2d aVec1( aRefPnt, GetVertex( aNodes[0] ).Coord() );
2382 gp_Vec2d aVec2( aRefPnt, GetVertex( aNodes[1] ).Coord() );
2384 aArea += aVec1 ^ aVec2;
2391 //=======================================================================
2392 //function : BRepMesh_DumpPoly
2394 //=======================================================================
2395 #include <TopoDS_Compound.hxx>
2396 #include <BRep_Builder.hxx>
2397 #include <Standard_ErrorHandler.hxx>
2398 #include <BRepBuilderAPI_MakeEdge.hxx>
2399 #include <BRepTools.hxx>
2400 Standard_CString BRepMesh_DumpPoly(void* thePolygon,
2401 void* theMeshHandlePtr,
2402 Standard_CString theFileNameStr)
2404 if (thePolygon == 0 || theFileNameStr == 0)
2406 return "Error: file name or polygon data is null";
2409 BRepMesh::SequenceOfInteger& aPolygon = *(BRepMesh::SequenceOfInteger*)thePolygon;
2411 Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
2412 *(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
2414 if (aMeshData.IsNull())
2415 return "Error: mesh data is empty";
2417 TopoDS_Compound aMesh;
2418 BRep_Builder aBuilder;
2419 aBuilder.MakeCompound(aMesh);
2425 BRepMesh::SequenceOfInteger::Iterator aLinksIt(aPolygon);
2426 for (; aLinksIt.More(); aLinksIt.Next())
2428 const BRepMesh_Edge& aLink = aMeshData->GetLink(Abs(aLinksIt.Value()));
2431 for (Standard_Integer i = 0; i < 2; ++i)
2433 const Standard_Integer aNodeId =
2434 (i == 0) ? aLink.FirstNode() : aLink.LastNode();
2436 const gp_XY& aNode = aMeshData->GetNode(aNodeId).Coord();
2437 aPnt[i] = gp_Pnt(aNode.X(), aNode.Y(), 0.);
2440 if (aPnt[0].SquareDistance(aPnt[1]) < Precision::SquareConfusion())
2443 aBuilder.Add(aMesh, BRepBuilderAPI_MakeEdge(aPnt[0], aPnt[1]));
2446 if (!BRepTools::Write(aMesh, theFileNameStr))
2447 return "Error: write failed";
2449 catch (Standard_Failure const& anException)
2451 return anException.GetMessageString();
2454 return theFileNameStr;