X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FDriverMED%2FDriverMED_W_SMESHDS_Mesh.cxx;h=1b3c26bac11ab5e2120c601832686403dc5b2792;hp=ade26b2b7ab24e514ee69914ca26ab4dcc4586f6;hb=77ab84920942791849f9fdbd567da6701acfca7f;hpb=bd8f1aee7c78f7d2eb82bd4fec5e08c9e3d280ce diff --git a/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx b/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx index ade26b2b7..1b3c26bac 100644 --- a/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx +++ b/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2015 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 @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,19 +24,25 @@ // File : DriverMED_W_SMESHDS_Mesh.cxx // Module : SMESH // -#include #include "DriverMED_W_SMESHDS_Mesh.h" -#include "DriverMED_Family.h" -#include "SMESHDS_Mesh.hxx" +#include "DriverMED_Family.h" +#include "MED_Factory.hxx" +#include "MED_Utilities.hxx" +#include "SMDS_IteratorOnIterators.hxx" #include "SMDS_MeshElement.hxx" #include "SMDS_MeshNode.hxx" #include "SMDS_PolyhedralVolumeOfNodes.hxx" +#include "SMDS_SetIterator.hxx" +#include "SMESHDS_Mesh.hxx" -#include "utilities.h" +#include +#include +#include + +#include -#include "MED_Utilities.hxx" #define _EDF_NODE_IDS_ //#define _ELEMENTS_BY_DIM_ @@ -46,25 +52,28 @@ using namespace MED; DriverMED_W_SMESHDS_Mesh::DriverMED_W_SMESHDS_Mesh(): + myMedVersion(MED::eV2_2), myAllSubMeshes (false), myDoGroupOfNodes (false), myDoGroupOfEdges (false), myDoGroupOfFaces (false), myDoGroupOfVolumes (false), myDoGroupOf0DElems(false), - myDoGroupOfBalls(false) + myDoGroupOfBalls(false), + myAutoDimension(true), + myAddODOnVertices(false) {} void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName, - MED::EVersion theId) + MED::EVersion theId) { - myMed = CrWrapper(theFileName,theId); Driver_SMESHDS_Mesh::SetFile(theFileName); + myMedVersion = theId; } void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName) { - return SetFile(theFileName,MED::eV2_2); + Driver_SMESHDS_Mesh::SetFile(theFileName); } string DriverMED_W_SMESHDS_Mesh::GetVersionString(const MED::EVersion theVersion, int theNbDigits) @@ -97,7 +106,7 @@ void DriverMED_W_SMESHDS_Mesh::AddAllSubMeshes() void DriverMED_W_SMESHDS_Mesh::AddSubMesh(SMESHDS_SubMesh* theSubMesh, int theID) { - mySubMeshes[theID] = theSubMesh; + mySubMeshes.push_back( theSubMesh ); } void DriverMED_W_SMESHDS_Mesh::AddGroupOfNodes() @@ -120,7 +129,8 @@ void DriverMED_W_SMESHDS_Mesh::AddGroupOfVolumes() myDoGroupOfVolumes = true; } -namespace{ +namespace +{ typedef double (SMDS_MeshNode::* TGetCoord)() const; typedef const char* TName; typedef const char* TUnit; @@ -248,7 +258,6 @@ namespace{ const SMDSAbs_ElementType anElemType) { anElemFamMap.Clear(); - //anElemFamMap.clear(); list::iterator aFamsIter = aFamilies.begin(); while ( aFamsIter != aFamilies.end() ) { @@ -257,12 +266,11 @@ namespace{ } else { int aFamId = (*aFamsIter)->GetId(); - const set& anElems = (*aFamsIter)->GetElements(); - set::const_iterator anElemsIter = anElems.begin(); + const ElementsSet& anElems = (*aFamsIter)->GetElements(); + ElementsSet::const_iterator anElemsIter = anElems.begin(); for (; anElemsIter != anElems.end(); anElemsIter++) { anElemFamMap.Bind( (Standard_Address)*anElemsIter, aFamId ); - //anElemFamMap[*anElemsIter] = aFamId; } // remove a family from the list aFamilies.erase( aFamsIter++ ); @@ -282,11 +290,23 @@ namespace{ { if ( anElemFamMap.IsBound( (Standard_Address) anElement )) return anElemFamMap( (Standard_Address) anElement ); -// TElemFamilyMap::iterator elem_famNum = anElemFamMap.find( anElement ); -// if ( elem_famNum != anElemFamMap.end() ) -// return elem_famNum->second; + return aDefaultFamilyId; } + + //================================================================================ + /*! + * \brief Returns iterator on sub-meshes + */ + //================================================================================ + + SMESHDS_SubMeshIteratorPtr getIterator( std::vector& mySubMeshes ) + { + return SMESHDS_SubMeshIteratorPtr + ( new SMDS_SetIterator + < const SMESHDS_SubMesh*, std::vector< SMESHDS_SubMesh* >::iterator >( mySubMeshes.begin(), + mySubMeshes.end() )); + } } Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() @@ -311,12 +331,13 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() } // Mesh dimension definition - TInt aSpaceDimension; + TInt aSpaceDimension = 3; TCoordHelperPtr aCoordHelperPtr; { bool anIsXDimension = false; bool anIsYDimension = false; bool anIsZDimension = false; + if ( myAutoDimension ) { SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator(); double aBounds[6]; @@ -333,17 +354,34 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() aBounds[2] = min(aBounds[2],aNode->Y()); aBounds[3] = max(aBounds[3],aNode->Y()); - + aBounds[4] = min(aBounds[4],aNode->Z()); aBounds[5] = max(aBounds[5],aNode->Z()); } double EPS = 1.0E-7; + TopoDS_Shape mainShape = myMesh->ShapeToMesh(); + bool hasShapeToMesh = ( myMesh->SubMeshIndices().size() > 1 ); + if ( !mainShape.IsNull() && hasShapeToMesh ) + { + // define EPS by max tolerance of the mainShape (IPAL53097) + TopExp_Explorer subShape; + for ( subShape.Init( mainShape, TopAbs_FACE ); subShape.More(); subShape.Next() ) { + EPS = Max( EPS, BRep_Tool::Tolerance( TopoDS::Face( subShape.Current() ))); + } + for ( subShape.Init( mainShape, TopAbs_EDGE ); subShape.More(); subShape.Next() ) { + EPS = Max( EPS, BRep_Tool::Tolerance( TopoDS::Edge( subShape.Current() ))); + } + for ( subShape.Init( mainShape, TopAbs_VERTEX ); subShape.More(); subShape.Next() ) { + EPS = Max( EPS, BRep_Tool::Tolerance( TopoDS::Vertex( subShape.Current() ))); + } + EPS *= 2.; + } anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS; anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS; anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS; aSpaceDimension = anIsXDimension + anIsYDimension + anIsZDimension; - if(!aSpaceDimension) + if ( !aSpaceDimension ) aSpaceDimension = 3; // PAL16857(SMESH not conform to the MED convention): if ( aSpaceDimension == 2 && anIsZDimension ) // 2D only if mesh is in XOY plane @@ -360,7 +398,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() } SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator(/*idInceasingOrder=*/true); - switch(aSpaceDimension){ + switch ( aSpaceDimension ) { case 3: aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName)); break; @@ -390,6 +428,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() if ( myMesh->NbVolumes() > 0 ) aMeshDimension = 3; + MED::PWrapper myMed = CrWrapper(myFile,myMedVersion); PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aSpaceDimension,aMeshName); MESSAGE("Add - aMeshName : "<GetName()); myMed->SetMeshInfo(aMeshInfo); @@ -416,7 +455,6 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() if (myDoGroupOfBalls && nbBalls) myBallsDefaultFamilyId = REST_BALL_FAMILY; MESSAGE("Perform - aFamilyInfo"); - //cout << " DriverMED_Family::MakeFamilies() " << endl; list aFamilies; if (myAllSubMeshes) { aFamilies = DriverMED_Family::MakeFamilies @@ -427,9 +465,10 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() myDoGroupOfVolumes && nbVolumes, myDoGroupOf0DElems && nb0DElements, myDoGroupOfBalls && nbBalls); - } else { + } + else { aFamilies = DriverMED_Family::MakeFamilies - (mySubMeshes, myGroups, + (getIterator( mySubMeshes ), myGroups, myDoGroupOfNodes && nbNodes, myDoGroupOfEdges && nbEdges, myDoGroupOfFaces && nbFaces, @@ -437,7 +476,6 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() myDoGroupOf0DElems && nb0DElements, myDoGroupOfBalls && nbBalls); } - //cout << " myMed->SetFamilyInfo() " << endl; list::iterator aFamsIter; for (aFamsIter = aFamilies.begin(); aFamsIter != aFamilies.end(); aFamsIter++) { @@ -458,11 +496,9 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() const EConnectivite theConnMode = eNOD; TInt aNbNodes = myMesh->NbNodes(); - //cout << " myMed->CrNodeInfo() aNbNodes = " << aNbNodes << endl; PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo, aNbNodes, theMode, theSystem, theIsElemNum, theIsElemNames); - //cout << " fillElemFamilyMap( SMDSAbs_Node )" << endl; // find family numbers for nodes TElemFamilyMap anElemFamMap; fillElemFamilyMap( anElemFamMap, aFamilies, SMDSAbs_Node ); @@ -478,7 +514,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() int aNodeID = aCoordHelperPtr->GetID(); aNodeInfo->SetElemNum( iNode, aNodeID ); #ifdef _EDF_NODE_IDS_ - aNodeIdMap[aNodeID] = iNode+1; + aNodeIdMap.insert( aNodeIdMap.end(), make_pair( aNodeID, iNode+1 )); #endif // family number const SMDS_MeshNode* aNode = aCoordHelperPtr->GetNode(); @@ -506,9 +542,25 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() const SMDS_MeshInfo& nbElemInfo = myMesh->GetMeshInfo(); // poly elements are not supported by med-2.1 - bool polyTypesSupported = myMed->CrPolygoneInfo(aMeshInfo,eMAILLE,ePOLYGONE,0,0); + bool polyTypesSupported = ( myMed->CrPolygoneInfo(aMeshInfo,eMAILLE,ePOLYGONE,0,0).get() != 0 ); TInt nbPolygonNodes = 0, nbPolyhedronNodes = 0, nbPolyhedronFaces = 0; + // nodes on VERTEXes where 0D elements are absent + std::vector nodesOf0D; + std::vector< SMDS_ElemIteratorPtr > iterVec; + SMDS_ElemIteratorPtr iterVecIter; + if ( myAddODOnVertices && getNodesOfMissing0DOnVert( myMesh, nodesOf0D )) + { + iterVec.resize(2); + iterVec[0] = myMesh->elementsIterator( SMDSAbs_0DElement ); + iterVec[1] = SMDS_ElemIteratorPtr + ( new SMDS_ElementVectorIterator( nodesOf0D.begin(), nodesOf0D.end() )); + + typedef SMDS_IteratorOnIterators + < const SMDS_MeshElement *, std::vector< SMDS_ElemIteratorPtr > > TItIterator; + iterVecIter = SMDS_ElemIteratorPtr( new TItIterator( iterVec )); + } + // collect info on all geom types list< TElemTypeData > aTElemTypeDatas; @@ -519,7 +571,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() #endif aTElemTypeDatas.push_back(TElemTypeData(anEntity, ePOINT1, - nbElemInfo.Nb0DElements(), + nbElemInfo.Nb0DElements() + nodesOf0D.size(), SMDSAbs_0DElement)); #ifdef _ELEMENTS_BY_DIM_ anEntity = eSTRUCT_ELEMENT; @@ -532,28 +584,33 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() anEntity = eARETE; #endif aTElemTypeDatas.push_back( TElemTypeData(anEntity, - eSEG2, - nbElemInfo.NbEdges( ORDER_LINEAR ), - SMDSAbs_Edge)); + eSEG2, + nbElemInfo.NbEdges( ORDER_LINEAR ), + SMDSAbs_Edge)); aTElemTypeDatas.push_back( TElemTypeData(anEntity, - eSEG3, - nbElemInfo.NbEdges( ORDER_QUADRATIC ), - SMDSAbs_Edge)); + eSEG3, + nbElemInfo.NbEdges( ORDER_QUADRATIC ), + SMDSAbs_Edge)); #ifdef _ELEMENTS_BY_DIM_ anEntity = eFACE; #endif aTElemTypeDatas.push_back( TElemTypeData(anEntity, - eTRIA3, - nbElemInfo.NbTriangles( ORDER_LINEAR ), - SMDSAbs_Face)); + eTRIA3, + nbElemInfo.NbTriangles( ORDER_LINEAR ), + SMDSAbs_Face)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eTRIA6, + nbElemInfo.NbTriangles( ORDER_QUADRATIC ) - + nbElemInfo.NbBiQuadTriangles(), + SMDSAbs_Face)); aTElemTypeDatas.push_back( TElemTypeData(anEntity, - eTRIA6, - nbElemInfo.NbTriangles( ORDER_QUADRATIC ), - SMDSAbs_Face)); + eTRIA7, + nbElemInfo.NbBiQuadTriangles(), + SMDSAbs_Face)); aTElemTypeDatas.push_back( TElemTypeData(anEntity, - eQUAD4, - nbElemInfo.NbQuadrangles( ORDER_LINEAR ), - SMDSAbs_Face)); + eQUAD4, + nbElemInfo.NbQuadrangles( ORDER_LINEAR ), + SMDSAbs_Face)); aTElemTypeDatas.push_back( TElemTypeData(anEntity, eQUAD8, nbElemInfo.NbQuadrangles( ORDER_QUADRATIC ) - @@ -566,37 +623,46 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() if ( polyTypesSupported ) { aTElemTypeDatas.push_back( TElemTypeData(anEntity, ePOLYGONE, - nbElemInfo.NbPolygons(), + nbElemInfo.NbPolygons( ORDER_LINEAR ), SMDSAbs_Face)); // we need one more loop on poly elements to count nb of their nodes aTElemTypeDatas.push_back( TElemTypeData(anEntity, ePOLYGONE, - nbElemInfo.NbPolygons(), + nbElemInfo.NbPolygons( ORDER_LINEAR ), + SMDSAbs_Face)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + ePOLYGON2, + nbElemInfo.NbPolygons( ORDER_QUADRATIC ), + SMDSAbs_Face)); + // we need one more loop on QUAD poly elements to count nb of their nodes + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + ePOLYGON2, + nbElemInfo.NbPolygons( ORDER_QUADRATIC ), SMDSAbs_Face)); } #ifdef _ELEMENTS_BY_DIM_ anEntity = eMAILLE; #endif aTElemTypeDatas.push_back( TElemTypeData(anEntity, - eTETRA4, - nbElemInfo.NbTetras( ORDER_LINEAR ), - SMDSAbs_Volume)); + eTETRA4, + nbElemInfo.NbTetras( ORDER_LINEAR ), + SMDSAbs_Volume)); aTElemTypeDatas.push_back( TElemTypeData(anEntity, - eTETRA10, - nbElemInfo.NbTetras( ORDER_QUADRATIC ), - SMDSAbs_Volume)); + eTETRA10, + nbElemInfo.NbTetras( ORDER_QUADRATIC ), + SMDSAbs_Volume)); aTElemTypeDatas.push_back( TElemTypeData(anEntity, - ePYRA5, - nbElemInfo.NbPyramids( ORDER_LINEAR ), - SMDSAbs_Volume)); + ePYRA5, + nbElemInfo.NbPyramids( ORDER_LINEAR ), + SMDSAbs_Volume)); aTElemTypeDatas.push_back( TElemTypeData(anEntity, - ePYRA13, - nbElemInfo.NbPyramids( ORDER_QUADRATIC ), - SMDSAbs_Volume)); + ePYRA13, + nbElemInfo.NbPyramids( ORDER_QUADRATIC ), + SMDSAbs_Volume)); aTElemTypeDatas.push_back( TElemTypeData(anEntity, - ePENTA6, - nbElemInfo.NbPrisms( ORDER_LINEAR ), - SMDSAbs_Volume)); + ePENTA6, + nbElemInfo.NbPrisms( ORDER_LINEAR ), + SMDSAbs_Volume)); aTElemTypeDatas.push_back( TElemTypeData(anEntity, ePENTA15, nbElemInfo.NbPrisms( ORDER_QUADRATIC ), @@ -642,21 +708,11 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() int defaultFamilyId = 0; switch ( aElemTypeData->_smdsType ) { - case SMDSAbs_0DElement: - defaultFamilyId = my0DElementsDefaultFamilyId; - break; - case SMDSAbs_Ball: - defaultFamilyId = myBallsDefaultFamilyId; - break; - case SMDSAbs_Edge: - defaultFamilyId = myEdgesDefaultFamilyId; - break; - case SMDSAbs_Face: - defaultFamilyId = myFacesDefaultFamilyId; - break; - case SMDSAbs_Volume: - defaultFamilyId = myVolumesDefaultFamilyId; - break; + case SMDSAbs_0DElement: defaultFamilyId = my0DElementsDefaultFamilyId; break; + case SMDSAbs_Ball: defaultFamilyId = myBallsDefaultFamilyId; break; + case SMDSAbs_Edge: defaultFamilyId = myEdgesDefaultFamilyId; break; + case SMDSAbs_Face: defaultFamilyId = myFacesDefaultFamilyId; break; + case SMDSAbs_Volume: defaultFamilyId = myVolumesDefaultFamilyId; break; default: continue; } @@ -667,9 +723,14 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() // Treat POLYGONs // --------------- - if ( aElemTypeData->_geomType == ePOLYGONE ) + if ( aElemTypeData->_geomType == ePOLYGONE || + aElemTypeData->_geomType == ePOLYGON2 ) { - elemIterator = myMesh->elementGeomIterator( SMDSGeom_POLYGON ); + if ( aElemTypeData->_geomType == ePOLYGONE ) + elemIterator = myMesh->elementEntityIterator( SMDSEntity_Polygon ); + else + elemIterator = myMesh->elementEntityIterator( SMDSEntity_Quad_Polygon ); + if ( nbPolygonNodes == 0 ) { // Count nb of nodes while ( elemIterator->more() ) { @@ -719,9 +780,10 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() break; } myMed->SetPolygoneInfo(aPolygoneInfo); - } - } + nbPolygonNodes = 0; // to treat next polygon type + } + } // Treat POLYEDREs // ---------------- @@ -732,7 +794,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() if ( nbPolyhedronNodes == 0 ) { // Count nb of nodes while ( elemIterator->more() ) { - const SMDS_MeshElement* anElem = elemIterator->next(); + const SMDS_MeshElement* anElem = elemIterator->next(); const SMDS_VtkVolume *aPolyedre = dynamic_cast(anElem); if ( !aPolyedre ) continue; nbPolyhedronNodes += aPolyedre->NbNodes(); @@ -761,7 +823,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() TInt iFace = 0, iNode = 0; while ( elemIterator->more() ) { - const SMDS_MeshElement* anElem = elemIterator->next(); + const SMDS_MeshElement* anElem = elemIterator->next(); const SMDS_VtkVolume *aPolyedre = dynamic_cast(anElem); if ( !aPolyedre ) continue; // index @@ -803,8 +865,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() else if (aElemTypeData->_geomType == eBALL ) { // allocate data arrays - PBallInfo aBallInfo = myMed->CrBallInfo( aMeshInfo, - aElemTypeData->_nbElems ); + PBallInfo aBallInfo = myMed->CrBallInfo( aMeshInfo, aElemTypeData->_nbElems ); // build map of family numbers for this type if ( !isElemFamMapBuilt[ aElemTypeData->_smdsType ]) @@ -863,6 +924,8 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() TInt aNbNodes = MED::GetNbNodes(aElemTypeData->_geomType); elemIterator = myMesh->elementsIterator( aElemTypeData->_smdsType ); + if ( aElemTypeData->_smdsType == SMDSAbs_0DElement && ! nodesOf0D.empty() ) + elemIterator = iterVecIter; while ( elemIterator->more() ) { const SMDS_MeshElement* anElem = elemIterator->next(); @@ -911,3 +974,31 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() mySubMeshes.clear(); return aResult; } + +//================================================================================ +/*! + * \brief Returns nodes on VERTEXes where 0D elements are absent + */ +//================================================================================ + +bool DriverMED_W_SMESHDS_Mesh:: +getNodesOfMissing0DOnVert(SMESHDS_Mesh* meshDS, + std::vector& nodes) +{ + nodes.clear(); + for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i ) + { + if ( meshDS->IndexToShape( i ).ShapeType() != TopAbs_VERTEX ) + continue; + if ( SMESHDS_SubMesh* sm = meshDS->MeshElements(i) ) { + SMDS_NodeIteratorPtr nIt= sm->GetNodes(); + while (nIt->more()) + { + const SMDS_MeshNode* n = nIt->next(); + if ( n->NbInverseElements( SMDSAbs_0DElement ) == 0 ) + nodes.push_back( n ); + } + } + } + return !nodes.empty(); +}