X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=0dc929c50d3f38f545eff0353d1dec999b4ca8ab;hb=bdfc51bda9296408c0908cf01a6acc23c539dadb;hp=198cf0f2da50310c81b584dadef6b9cf30c9d36e;hpb=2de294b09ac8b9ace071a01db9cb4e235f1eadbb;p=modules%2Fsmesh.git diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 198cf0f2d..0dc929c50 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -135,27 +135,27 @@ SMESH_MeshEditor::AddElement(const vector & node, case SMDSAbs_Face: if ( !isPoly ) { if (nbnode == 3) { - if ( ID >= 0 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID); + if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID); else e = mesh->AddFace (node[0], node[1], node[2] ); } else if (nbnode == 4) { - if ( ID >= 0 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], ID); + if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], ID); else e = mesh->AddFace (node[0], node[1], node[2], node[3] ); } else if (nbnode == 6) { - if ( ID >= 0 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], - node[4], node[5], ID); + if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], + node[4], node[5], ID); else e = mesh->AddFace (node[0], node[1], node[2], node[3], - node[4], node[5] ); + node[4], node[5] ); } else if (nbnode == 8) { - if ( ID >= 0 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], ID); + if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], ID); else e = mesh->AddFace (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7] ); + node[4], node[5], node[6], node[7] ); } } else { - if ( ID >= 0 ) e = mesh->AddPolygonalFaceWithID(node, ID); + if ( ID >= 1 ) e = mesh->AddPolygonalFaceWithID(node, ID); else e = mesh->AddPolygonalFace (node ); } break; @@ -163,90 +163,90 @@ SMESH_MeshEditor::AddElement(const vector & node, case SMDSAbs_Volume: if ( !isPoly ) { if (nbnode == 4) { - if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID); + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID); else e = mesh->AddVolume (node[0], node[1], node[2], node[3] ); } else if (nbnode == 5) { - if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], ID); + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], ID); else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4] ); + node[4] ); } else if (nbnode == 6) { - if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], ID); + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], ID); else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5] ); + node[4], node[5] ); } else if (nbnode == 8) { - if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], ID); + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], ID); else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7] ); + node[4], node[5], node[6], node[7] ); } else if (nbnode == 10) { - if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], ID); + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], ID); else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9] ); + node[4], node[5], node[6], node[7], + node[8], node[9] ); } else if (nbnode == 13) { - if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],ID); + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],ID); else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12] ); + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12] ); } else if (nbnode == 15) { - if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],node[13],node[14],ID); + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],ID); else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],node[13],node[14] ); + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14] ); } else if (nbnode == 20) { - if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],node[13],node[14],node[15], - node[16],node[17],node[18],node[19],ID); + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],node[15], + node[16],node[17],node[18],node[19],ID); else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],node[13],node[14],node[15], - node[16],node[17],node[18],node[19] ); + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],node[15], + node[16],node[17],node[18],node[19] ); } } break; case SMDSAbs_Edge: if ( nbnode == 2 ) { - if ( ID >= 0 ) e = mesh->AddEdgeWithID(node[0], node[1], ID); + if ( ID >= 1 ) e = mesh->AddEdgeWithID(node[0], node[1], ID); else e = mesh->AddEdge (node[0], node[1] ); } else if ( nbnode == 3 ) { - if ( ID >= 0 ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID); + if ( ID >= 1 ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID); else e = mesh->AddEdge (node[0], node[1], node[2] ); } break; case SMDSAbs_0DElement: if ( nbnode == 1 ) { - if ( ID >= 0 ) e = mesh->Add0DElementWithID(node[0], ID); + if ( ID >= 1 ) e = mesh->Add0DElementWithID(node[0], ID); else e = mesh->Add0DElement (node[0] ); } break; case SMDSAbs_Node: - if ( ID >= 0 ) e = mesh->AddNodeWithID(node[0]->X(), node[0]->Y(), node[0]->Z(), ID); + if ( ID >= 1 ) e = mesh->AddNodeWithID(node[0]->X(), node[0]->Y(), node[0]->Z(), ID); else e = mesh->AddNode (node[0]->X(), node[0]->Y(), node[0]->Z()); break; @@ -1563,14 +1563,14 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems, const int theMethodFlags) { // std-like iterator on coordinates of nodes of mesh element - typedef SMDS_StdIterator< TNodeXYZ, SMDS_ElemIteratorPtr > NXyzIterator; + typedef SMDS_StdIterator< SMESH_TNodeXYZ, SMDS_ElemIteratorPtr > NXyzIterator; NXyzIterator xyzEnd; SMDS_VolumeTool volTool; SMESH_MesherHelper helper( *GetMesh()); - SMESHDS_SubMesh* subMesh = GetMeshDS()->MeshElements(1); - SMESHDS_SubMesh* fSubMesh = subMesh; + SMESHDS_SubMesh* subMesh = 0;//GetMeshDS()->MeshElements(1); + SMESHDS_SubMesh* fSubMesh = 0;//subMesh; SMESH_SequenceOfElemPtr newNodes, newElems; @@ -2681,6 +2681,9 @@ void SMESH_MeshEditor::GetLinkedNodes( const SMDS_MeshNode* theNode, while ( elemIt->more() ) { const SMDS_MeshElement* elem = elemIt->next(); + if(elem->GetType() == SMDSAbs_0DElement) + continue; + SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); if ( elem->GetType() == SMDSAbs_Volume ) { @@ -6241,7 +6244,7 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher const SMDS_MeshNode* closestNode = 0; list::iterator nIt = nodes.begin(); for ( ; nIt != nodes.end(); ++nIt ) { - double sqDist = thePnt.SquareDistance( SMESH_MeshEditor::TNodeXYZ( *nIt ) ); + double sqDist = thePnt.SquareDistance( SMESH_TNodeXYZ( *nIt ) ); if ( minSqDist > sqDist ) { closestNode = *nIt; minSqDist = sqDist; @@ -6296,7 +6299,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() { public: - ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, double tolerance = NodeRadius ); + ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt = SMDS_ElemIteratorPtr(), double tolerance = NodeRadius ); void getElementsNearPoint( const gp_Pnt& point, TIDSortedElemSet& foundElems); void getElementsNearLine ( const gp_Ax1& line, TIDSortedElemSet& foundElems); ~ElementBndBoxTree(); @@ -6323,13 +6326,13 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() */ //================================================================================ - ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, double tolerance) + ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt, double tolerance) :SMESH_Octree( new SMESH_Octree::Limit( MaxLevel, /*minSize=*/0. )) { int nbElems = mesh.GetMeshInfo().NbElements( elemType ); _elements.reserve( nbElems ); - SMDS_ElemIteratorPtr elemIt = mesh.elementsIterator( elemType ); + SMDS_ElemIteratorPtr elemIt = theElemIt ? theElemIt : mesh.elementsIterator( elemType ); while ( elemIt->more() ) _elements.push_back( new ElementBox( elemIt->next(),tolerance )); @@ -6461,7 +6464,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() _refCount = 1; SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); while ( nIt->more() ) - Add( SMESH_MeshEditor::TNodeXYZ( cast2Node( nIt->next() ))); + Add( SMESH_TNodeXYZ( cast2Node( nIt->next() ))); Enlarge( tolerance ); } @@ -6477,6 +6480,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher { SMESHDS_Mesh* _mesh; + SMDS_ElemIteratorPtr _meshPartIt; ElementBndBoxTree* _ebbTree; SMESH_NodeSearcherImpl* _nodeSearcher; SMDSAbs_ElementType _elementType; @@ -6484,8 +6488,8 @@ struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher bool _outerFacesFound; set _outerFaces; // empty means "no internal faces at all" - SMESH_ElementSearcherImpl( SMESHDS_Mesh& mesh ) - : _mesh(&mesh),_ebbTree(0),_nodeSearcher(0), _tolerance(-1), _outerFacesFound(false) {} + SMESH_ElementSearcherImpl( SMESHDS_Mesh& mesh, SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr()) + : _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_nodeSearcher(0),_tolerance(-1),_outerFacesFound(false) {} ~SMESH_ElementSearcherImpl() { if ( _ebbTree ) delete _ebbTree; _ebbTree = 0; @@ -6567,7 +6571,7 @@ double SMESH_ElementSearcherImpl::getTolerance() SMDS_NodeIteratorPtr nodeIt = _mesh->nodesIterator(); elemSize = 1; if ( meshInfo.NbNodes() > 2 ) - elemSize = SMESH_MeshEditor::TNodeXYZ( nodeIt->next() ).Distance( nodeIt->next() ); + elemSize = SMESH_TNodeXYZ( nodeIt->next() ).Distance( nodeIt->next() ); } else { @@ -6575,7 +6579,8 @@ double SMESH_ElementSearcherImpl::getTolerance() _mesh->elementsIterator( SMDSAbs_ElementType( complexType )); const SMDS_MeshElement* elem = elemIt->next(); SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); - SMESH_MeshEditor::TNodeXYZ n1( cast2Node( nodeIt->next() )); + SMESH_TNodeXYZ n1( cast2Node( nodeIt->next() )); + elemSize = 0; while ( nodeIt->more() ) { double dist = n1.Distance( cast2Node( nodeIt->next() )); @@ -6608,8 +6613,8 @@ bool SMESH_ElementSearcherImpl::getIntersParamOnLine(const gp_Lin& lin int nbNodes = face->IsQuadratic() ? face->NbNodes()/2 : face->NbNodes(); for ( int i = 0; i < nbNodes && nbInts < 2; ++i ) { - GC_MakeSegment edge( SMESH_MeshEditor::TNodeXYZ( face->GetNode( i )), - SMESH_MeshEditor::TNodeXYZ( face->GetNode( (i+1)%nbNodes) )); + GC_MakeSegment edge( SMESH_TNodeXYZ( face->GetNode( i )), + SMESH_TNodeXYZ( face->GetNode( (i+1)%nbNodes) )); anExtCC.Init( lineCurve, edge); if ( anExtCC.NbExtrema() > 0 && anExtCC.LowerDistance() <= tol) { @@ -6669,8 +6674,8 @@ void SMESH_ElementSearcherImpl::findOuterBoundary(const SMDS_MeshElement* outerF seamLinks.insert( link ); // link direction within the outerFace - gp_Vec n1n2( SMESH_MeshEditor::TNodeXYZ( link.node1()), - SMESH_MeshEditor::TNodeXYZ( link.node2())); + gp_Vec n1n2( SMESH_TNodeXYZ( link.node1()), + SMESH_TNodeXYZ( link.node2())); int i1 = outerFace->GetNodeIndex( link.node1() ); int i2 = outerFace->GetNodeIndex( link.node2() ); bool rev = ( abs(i2-i1) == 1 ? i1 > i2 : i2 > i1 ); @@ -6753,7 +6758,7 @@ FindElementsByPoint(const gp_Pnt& point, const SMDS_MeshNode* closeNode = _nodeSearcher->FindClosestTo( point ); if ( !closeNode ) return foundElements.size(); - if ( point.Distance( SMESH_MeshEditor::TNodeXYZ( closeNode )) > tolerance ) + if ( point.Distance( SMESH_TNodeXYZ( closeNode )) > tolerance ) return foundElements.size(); // to far from any node if ( type == SMDSAbs_Node ) @@ -6773,7 +6778,7 @@ FindElementsByPoint(const gp_Pnt& point, if ( !_ebbTree || _elementType != type ) { if ( _ebbTree ) delete _ebbTree; - _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, tolerance ); + _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt, tolerance ); } TIDSortedElemSet suspectElems; _ebbTree->getElementsNearPoint( point, suspectElems ); @@ -6797,7 +6802,7 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point) if ( !_ebbTree || _elementType != SMDSAbs_Face ) { if ( _ebbTree ) delete _ebbTree; - _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = SMDSAbs_Face ); + _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = SMDSAbs_Face, _meshPartIt ); } // Algo: analyse transition of a line starting at the point through mesh boundary; // try three lines parallel to axis of the coordinate system and perform rough @@ -6825,7 +6830,7 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point) // get face plane gp_XYZ fNorm; if ( !SMESH_Algo::FaceNormal( *face, fNorm, /*normalized=*/false)) continue; - gp_Pln facePlane( SMESH_MeshEditor::TNodeXYZ( (*face)->GetNode(0)), fNorm ); + gp_Pln facePlane( SMESH_TNodeXYZ( (*face)->GetNode(0)), fNorm ); // perform intersection IntAna_IntConicQuad intersection( line, IntAna_Quadric( facePlane )); @@ -7021,7 +7026,7 @@ void SMESH_ElementSearcherImpl::GetElementsNearLine( const gp_Ax1& if ( !_ebbTree || _elementType != type ) { if ( _ebbTree ) delete _ebbTree; - _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type ); + _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt ); } TIDSortedElemSet suspectFaces; // elements possibly intersecting the line _ebbTree->getElementsNearLine( line, suspectFaces ); @@ -7039,6 +7044,17 @@ SMESH_ElementSearcher* SMESH_MeshEditor::GetElementSearcher() return new SMESH_ElementSearcherImpl( *GetMeshDS() ); } +//======================================================================= +/*! + * \brief Return SMESH_ElementSearcher + */ +//======================================================================= + +SMESH_ElementSearcher* SMESH_MeshEditor::GetElementSearcher(SMDS_ElemIteratorPtr elemIt) +{ + return new SMESH_ElementSearcherImpl( *GetMeshDS(), elemIt ); +} + //======================================================================= /*! * \brief Return true if the point is IN or ON of the element @@ -7067,7 +7083,7 @@ bool SMESH_MeshEditor::isOut( const SMDS_MeshElement* element, const gp_Pnt& poi while ( nodeIt->more() ) { const SMDS_MeshNode* node = cast2Node( nodeIt->next() ); - xyz.push_back( TNodeXYZ(node) ); + xyz.push_back( SMESH_TNodeXYZ(node) ); nodeList.push_back(node); } @@ -10481,7 +10497,7 @@ namespace { gp_XYZ centerXYZ (0, 0, 0); SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); while (aNodeItr->more()) - centerXYZ += SMESH_MeshEditor::TNodeXYZ(cast2Node( aNodeItr->next())); + centerXYZ += SMESH_TNodeXYZ(cast2Node( aNodeItr->next())); gp_Pnt aPnt = centerXYZ / theElem->NbNodes(); theClassifier.Perform(aPnt, theTol); @@ -10600,9 +10616,9 @@ bool SMESH_MeshEditor::DoubleNodesInRegion( const TIDSortedElemSet& theElems, bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector& theElems, bool createJointElems) { - MESSAGE("------------------------------------------------------"); - MESSAGE("SMESH_MeshEditor::CreateJointElementsOnGroupBoundaries"); - MESSAGE("------------------------------------------------------"); + MESSAGE("----------------------------------------------"); + MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries"); + MESSAGE("----------------------------------------------"); SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS(); meshDS->BuildDownWardConnectivity(false); @@ -10610,11 +10626,16 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorgetGrid(); // --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes + // build the list of cells with only a node or an edge on the border, with their domain and volume indexes // build the list of nodes shared by 2 or more domains, with their domain indexes - std::map, DownIdCompare> faceDomains; // 2x(id domain --> id volume) - std::map > nodeDomains; //oldId -> (domainId -> newId) + std::map, DownIdCompare> faceDomains; // face --> (id domain --> id volume) + std::mapcelldom; // cell vtkId --> domain + std::map, DownIdCompare> cellDomains; // oldNode --> (id domain --> id cell) + std::map > nodeDomains; // oldId --> (domainId --> newId) faceDomains.clear(); + celldom.clear(); + cellDomains.clear(); nodeDomains.clear(); std::map emptyMap; emptyMap.clear(); @@ -10651,6 +10672,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector, DownIdCompare>::iterator itface; + + // --- explore the shared faces domain by domain, + // explore the nodes of the face and see if they belong to a cell in the domain, + // which has only a node or an edge on the border (not a shared face) - // --- for each shared face, get the nodes + for (int idomain = 0; idomain < theElems.size(); idomain++) + { + const TIDSortedElemSet& domain = theElems[idomain]; + itface = faceDomains.begin(); + for (; itface != faceDomains.end(); ++itface) + { + std::map domvol = itface->second; + if (!domvol.count(idomain)) + continue; + DownIdType face = itface->first; + //MESSAGE(" --- face " << face.cellId); + std::set oldNodes; + oldNodes.clear(); + grid->GetNodeIds(oldNodes, face.cellId, face.cellType); + std::set::iterator itn = oldNodes.begin(); + for (; itn != oldNodes.end(); ++itn) + { + int oldId = *itn; + //MESSAGE(" node " << oldId); + std::set cells; + cells.clear(); + vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId); + for (int i=0; iFindElement(GetMeshDS()->fromVtkToSmds(vtkId)); + if (!domain.count(anElem)) + continue; + int vtkType = grid->GetCellType(vtkId); + int downId = grid->CellIdToDownId(vtkId); + DownIdType aCell(downId, vtkType); + if (celldom.count(vtkId)) + continue; + cellDomains[aCell][idomain] = vtkId; + celldom[vtkId] = idomain; + } + } + } + } + + // --- explore the shared faces domain by domain, to duplicate the nodes in a coherent way + // for each shared face, get the nodes // for each node, for each domain of the face, create a clone of the node - std::map, DownIdCompare>::iterator itface = faceDomains.begin(); - for( ; itface != faceDomains.end();++itface ) + for (int idomain = 0; idomain < theElems.size(); idomain++) { - DownIdType face = itface->first; - std::map domvol = itface->second; - std::set oldNodes; - oldNodes.clear(); - grid->GetNodeIds(oldNodes, face.cellId, face.cellType); - std::set::iterator itn = oldNodes.begin(); - for (;itn != oldNodes.end(); ++itn) + itface = faceDomains.begin(); + for (; itface != faceDomains.end(); ++itface) { - int oldId = *itn; - if (!nodeDomains.count(oldId)) - nodeDomains[oldId] = emptyMap; // create an empty entry for node - std::map::iterator itdom = domvol.begin(); - for(; itdom != domvol.end(); ++itdom) + std::map domvol = itface->second; + if (!domvol.count(idomain)) + continue; + DownIdType face = itface->first; + //MESSAGE(" --- face " << face.cellId); + std::set oldNodes; + oldNodes.clear(); + grid->GetNodeIds(oldNodes, face.cellId, face.cellType); + std::set::iterator itn = oldNodes.begin(); + for (; itn != oldNodes.end(); ++itn) { - int idom = itdom->first; - if ( nodeDomains[oldId].empty() ) - nodeDomains[oldId][idom] = oldId; // keep the old node in the first domain - else + int oldId = *itn; + //MESSAGE(" node " << oldId); + if (!nodeDomains.count(oldId)) + nodeDomains[oldId] = emptyMap; // create an empty entry for node + if (nodeDomains[oldId].empty()) + nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain + std::map::iterator itdom = domvol.begin(); + for (; itdom != domvol.end(); ++itdom) { - double *coords = grid->GetPoint(oldId); - SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]); - int newId = newNode->getVtkId(); - nodeDomains[oldId][idom] = newId; // cloned node for other domains + int idom = itdom->first; + //MESSAGE(" domain " << idom); + if (!nodeDomains[oldId].count(idom)) + { + double *coords = grid->GetPoint(oldId); + SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]); + int newId = newNode->getVtkId(); + nodeDomains[oldId][idom] = newId; // cloned node for other domains + //MESSAGE(" newNode " << newId); + } } } } @@ -10697,6 +10774,10 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector ((domain1 X domain2) --> newId) + // (domain1 X domain2) = domain1 + MAXINT*domain2 + std::map > nodeQuadDomains; + if (createJointElems) { itface = faceDomains.begin(); @@ -10707,7 +10788,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector::iterator itn; oldNodes.clear(); grid->GetNodeIds(oldNodes, face.cellId, face.cellType); - std::map localClonedNodeIds; std::map domvol = itface->second; std::map::iterator itdom = domvol.begin(); @@ -10715,24 +10795,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorsecond; itdom++; int dom2 = itdom->first; - - localClonedNodeIds.clear(); - for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn) - { - int oldId = *itn; - int refid = oldId; - if (nodeDomains[oldId].count(dom1)) - refid = nodeDomains[oldId][dom1]; - else - MESSAGE("--- problem domain node " << dom1 << " " << oldId); - int newid = oldId; - if (nodeDomains[oldId].count(dom2)) - newid = nodeDomains[oldId][dom2]; - else - MESSAGE("--- problem domain node " << dom2 << " " << oldId); - localClonedNodeIds[oldId] = newid; - } - meshDS->extrudeVolumeFromFace(vtkVolId, localClonedNodeIds); + grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains, nodeQuadDomains); } } @@ -10740,6 +10803,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorGetType() != elemType ) throw SALOME_Exception(LOCALIZED("wrong element type")); + if ( aroundElements && elemType == SMDSAbs_Volume ) + throw SALOME_Exception(LOCALIZED("wrong element type for aroundElements==true")); + if ( !targetMesh ) toCopyElements = toCopyExistingBondary = false; SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh ); SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS(); + int nbAddedBnd = 0; + + // editor adding present bnd elements and optionally holding elements to add to the group + SMESH_MeshEditor* presentEditor; + SMESH_MeshEditor tgtEditor2( tgtEditor.GetMesh() ); + presentEditor = toAddExistingBondary ? &tgtEditor : &tgtEditor2; SMDS_VolumeTool vTool; - TIDSortedElemSet emptySet, avoidSet; + TIDSortedElemSet avoidSet; + const TIDSortedElemSet emptySet, *elemSet = aroundElements ? &elements : &emptySet; int inode; typedef vector TConnectivity; @@ -10883,7 +10966,9 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, const SMDS_MeshElement* elem = eIt->next(); const int iQuad = elem->IsQuadratic(); + // ------------------------------------------------------------------------------------ // 1. For an elem, get present bnd elements and connectivities of missing bnd elements + // ------------------------------------------------------------------------------------ vector presentBndElems; vector missingBndElems; TConnectivity nodes; @@ -10935,7 +11020,7 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, { nodes[0] = elem->GetNode(i); nodes[1] = elem->GetNode((i+1)%nbNodes); - if ( FindFaceInSet( nodes[0], nodes[1], emptySet, avoidSet)) + if ( FindFaceInSet( nodes[0], nodes[1], *elemSet, avoidSet)) continue; // not free link //if ( iQuad ) @@ -10948,7 +11033,9 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, } } + // --------------------------------- // 2. Add missing boundary elements + // --------------------------------- if ( targetMesh != myMesh ) // instead of making a map of nodes in this mesh and targetMesh, // we create nodes with same IDs. We can renumber them later, if needed @@ -10958,16 +11045,28 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, TConnectivity nodes( srcNodes.size() ); for ( inode = 0; inode < nodes.size(); ++inode ) nodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] ); + if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes, + missType, + /*noMedium=*/true)) + continue; tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4); + ++nbAddedBnd; } else for ( int i = 0; i < missingBndElems.size(); ++i ) { - TConnectivity& nodes = missingBndElems[i]; + TConnectivity& nodes = missingBndElems[i]; + if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes, + missType, + /*noMedium=*/true)) + continue; tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4); + ++nbAddedBnd; } + // ---------------------------------- // 3. Copy present boundary elements + // ---------------------------------- if ( toCopyExistingBondary ) for ( int i = 0 ; i < presentBndElems.size(); ++i ) { @@ -10975,13 +11074,19 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, TConnectivity nodes( e->NbNodes() ); for ( inode = 0; inode < nodes.size(); ++inode ) nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) ); - tgtEditor.AddElement(nodes, missType, e->IsPoly()); - // leave only missing elements in tgtEditor.myLastCreatedElems - tgtEditor.myLastCreatedElems.Remove( tgtEditor.myLastCreatedElems.Size() ); + presentEditor->AddElement(nodes, missType, e->IsPoly()); + } + else // store present elements to add them to a group + for ( int i = 0 ; i < presentBndElems.size(); ++i ) + { + presentEditor->myLastCreatedElems.Append(presentBndElems[i]); } + } // loop on given elements - // 4. Fill group with missing boundary elements + // --------------------------------------------- + // 4. Fill group with boundary elements + // --------------------------------------------- if ( group ) { if ( SMESHDS_Group* g = dynamic_cast( group->GetGroupDS() )) @@ -10989,9 +11094,12 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, g->SMDSGroup().Add( tgtEditor.myLastCreatedElems( i+1 )); } tgtEditor.myLastCreatedElems.Clear(); + tgtEditor2.myLastCreatedElems.Clear(); + // ----------------------- // 5. Copy given elements - if ( toCopyElements ) + // ----------------------- + if ( toCopyElements && targetMesh != myMesh ) { if (elements.empty()) eIt = aMesh->elementsIterator(elemType); @@ -11008,5 +11116,5 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, tgtEditor.myLastCreatedElems.Clear(); } } - return; + return nbAddedBnd; }