using namespace std;
using namespace SMESH::Controls;
-typedef map<const SMDS_MeshNode*, const SMDS_MeshNode*> TNodeNodeMap;
typedef map<const SMDS_MeshElement*, list<const SMDS_MeshNode*> > TElemOfNodeListMap;
typedef map<const SMDS_MeshElement*, list<const SMDS_MeshElement*> > TElemOfElemListMap;
typedef map<const SMDS_MeshNode*, list<const SMDS_MeshNode*> > TNodeOfNodeListMap;
typedef map<const SMDS_MeshElement*, vector<TNodeOfNodeListMapItr> > TElemOfVecOfNnlmiMap;
//typedef map<const SMDS_MeshElement*, vector<TNodeOfNodeVecMapItr> > TElemOfVecOfMapNodesMap;
-typedef pair<const SMDS_MeshNode*, const SMDS_MeshNode*> NLink;
+typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink;
//=======================================================================
//function : SMESH_MeshEditor
}
else {
- // split qudratic quadrangle
+ // split quadratic quadrangle
// get surface elem is on
if ( aShapeId != helper.GetSubShapeID() ) {
}
aMesh->ChangeElementNodes( elem, N, 6 );
- } // qudratic case
+ } // quadratic case
// care of a new element
list<const SMDS_MeshNode*>& nodes = *grIt;
list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
const SMDS_MeshNode* nToKeep = *nIt;
- for ( ; nIt != nodes.end(); nIt++ ) {
+ for ( ++nIt; nIt != nodes.end(); nIt++ ) {
const SMDS_MeshNode* nToRemove = *nIt;
nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep ));
if ( nToRemove != nToKeep ) {
}
//=======================================================================
-//function : findFreeBorder
+//function : FindFreeBorder
//purpose :
//=======================================================================
#define ControlFreeBorder SMESH::Controls::FreeEdges::IsFreeEdge
-static bool findFreeBorder (const SMDS_MeshNode* theFirstNode,
- const SMDS_MeshNode* theSecondNode,
- const SMDS_MeshNode* theLastNode,
- list< const SMDS_MeshNode* > & theNodes,
- list< const SMDS_MeshElement* > & theFaces)
+bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirstNode,
+ const SMDS_MeshNode* theSecondNode,
+ const SMDS_MeshNode* theLastNode,
+ list< const SMDS_MeshNode* > & theNodes,
+ list< const SMDS_MeshElement* >& theFaces)
{
if ( !theFirstNode || !theSecondNode )
return false;
cNL = & contNodes[ contNodes[0].empty() ? 0 : 1 ];
cFL = & contFaces[ contFaces[0].empty() ? 0 : 1 ];
// find one more free border
- if ( ! findFreeBorder( nIgnore, nStart, theLastNode, *cNL, *cFL )) {
+ if ( ! FindFreeBorder( nStart, *nStartIt, theLastNode, *cNL, *cFL )) {
cNL->clear();
cFL->clear();
}
{
list< const SMDS_MeshNode* > nodes;
list< const SMDS_MeshElement* > faces;
- return findFreeBorder( theNode1, theNode2, theNode3, nodes, faces);
+ return FindFreeBorder( theNode1, theNode2, theNode3, nodes, faces);
}
//=======================================================================
// Free border 1
// --------------
- if (!findFreeBorder(theBordFirstNode,theBordSecondNode,theBordLastNode,
+ if (!FindFreeBorder(theBordFirstNode,theBordSecondNode,theBordLastNode,
nSide[0], eSide[0])) {
MESSAGE(" Free Border 1 not found " );
aResult = SEW_BORDER1_NOT_FOUND;
if (theSideIsFreeBorder) {
// Free border 2
// --------------
- if (!findFreeBorder(theSideFirstNode, theSideSecondNode, theSideThirdNode,
+ if (!FindFreeBorder(theSideFirstNode, theSideSecondNode, theSideThirdNode,
nSide[1], eSide[1])) {
MESSAGE(" Free Border 2 not found " );
aResult = ( aResult != SEW_OK ? SEW_BOTH_BORDERS_NOT_FOUND : SEW_BORDER2_NOT_FOUND );
checkedLinkIDs.clear();
gp_XYZ prevXYZ( prevSideNode->X(), prevSideNode->Y(), prevSideNode->Z() );
- SMDS_ElemIteratorPtr invElemIt
- = prevSideNode->GetInverseElementIterator();
- while ( invElemIt->more() ) { // loop on inverse elements on the Side 2
+ // loop on inverse elements of current node (prevSideNode) on the Side 2
+ SMDS_ElemIteratorPtr invElemIt = prevSideNode->GetInverseElementIterator();
+ while ( invElemIt->more() )
+ {
const SMDS_MeshElement* elem = invElemIt->next();
- // prepare data for a loop on links, of a face or a volume
+ // prepare data for a loop on links coming to prevSideNode, of a face or a volume
int iPrevNode, iNode = 0, nbNodes = elem->NbNodes();
const SMDS_MeshNode* faceNodes[ nbNodes ];
bool isVolume = volume.Set( elem );
long iLink = aLinkID_Gen.GetLinkID( prevSideNode, n );
bool isJustChecked = !checkedLinkIDs.insert( iLink ).second;
if (!isJustChecked &&
- foundSideLinkIDs.find( iLink ) == foundSideLinkIDs.end() ) {
+ foundSideLinkIDs.find( iLink ) == foundSideLinkIDs.end() )
+ {
// test a link geometrically
gp_XYZ nextXYZ ( n->X(), n->Y(), n->Z() );
bool linkIsBetter = false;
// find the next border link to compare with
gp_XYZ sidePos( sideNode->X(), sideNode->Y(), sideNode->Z() );
searchByDir = ( bordDir * ( sidePos - bordPos ) <= 0 );
+ // move to next border node if sideNode is before forward border node (bordPos)
while ( *nBordIt != theBordLastNode && !searchByDir ) {
prevBordNode = *nBordIt;
nBordIt++;
set< long > linkIdSet; // links to process
linkIdSet.insert( aLinkID_Gen.GetLinkID( theFirstNode1, theSecondNode1 ));
- typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > TPairOfNodes;
- list< TPairOfNodes > linkList[2];
- linkList[0].push_back( TPairOfNodes( theFirstNode1, theSecondNode1 ));
- linkList[1].push_back( TPairOfNodes( theFirstNode2, theSecondNode2 ));
+ typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink;
+ list< NLink > linkList[2];
+ linkList[0].push_back( NLink( theFirstNode1, theSecondNode1 ));
+ linkList[1].push_back( NLink( theFirstNode2, theSecondNode2 ));
// loop on links in linkList; find faces by links and append links
// of the found faces to linkList
- list< TPairOfNodes >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
+ list< NLink >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ ) {
- TPairOfNodes link[] = { *linkIt[0], *linkIt[1] };
+ NLink link[] = { *linkIt[0], *linkIt[1] };
long linkID = aLinkID_Gen.GetLinkID( link[0].first, link[0].second );
if ( linkIdSet.find( linkID ) == linkIdSet.end() )
continue;
//const SMDS_MeshNode* n2 = nodes[ iNode + 1];
const SMDS_MeshNode* n1 = fnodes1[ iNode ];
const SMDS_MeshNode* n2 = fnodes1[ iNode + 1];
- linkList[0].push_back ( TPairOfNodes( n1, n2 ));
- linkList[1].push_back ( TPairOfNodes( nReplaceMap[n1], nReplaceMap[n2] ));
+ linkList[0].push_back ( NLink( n1, n2 ));
+ linkList[1].push_back ( NLink( nReplaceMap[n1], nReplaceMap[n2] ));
}
}
} // 2 faces found
return aResult;
}
+
+/*!
+ * \brief A sorted pair of nodes
+ */
+struct TLink: public NLink
+{
+ TLink(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2 ):NLink( n1, n2 )
+ { if ( n1 < n2 ) std::swap( first, second ); }
+ TLink(const NLink& link ):NLink( link )
+ { if ( first < second ) std::swap( first, second ); }
+};
+
+//================================================================================
+ /*!
+ * \brief Find corresponding nodes in two sets of faces
+ * \param theSide1 - first face set
+ * \param theSide2 - second first face
+ * \param theFirstNode1 - a boundary node of set 1
+ * \param theFirstNode2 - a node of set 2 corresponding to theFirstNode1
+ * \param theSecondNode1 - a boundary node of set 1 linked with theFirstNode1
+ * \param theSecondNode2 - a node of set 2 corresponding to theSecondNode1
+ * \param nReplaceMap - output map of corresponding nodes
+ * \retval bool - is a success or not
+ */
+//================================================================================
+
+//#define DEBUG_MATCHING_NODES
+
+SMESH_MeshEditor::Sew_Error
+SMESH_MeshEditor::FindMatchingNodes(set<const SMDS_MeshElement*>& theSide1,
+ set<const SMDS_MeshElement*>& theSide2,
+ const SMDS_MeshNode* theFirstNode1,
+ const SMDS_MeshNode* theFirstNode2,
+ const SMDS_MeshNode* theSecondNode1,
+ const SMDS_MeshNode* theSecondNode2,
+ TNodeNodeMap & nReplaceMap)
+{
+ set<const SMDS_MeshElement*> * faceSetPtr[] = { &theSide1, &theSide2 };
+
+ nReplaceMap.clear();
+ if ( theFirstNode1 != theFirstNode2 )
+ nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
+ if ( theSecondNode1 != theSecondNode2 )
+ nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));
+
+ set< TLink > linkSet; // set of nodes where order of nodes is ignored
+ linkSet.insert( TLink( theFirstNode1, theSecondNode1 ));
+
+ list< NLink > linkList[2];
+ linkList[0].push_back( NLink( theFirstNode1, theSecondNode1 ));
+ linkList[1].push_back( NLink( theFirstNode2, theSecondNode2 ));
+
+ // loop on links in linkList; find faces by links and append links
+ // of the found faces to linkList
+ list< NLink >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
+ for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ ) {
+ NLink link[] = { *linkIt[0], *linkIt[1] };
+ if ( linkSet.find( link[0] ) == linkSet.end() )
+ continue;
+
+ // by links, find faces in the face sets,
+ // and find indices of link nodes in the found faces;
+ // in a face set, there is only one or no face sharing a link
+ // ---------------------------------------------------------------
+
+ const SMDS_MeshElement* face[] = { 0, 0 };
+ list<const SMDS_MeshNode*> notLinkNodes[2];
+ //bool reverse[] = { false, false }; // order of notLinkNodes
+ int nbNodes[2];
+ for ( int iSide = 0; iSide < 2; iSide++ ) // loop on 2 sides
+ {
+ const SMDS_MeshNode* n1 = link[iSide].first;
+ const SMDS_MeshNode* n2 = link[iSide].second;
+ set<const SMDS_MeshElement*> * faceSet = faceSetPtr[ iSide ];
+ set< const SMDS_MeshElement* > facesOfNode1;
+ for ( int iNode = 0; iNode < 2; iNode++ ) // loop on 2 nodes of a link
+ {
+ // during a loop of the first node, we find all faces around n1,
+ // during a loop of the second node, we find one face sharing both n1 and n2
+ const SMDS_MeshNode* n = iNode ? n1 : n2; // a node of a link
+ SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator();
+ while ( fIt->more() ) { // loop on faces sharing a node
+ const SMDS_MeshElement* f = fIt->next();
+ if (f->GetType() == SMDSAbs_Face &&
+ faceSet->find( f ) != faceSet->end() && // f is in face set
+ ! facesOfNode1.insert( f ).second ) // f encounters twice
+ {
+ if ( face[ iSide ] ) {
+ MESSAGE( "2 faces per link " );
+ return ( iSide ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
+ }
+ face[ iSide ] = f;
+ faceSet->erase( f );
+
+ // get not link nodes
+ int nbN = f->NbNodes();
+ if ( f->IsQuadratic() )
+ nbN /= 2;
+ nbNodes[ iSide ] = nbN;
+ list< const SMDS_MeshNode* > & nodes = notLinkNodes[ iSide ];
+ int i1 = f->GetNodeIndex( n1 );
+ int i2 = f->GetNodeIndex( n2 );
+ int iEnd = nbN, iBeg = -1, iDelta = 1;
+ bool reverse = ( Abs( i1 - i2 ) == 1 ? i1 > i2 : i2 > i1 );
+ if ( reverse ) {
+ std::swap( iEnd, iBeg ); iDelta = -1;
+ }
+ int i = i2;
+ while ( true ) {
+ i += iDelta;
+ if ( i == iEnd ) i = iBeg + iDelta;
+ if ( i == i1 ) break;
+ nodes.push_back ( f->GetNode( i ) );
+ }
+ }
+ }
+ }
+ }
+ // check similarity of elements of the sides
+ if (( face[0] && !face[1] ) || ( !face[0] && face[1] )) {
+ MESSAGE("Correspondent face not found on side " << ( face[0] ? 1 : 0 ));
+ if ( nReplaceMap.size() == 2 ) { // faces on input nodes not found
+ return ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
+ }
+ else {
+ return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
+ }
+ }
+
+ // set nodes to merge
+ // -------------------
+
+ if ( face[0] && face[1] ) {
+ if ( nbNodes[0] != nbNodes[1] ) {
+ MESSAGE("Diff nb of face nodes");
+ return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
+ }
+#ifdef DEBUG_MATCHING_NODES
+ cout << " Link 1: " << link[0].first->GetID() <<" "<< link[0].second->GetID()
+ << " F 1: " << face[0];
+ cout << "| Link 2: " << link[1].first->GetID() <<" "<< link[1].second->GetID()
+ << " F 2: " << face[1] << " | Bind: "<<endl ;
+#endif
+ int nbN = nbNodes[0];
+ {
+ list<const SMDS_MeshNode*>::iterator n1 = notLinkNodes[0].begin();
+ list<const SMDS_MeshNode*>::iterator n2 = notLinkNodes[1].begin();
+ for ( int i = 0 ; i < nbN - 2; ++i ) {
+#ifdef DEBUG_MATCHING_NODES
+ cout << (*n1)->GetID() << " to " << (*n2)->GetID() << endl;
+#endif
+ nReplaceMap.insert( make_pair( *(n1++), *(n2++) ));
+ }
+ }
+
+ // add other links of the face 1 to linkList
+ // -----------------------------------------
+
+ const SMDS_MeshElement* f0 = face[0];
+ const SMDS_MeshNode* n1 = f0->GetNode( nbN - 1 );
+ for ( int i = 0; i < nbN; i++ )
+ {
+ const SMDS_MeshNode* n2 = f0->GetNode( i );
+ pair< set< TLink >::iterator, bool > iter_isnew =
+ linkSet.insert( TLink( n1, n2 ));
+ if ( !iter_isnew.second ) { // already in a set: no need to process
+ linkSet.erase( iter_isnew.first );
+ }
+ else // new in set == encountered for the first time: add
+ {
+#ifdef DEBUG_MATCHING_NODES
+ cout << "Add link 1: " << n1->GetID() << " " << n2->GetID() << " ";
+ cout << " | link 2: " << nReplaceMap[n1]->GetID() << " " << nReplaceMap[n2]->GetID() << " " << endl;
+#endif
+ linkList[0].push_back ( NLink( n1, n2 ));
+ linkList[1].push_back ( NLink( nReplaceMap[n1], nReplaceMap[n2] ));
+ }
+ n1 = n2;
+ }
+ } // 2 faces found
+ } // loop on link lists
+
+ return SEW_OK;
+}