+ int lastFreeId = myXYZ.size();
+
+ // loop on links of refined elements
+ indListIt = myIdsOnBoundary.begin();
+ for ( ; indListIt != myIdsOnBoundary.end(); indListIt++ )
+ {
+ const TNodeSet & linkNodes = indListIt->first;
+ if ( linkNodes.size() != 2 )
+ continue; // skip face
+ const SMDS_MeshNode* n1 = * linkNodes.begin();
+ const SMDS_MeshNode* n2 = * linkNodes.rbegin();
+
+ list<list< int > >& idGroups = indListIt->second; // ids of nodes to build
+ if ( idGroups.empty() || idGroups.front().empty() )
+ continue;
+
+ // find not refined face having n1-n2 link
+
+ while (true)
+ {
+ const SMDS_MeshElement* face =
+ SMESH_MeshAlgos::FindFaceInSet( n1, n2, elemSet, avoidSet );
+ if ( face )
+ {
+ avoidSet.insert ( face );
+ myPolyElems.push_back( face );
+
+ // some links of <face> are split;
+ // make list of xyz for <face>
+ myPolyElemXYZIDs.push_back(TElemDef());
+ TElemDef & faceNodeIds = myPolyElemXYZIDs.back();
+ // loop on links of a <face>
+ SMDS_ElemIteratorPtr nIt = face->nodesIterator();
+ int i = 0, nbNodes = face->NbNodes();
+ vector<const SMDS_MeshNode*> nodes( nbNodes + 1 );
+ while ( nIt->more() )
+ nodes[ i++ ] = smdsNode( nIt->next() );
+ nodes[ i ] = nodes[ 0 ];
+ for ( i = 0; i < nbNodes; ++i )
+ {
+ // look for point mapped on a link
+ TNodeSet faceLinkNodes;
+ faceLinkNodes.insert( nodes[ i ] );
+ faceLinkNodes.insert( nodes[ i + 1 ] );
+ if ( faceLinkNodes == linkNodes )
+ nn_IdList = indListIt;
+ else
+ nn_IdList = myIdsOnBoundary.find( faceLinkNodes );
+ // add face point ids
+ faceNodeIds.push_back( ++lastFreeId );
+ myXYZIdToNodeMap.insert( make_pair( lastFreeId, nodes[ i ]));
+ if ( nn_IdList != myIdsOnBoundary.end() )
+ {
+ // there are points mapped on a link
+ list< int >& mappedIds = nn_IdList->second.front();
+ if ( isReversed( nodes[ i ], mappedIds ))
+ faceNodeIds.insert (faceNodeIds.end(),mappedIds.rbegin(), mappedIds.rend() );
+ else
+ faceNodeIds.insert (faceNodeIds.end(),mappedIds.begin(), mappedIds.end() );
+ }
+ } // loop on links of a <face>
+ } // if ( face )
+ else
+ break;
+ } // while (true)
+
+ if ( myIs2D && idGroups.size() > 1 ) {
+
+ // sew new elements on 2 refined elements sharing n1-n2 link
+
+ list< int >& idsOnLink = idGroups.front();
+ // temporarily add ids of link nodes to idsOnLink
+ bool rev = isReversed( n1, idsOnLink );
+ for ( int i = 0; i < 2; ++i )
+ {
+ TNodeSet nodeSet;
+ nodeSet.insert( i ? n2 : n1 );
+ ASSERT( myIdsOnBoundary.find( nodeSet ) != myIdsOnBoundary.end() );
+ list<list< int > >& groups = myIdsOnBoundary[ nodeSet ];
+ int nodeId = groups.front().front();
+ bool append = i;
+ if ( rev ) append = !append;
+ if ( append )
+ idsOnLink.push_back( nodeId );
+ else
+ idsOnLink.push_front( nodeId );
+ }
+ list< int >::iterator id = idsOnLink.begin();
+ for ( ; id != idsOnLink.end(); ++id ) // loop on XYZ ids on a link
+ {
+ list< TElemDef* >& elemDefs = myReverseConnectivity[ *id ]; // elems sharing id
+ list< TElemDef* >::iterator pElemDef = elemDefs.begin();
+ for ( ; pElemDef != elemDefs.end(); pElemDef++ ) // loop on elements sharing id
+ {
+ TElemDef* pIdList = *pElemDef; // ptr on list of ids making element up
+ // look for <id> in element definition
+ TElemDef::iterator idDef = find( pIdList->begin(), pIdList->end(), *id );
+ ASSERT ( idDef != pIdList->end() );
+ // look for 2 neighbour ids of <id> in element definition
+ for ( int prev = 0; prev < 2; ++prev ) {
+ TElemDef::iterator idDef2 = idDef;
+ if ( prev )
+ idDef2 = ( idDef2 == pIdList->begin() ) ? --pIdList->end() : --idDef2;
+ else
+ idDef2 = ( ++idDef2 == pIdList->end() ) ? pIdList->begin() : idDef2;
+ // look for idDef2 on a link starting from id
+ list< int >::iterator id2 = find( id, idsOnLink.end(), *idDef2 );
+ if ( id2 != idsOnLink.end() && id != --id2 ) { // found not next to id
+ // insert ids located on link between <id> and <id2>
+ // into the element definition between idDef and idDef2
+ if ( prev )
+ for ( ; id2 != id; --id2 )
+ pIdList->insert( idDef, *id2 );
+ else {
+ list< int >::iterator id1 = id;
+ for ( ++id1, ++id2; id1 != id2; ++id1 )
+ pIdList->insert( idDef2, *id1 );
+ }
+ }
+ }
+ }
+ }
+ // remove ids of link nodes
+ idsOnLink.pop_front();
+ idsOnLink.pop_back();
+ }
+ } // loop on myIdsOnBoundary
+ } // if ( toCreatePolygons )
+
+ if ( toCreatePolyedrs )
+ {
+ // check volumes adjacent to the refined elements
+ SMDS_VolumeTool volTool;
+ vector<const SMDS_MeshElement*>::iterator refinedElem = myElements.begin();
+ for ( ; refinedElem != myElements.end(); ++refinedElem )
+ {
+ // loop on nodes of refinedElem
+ SMDS_ElemIteratorPtr nIt = (*refinedElem)->nodesIterator();
+ while ( nIt->more() ) {
+ const SMDS_MeshNode* node = smdsNode( nIt->next() );
+ // loop on inverse elements of node
+ SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator();
+ while ( eIt->more() )
+ {
+ const SMDS_MeshElement* elem = eIt->next();
+ if ( !volTool.Set( elem ) || !avoidSet.insert( elem ).second )
+ continue; // skip faces or refined elements
+ // add polyhedron definition
+ myPolyhedronQuantities.push_back(vector<int> ());
+ myPolyElemXYZIDs.push_back(TElemDef());
+ vector<int>& quantity = myPolyhedronQuantities.back();
+ TElemDef & elemDef = myPolyElemXYZIDs.back();
+ // get definitions of new elements on volume faces
+ bool makePoly = false;
+ for ( int iF = 0; iF < volTool.NbFaces(); ++iF )
+ {
+ if ( getFacesDefinition(volTool.GetFaceNodes( iF ),
+ volTool.NbFaceNodes( iF ),
+ theNodes, elemDef, quantity))
+ makePoly = true;
+ }
+ if ( makePoly )
+ myPolyElems.push_back( elem );
+ else {
+ myPolyhedronQuantities.pop_back();
+ myPolyElemXYZIDs.pop_back();
+ }
+ }
+ }
+ }
+ }
+}
+
+//=======================================================================
+//function : getFacesDefinition
+//purpose : return faces definition for a volume face defined by theBndNodes
+//=======================================================================
+
+bool SMESH_Pattern::
+ getFacesDefinition(const SMDS_MeshNode** theBndNodes,
+ const int theNbBndNodes,
+ const vector< const SMDS_MeshNode* >& theNodes,
+ list< int >& theFaceDefs,
+ vector<int>& theQuantity)
+{
+ bool makePoly = false;
+
+ set< const SMDS_MeshNode* > bndNodeSet( theBndNodes, theBndNodes + theNbBndNodes);
+
+ map< TNodeSet, list< list< int > > >::iterator nn_IdList;
+
+ // make a set of all nodes on a face
+ set< int > ids;
+ if ( !myIs2D ) { // for 2D, merge only edges
+ nn_IdList = myIdsOnBoundary.find( bndNodeSet );
+ if ( nn_IdList != myIdsOnBoundary.end() ) {
+ list< int > & faceIds = nn_IdList->second.front();
+ if ( !faceIds.empty() ) {
+ makePoly = true;
+ ids.insert( faceIds.begin(), faceIds.end() );
+ }
+ }
+ }
+
+ // add ids on links and bnd nodes
+ int lastFreeId = Max( myXYZIdToNodeMap.rbegin()->first, theNodes.size() );
+ TElemDef faceDef; // definition for the case if there is no new adjacent volumes
+ for ( int iN = 0; iN < theNbBndNodes; ++iN )
+ {
+ // add id of iN-th bnd node
+ TNodeSet nSet;
+ nSet.insert( theBndNodes[ iN ] );
+ nn_IdList = myIdsOnBoundary.find( nSet );
+ int bndId = ++lastFreeId;
+ if ( nn_IdList != myIdsOnBoundary.end() ) {
+ bndId = nn_IdList->second.front().front();
+ ids.insert( bndId );
+ }
+ else {
+ myXYZIdToNodeMap.insert( make_pair( bndId, theBndNodes[ iN ] ));
+ }
+ faceDef.push_back( bndId );
+ // add ids on a link
+ TNodeSet linkNodes;
+ linkNodes.insert( theBndNodes[ iN ]);
+ linkNodes.insert( theBndNodes[ (iN + 1) % theNbBndNodes] );
+ nn_IdList = myIdsOnBoundary.find( linkNodes );
+ if ( nn_IdList != myIdsOnBoundary.end() ) {
+ list< int > & linkIds = nn_IdList->second.front();
+ if ( !linkIds.empty() )
+ {
+ makePoly = true;
+ ids.insert( linkIds.begin(), linkIds.end() );
+ if ( isReversed( theBndNodes[ iN ], linkIds ))
+ faceDef.insert( faceDef.end(), linkIds.begin(), linkIds.end() );
+ else
+ faceDef.insert( faceDef.end(), linkIds.rbegin(), linkIds.rend() );
+ }
+ }
+ }
+
+ // find faces definition of new volumes
+
+ bool defsAdded = false;
+ if ( !myIs2D ) { // for 2D, merge only edges
+ SMDS_VolumeTool vol;
+ set< TElemDef* > checkedVolDefs;
+ set< int >::iterator id = ids.begin();
+ for ( ; id != ids.end(); ++id )
+ {
+ // definitions of volumes sharing id
+ list< TElemDef* >& defList = myReverseConnectivity[ *id ];
+ ASSERT( !defList.empty() );
+ // loop on volume definitions
+ list< TElemDef* >::iterator pIdList = defList.begin();
+ for ( ; pIdList != defList.end(); ++pIdList)
+ {
+ if ( !checkedVolDefs.insert( *pIdList ).second )
+ continue; // skip already checked volume definition
+ vector< int > idVec( (*pIdList)->begin(), (*pIdList)->end() );
+ // loop on face defs of a volume
+ SMDS_VolumeTool::VolumeType volType = vol.GetType( idVec.size() );
+ if ( volType == SMDS_VolumeTool::UNKNOWN )
+ continue;
+ int nbFaces = vol.NbFaces( volType );
+ for ( int iF = 0; iF < nbFaces; ++iF )
+ {
+ const int* nodeInds = vol.GetFaceNodesIndices( volType, iF, true );
+ int iN, nbN = vol.NbFaceNodes( volType, iF );
+ // check if all nodes of a faces are in <ids>
+ bool all = true;
+ for ( iN = 0; iN < nbN && all; ++iN ) {
+ int nodeId = idVec[ nodeInds[ iN ]];
+ all = ( ids.find( nodeId ) != ids.end() );
+ }
+ if ( all ) {
+ // store a face definition
+ for ( iN = 0; iN < nbN; ++iN ) {
+ theFaceDefs.push_back( idVec[ nodeInds[ iN ]]);
+ }
+ theQuantity.push_back( nbN );
+ defsAdded = true;
+ }
+ }
+ }
+ }
+ }
+ if ( !defsAdded ) {
+ theQuantity.push_back( faceDef.size() );
+ theFaceDefs.splice( theFaceDefs.end(), faceDef );
+ }
+
+ return makePoly;
+}
+
+//=======================================================================
+//function : clearSubMesh
+//purpose :
+//=======================================================================
+
+static bool clearSubMesh( SMESH_Mesh* theMesh,
+ const TopoDS_Shape& theShape)
+{
+ bool removed = false;
+ if ( SMESH_subMesh * aSubMesh = theMesh->GetSubMeshContaining( theShape ))
+ {
+ removed = !aSubMesh->IsEmpty();
+ if ( removed )