-// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
EdgeLoop() : SMDS_PolygonalFaceOfNodes( std::vector<const SMDS_MeshNode *>() ) {}
void Clear() { myLinks.clear(); myIsBndConnected = false; myHasPending = false; }
bool SetConnected() { bool was = myIsBndConnected; myIsBndConnected = true; return !was; }
- bool Contains( const SMDS_MeshNode* n ) const
+ size_t Contains( const SMDS_MeshNode* n ) const
{
for ( size_t i = 0; i < myLinks.size(); ++i )
- if ( myLinks[i]->myNode1 == n ) return true;
- return false;
+ if ( myLinks[i]->myNode1 == n ) return i + 1;
+ return 0;
}
virtual int NbNodes() const { return myLinks.size(); }
virtual SMDS_ElemIteratorPtr nodesIterator() const
myLoopOfEdge[ Index( *loop->myLinks[ iE ] )] = 0;
loop->Clear();
}
+ void Join( EdgeLoop& loop1, size_t iAfterConcact,
+ EdgeLoop& loop2, size_t iFromEdge2 )
+ {
+ std::vector< const EdgePart* > linksAfterContact( loop1.myLinks.begin() + iAfterConcact,
+ loop1.myLinks.end() );
+ loop1.myLinks.reserve( loop2.myLinks.size() + loop1.myLinks.size() );
+ loop1.myLinks.resize( iAfterConcact );
+ loop1.myLinks.insert( loop1.myLinks.end(),
+ loop2.myLinks.begin() + iFromEdge2, loop2.myLinks.end() );
+ loop1.myLinks.insert( loop1.myLinks.end(),
+ loop2.myLinks.begin(), loop2.myLinks.begin() + iFromEdge2 );
+ loop1.myLinks.insert( loop1.myLinks.end(),
+ linksAfterContact.begin(), linksAfterContact.end() );
+ loop1.myIsBndConnected = loop2.myIsBndConnected;
+ loop2.Clear();
+ for ( size_t iE = 0; iE < loop1.myLinks.size(); ++iE )
+ myLoopOfEdge[ Index( *loop1.myLinks[ iE ] )] = & loop1;
+ }
size_t Index( const EdgePart& edge ) const { return &edge - myEdge0; }
EdgeLoop* GetLoopOf( const EdgePart* edge ) { return myLoopOfEdge[ Index( *edge )]; }
};
const double theSign,
const bool theOptimize );
- //! Cut a face by planes, whose normals point to parts to keep
- bool CutByPlanes(const SMDS_MeshElement* face,
- const std::vector< gp_Ax1 > & planes,
- std::vector< SMESH_NodeXYZ > & newConnectivity );
+ void IntersectNewEdges( const CutFace& theCFace );
private:
bool & isCollinear );
bool intersectEdgeEdge( int iE1, int iE2, IntPoint2D& intPoint );
bool isPointInTriangle( const gp_XYZ& p, const std::vector< SMESH_NodeXYZ >& nodes );
- void intersectNewEdges( const CutFace& theCFace );
const SMDS_MeshNode* createNode( const gp_XYZ& p );
};
*/
//================================================================================
- void Intersector::Algo::intersectNewEdges( const CutFace& cf )
+ void Intersector::Algo::IntersectNewEdges( const CutFace& cf )
{
IntPoint2D intPoint;
}
}
if ( cf.myLinks.size() >= limit )
- throw SALOME_Exception( "Infinite loop in Intersector::Algo::intersectNewEdges()" );
+ throw SALOME_Exception( "Infinite loop in Intersector::Algo::IntersectNewEdges()" );
}
++i1; // each internal edge encounters twice
}
{
const CutFace& cf = *cutFacesIt;
cf.ReplaceNodes( myRemove2KeepNodes );
- intersectNewEdges( cf );
+ IntersectNewEdges( cf );
}
// make new faces
// avoid loops that are not connected to boundary edges of cf.myInitFace
if ( cf.RemoveInternalLoops( loopSet ))
{
- intersectNewEdges( cf );
+ IntersectNewEdges( cf );
cf.MakeLoops( loopSet, normal );
}
// erase loops that are cut off by face intersections
theNewFaceConnectivity.push_back( facePoints );
break;
}
+
+ // intersect cut lines
+ algo.IntersectNewEdges( cf );
+
// form loops of new faces
EdgeLoopSet loopSet;
cf.MakeLoops( loopSet, normals[ faceToCut->GetID() ]);
// if ( !myLinks[i].IsInternal() )
// myLinks[ i ].myFace = cutterFace;
// else
- myLinks[ i ].ReplaceCoplanar( newEdge );
- myLinks[ i+1 ].ReplaceCoplanar( newEdge );
+ myLinks[ i ].ReplaceCoplanar( newEdge );
+ if ( myLinks[i].IsInternal() && i+1 < myLinks.size() )
+ myLinks[ i+1 ].ReplaceCoplanar( newEdge );
return;
}
i += myLinks[i].IsInternal();
//================================================================================
/*!
* \brief Remove loops that are not connected to boundary edges of myFace by
- * adding edges connecting these loops to the boundary
+ * adding edges connecting these loops to the boundary.
+ * Such loops must be removed as they form polygons with ring topology.
*/
//================================================================================
while ( prevNbReached < nbReachedLoops );
- // add links connecting internal loops with the boundary ones
for ( size_t iL = 0; iL < theLoops.myNbLoops; ++iL )
{
EdgeLoop& loop = theLoops.myLoops[ iL ];
- if ( loop.myIsBndConnected )
+ if ( loop.myIsBndConnected || loop.myLinks.size() == 0 )
continue;
+ if ( loop.myHasPending )
+ {
+ // try to join the loop to another one, with which it contacts at a node
+
+ // look for a node where the loop reverses
+ const EdgePart* edgePrev = loop.myLinks.back();
+ for ( size_t iE = 0; iE < loop.myLinks.size(); edgePrev = loop.myLinks[ iE++ ] )
+ {
+ if ( !edgePrev->IsTwin( *loop.myLinks[ iE ]))
+ continue;
+ const SMDS_MeshNode* reverseNode = edgePrev->myNode2;
+
+ // look for a loop including reverseNode
+ size_t iContactEdge2; // index(+1) of edge starting at reverseNode
+ for ( size_t iL2 = 0; iL2 < theLoops.myNbLoops; ++iL2 )
+ {
+ if ( iL == iL2 )
+ continue;
+ EdgeLoop& loop2 = theLoops.myLoops[ iL2 ];
+ if ( ! ( iContactEdge2 = loop2.Contains( reverseNode )))
+ continue;
+
+ // insert loop2 into the loop
+ theLoops.Join( loop, iE, loop2, iContactEdge2 - 1 );
+ break;
+ }
+ if ( loop.myIsBndConnected )
+ break;
+ }
+
+ if ( loop.myIsBndConnected )
+ continue;
+ }
+
+ // add links connecting internal loops with the boundary ones
+
// find a pair of closest nodes
const SMDS_MeshNode *closestNode1, *closestNode2;
double minDist = 1e100;
while ( !theLoops.AllEdgesUsed() )
{
- theLoops.AddNewLoop();
+ EdgeLoop& loop = theLoops.AddNewLoop();
// add 1st edge to a new loop
size_t i1;
// choose among candidates
if ( theLoops.myCandidates.size() == 0 )
{
- theLoops.GetLoopOf( lastEdge )->myHasPending = true;
+ loop.myHasPending = bool( twinEdge );
lastEdge = twinEdge;
}
else if ( theLoops.myCandidates.size() == 1 )
}
while ( lastNode != firstNode );
+
+ if ( twinEdge == & myLinks[ i1 ])
+ loop.myHasPending = true;
+
} // while ( !theLoops.AllEdgesUsed() )
return;