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=980a648d03b6d8d33736ac13eb29fcd12fafbd83;hb=77ab84920942791849f9fdbd567da6701acfca7f;hpb=aeef41e893791465b04f5ce306640a42605849b9 diff --git a/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx b/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx index 980a648d0..1b3c26bac 100644 --- a/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx +++ b/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx @@ -1,43 +1,48 @@ -// SMESH DriverMED : driver to read and write 'med' files +// 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 +// +// 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, or (at your option) any later version. // -// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// 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. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + +// SMESH DriverMED : driver to read and write 'med' files // File : DriverMED_W_SMESHDS_Mesh.cxx // Module : SMESH - -#include +// #include "DriverMED_W_SMESHDS_Mesh.h" -#include "DriverMED_W_SMDS_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_ @@ -47,28 +52,46 @@ 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) + myDoGroupOfVolumes (false), + myDoGroupOf0DElems(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); } -void DriverMED_W_SMESHDS_Mesh::SetMeshName(const std::string& theMeshName) +string DriverMED_W_SMESHDS_Mesh::GetVersionString(const MED::EVersion theVersion, int theNbDigits) { - myMeshName = theMeshName; + TInt majeur, mineur, release; + majeur = mineur = release = 0; +// if ( theVersion == eV2_1 ) +// MED::GetVersionRelease(majeur, mineur, release); +// else + MED::GetVersionRelease(majeur, mineur, release); + ostringstream name; + if ( theNbDigits > 0 ) + name << majeur; + if ( theNbDigits > 1 ) + name << "." << mineur; + if ( theNbDigits > 2 ) + name << "." << release; + return name.str(); } void DriverMED_W_SMESHDS_Mesh::AddGroup(SMESHDS_GroupBase* theGroup) @@ -83,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() @@ -106,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; @@ -172,9 +196,9 @@ namespace{ TUnit* myUnit; public: TCoordHelper(const SMDS_NodeIteratorPtr& theNodeIter, - TGetCoord* theGetCoord, - TName* theName, - TUnit* theUnit = aUnit): + TGetCoord* theGetCoord, + TName* theName, + TUnit* theUnit = aUnit): myNodeIter(theNodeIter), myGetCoord(theGetCoord), myName(theName), @@ -183,7 +207,7 @@ namespace{ virtual ~TCoordHelper(){} bool Next(){ return myNodeIter->more() && - (myCurrentNode = myNodeIter->next()); + (myCurrentNode = myNodeIter->next()); } const SMDS_MeshNode* GetNode(){ return myCurrentNode; @@ -202,10 +226,89 @@ namespace{ } }; typedef boost::shared_ptr TCoordHelperPtr; - + + //------------------------------------------------------- + /*! + * \brief Structure describing element type + */ + //------------------------------------------------------- + struct TElemTypeData + { + EEntiteMaillage _entity; + EGeometrieElement _geomType; + TInt _nbElems; + SMDSAbs_ElementType _smdsType; + + TElemTypeData (EEntiteMaillage entity, EGeometrieElement geom, TInt nb, SMDSAbs_ElementType type) + : _entity(entity), _geomType(geom), _nbElems( nb ), _smdsType( type ) {} + }; + + + typedef NCollection_DataMap< Standard_Address, int > TElemFamilyMap; + + //================================================================================ + /*! + * \brief Fills element to famaly ID map for element type. + * Removes all families of anElemType + */ + //================================================================================ + + void fillElemFamilyMap( TElemFamilyMap & anElemFamMap, + list & aFamilies, + const SMDSAbs_ElementType anElemType) + { + anElemFamMap.Clear(); + list::iterator aFamsIter = aFamilies.begin(); + while ( aFamsIter != aFamilies.end() ) + { + if ((*aFamsIter)->GetType() != anElemType) { + aFamsIter++; + } + else { + int aFamId = (*aFamsIter)->GetId(); + const ElementsSet& anElems = (*aFamsIter)->GetElements(); + ElementsSet::const_iterator anElemsIter = anElems.begin(); + for (; anElemsIter != anElems.end(); anElemsIter++) + { + anElemFamMap.Bind( (Standard_Address)*anElemsIter, aFamId ); + } + // remove a family from the list + aFamilies.erase( aFamsIter++ ); + } + } + } + + //================================================================================ + /*! + * \brief For an element, return family ID found in the map or a default one + */ + //================================================================================ + + int getFamilyId( const TElemFamilyMap & anElemFamMap, + const SMDS_MeshElement* anElement, + const int aDefaultFamilyId) + { + if ( anElemFamMap.IsBound( (Standard_Address) anElement )) + return anElemFamMap( (Standard_Address) anElement ); + + 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() { Status aResult = DRS_OK; @@ -213,7 +316,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() INFOS("SMDS_MESH with hasConstructionEdges() or hasConstructionFaces() do not supports!!!"); return DRS_FAIL; } - try{ + try { MESSAGE("Perform - myFile : "<nodesIterator(); - double aBounds[6]; - if(aNodesIter->more()){ - const SMDS_MeshNode* aNode = aNodesIter->next(); - aBounds[0] = aBounds[1] = aNode->X(); - aBounds[2] = aBounds[3] = aNode->Y(); - aBounds[4] = aBounds[5] = aNode->Z(); - } - while(aNodesIter->more()){ - const SMDS_MeshNode* aNode = aNodesIter->next(); - aBounds[0] = min(aBounds[0],aNode->X()); - aBounds[1] = max(aBounds[1],aNode->X()); - - 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; - 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; - aMeshDimension = anIsXDimension + anIsYDimension + anIsZDimension; - if(!aMeshDimension) - aMeshDimension = 3; + SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator(); + double aBounds[6]; + if(aNodesIter->more()){ + const SMDS_MeshNode* aNode = aNodesIter->next(); + aBounds[0] = aBounds[1] = aNode->X(); + aBounds[2] = aBounds[3] = aNode->Y(); + aBounds[4] = aBounds[5] = aNode->Z(); + } + while(aNodesIter->more()){ + const SMDS_MeshNode* aNode = aNodesIter->next(); + aBounds[0] = min(aBounds[0],aNode->X()); + aBounds[1] = max(aBounds[1],aNode->X()); + + 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 ) + aSpaceDimension = 3; + // PAL16857(SMESH not conform to the MED convention): + if ( aSpaceDimension == 2 && anIsZDimension ) // 2D only if mesh is in XOY plane + aSpaceDimension = 3; + // PAL18941(a saved study with a mesh belong Z is opened and the mesh is belong X) + if ( aSpaceDimension == 1 && !anIsXDimension ) {// 1D only if mesh is along OX + if ( anIsYDimension ) { + aSpaceDimension = 2; + anIsXDimension = true; + } else { + aSpaceDimension = 3; + } + } } - SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator(); - switch(aMeshDimension){ + SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator(/*idInceasingOrder=*/true); + switch ( aSpaceDimension ) { case 3: - aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName)); - break; + aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName)); + break; case 2: - if(anIsXDimension && anIsYDimension) - aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYGetCoord,aXYName)); - if(anIsYDimension && anIsZDimension) - aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYZGetCoord,aYZName)); - if(anIsXDimension && anIsZDimension) - aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXZGetCoord,aXZName)); - break; + if(anIsXDimension && anIsYDimension) + aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYGetCoord,aXYName)); + if(anIsYDimension && anIsZDimension) + aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYZGetCoord,aYZName)); + if(anIsXDimension && anIsZDimension) + aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXZGetCoord,aXZName)); + break; case 1: - if(anIsXDimension) - aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXGetCoord,aXName)); - if(anIsYDimension) - aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYGetCoord,aYName)); - if(anIsZDimension) - aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aZGetCoord,aZName)); - break; + if(anIsXDimension) + aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXGetCoord,aXName)); + if(anIsYDimension) + aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYGetCoord,aYName)); + if(anIsZDimension) + aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aZGetCoord,aZName)); + break; } } - + TInt aMeshDimension = 0; + if ( myMesh->NbEdges() > 0 ) + aMeshDimension = 1; + if ( myMesh->NbFaces() > 0 ) + aMeshDimension = 2; + if ( myMesh->NbVolumes() > 0 ) + aMeshDimension = 3; - PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aMeshName); + MED::PWrapper myMed = CrWrapper(myFile,myMedVersion); + PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aSpaceDimension,aMeshName); MESSAGE("Add - aMeshName : "<GetName()); myMed->SetMeshInfo(aMeshInfo); - // Storing SMDS groups and sub-meshes - //----------------------------------- - int myNodesDefaultFamilyId = 0; - int myEdgesDefaultFamilyId = 0; - int myFacesDefaultFamilyId = 0; - int myVolumesDefaultFamilyId = 0; - if (myDoGroupOfNodes) - myNodesDefaultFamilyId = REST_NODES_FAMILY; - if (myDoGroupOfEdges) - myEdgesDefaultFamilyId = REST_EDGES_FAMILY; - if (myDoGroupOfFaces) - myFacesDefaultFamilyId = REST_FACES_FAMILY; - if (myDoGroupOfVolumes) - myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY; + // Storing SMDS groups and sub-meshes as med families + //---------------------------------------------------- + int myNodesDefaultFamilyId = 0; + int my0DElementsDefaultFamilyId = 0; + int myBallsDefaultFamilyId = 0; + int myEdgesDefaultFamilyId = 0; + int myFacesDefaultFamilyId = 0; + int myVolumesDefaultFamilyId = 0; + int nbNodes = myMesh->NbNodes(); + int nb0DElements = myMesh->Nb0DElements(); + int nbBalls = myMesh->NbBalls(); + int nbEdges = myMesh->NbEdges(); + int nbFaces = myMesh->NbFaces(); + int nbVolumes = myMesh->NbVolumes(); + if (myDoGroupOfNodes && nbNodes) myNodesDefaultFamilyId = REST_NODES_FAMILY; + if (myDoGroupOfEdges && nbEdges) myEdgesDefaultFamilyId = REST_EDGES_FAMILY; + if (myDoGroupOfFaces && nbFaces) myFacesDefaultFamilyId = REST_FACES_FAMILY; + if (myDoGroupOfVolumes && nbVolumes) myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY; + if (myDoGroupOf0DElems && nb0DElements) my0DElementsDefaultFamilyId = REST_0DELEM_FAMILY; + if (myDoGroupOfBalls && nbBalls) myBallsDefaultFamilyId = REST_BALL_FAMILY; MESSAGE("Perform - aFamilyInfo"); - map anElemFamMap; list aFamilies; if (myAllSubMeshes) { aFamilies = DriverMED_Family::MakeFamilies (myMesh->SubMeshes(), myGroups, - myDoGroupOfNodes, myDoGroupOfEdges, myDoGroupOfFaces, myDoGroupOfVolumes); - } else { + myDoGroupOfNodes && nbNodes, + myDoGroupOfEdges && nbEdges, + myDoGroupOfFaces && nbFaces, + myDoGroupOfVolumes && nbVolumes, + myDoGroupOf0DElems && nb0DElements, + myDoGroupOfBalls && nbBalls); + } + else { aFamilies = DriverMED_Family::MakeFamilies - (mySubMeshes, myGroups, - myDoGroupOfNodes, myDoGroupOfEdges, myDoGroupOfFaces, myDoGroupOfVolumes); + (getIterator( mySubMeshes ), myGroups, + myDoGroupOfNodes && nbNodes, + myDoGroupOfEdges && nbEdges, + myDoGroupOfFaces && nbFaces, + myDoGroupOfVolumes && nbVolumes, + myDoGroupOf0DElems && nb0DElements, + myDoGroupOfBalls && nbBalls); } - list::iterator aFamsIter = aFamilies.begin(); - - for (; aFamsIter != aFamilies.end(); aFamsIter++) + list::iterator aFamsIter; + for (aFamsIter = aFamilies.begin(); aFamsIter != aFamilies.end(); aFamsIter++) { PFamilyInfo aFamilyInfo = (*aFamsIter)->GetFamilyInfo(myMed,aMeshInfo); myMed->SetFamilyInfo(aFamilyInfo); - int aFamId = (*aFamsIter)->GetId(); - - const set& anElems = (*aFamsIter)->GetElements(); - set::const_iterator anElemsIter = anElems.begin(); - for (; anElemsIter != anElems.end(); anElemsIter++) - { - anElemFamMap[*anElemsIter] = aFamId; - } -// delete (*aFamsIter); } // Storing SMDS nodes to the MED file for the MED mesh @@ -343,447 +489,484 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() typedef map TNodeIdMap; TNodeIdMap aNodeIdMap; #endif - TInt aNbElems = myMesh->NbNodes(); - MED::TIntVector anElemNums(aNbElems); - MED::TIntVector aFamilyNums(aNbElems); - MED::TFloatVector aCoordinates(aNbElems*aMeshDimension); - for(TInt iNode = 0, aStartId = 0; aCoordHelperPtr->Next(); iNode++, aStartId += aMeshDimension){ - for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){ - aCoordinates[aStartId+iCoord] = aCoordHelperPtr->GetCoord(iCoord); + const EModeSwitch theMode = eFULL_INTERLACE; + const ERepere theSystem = eCART; + const EBooleen theIsElemNum = eVRAI; + const EBooleen theIsElemNames = eFAUX; + const EConnectivite theConnMode = eNOD; + + TInt aNbNodes = myMesh->NbNodes(); + PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo, aNbNodes, + theMode, theSystem, theIsElemNum, theIsElemNames); + + // find family numbers for nodes + TElemFamilyMap anElemFamMap; + fillElemFamilyMap( anElemFamMap, aFamilies, SMDSAbs_Node ); + + for (TInt iNode = 0; aCoordHelperPtr->Next(); iNode++) + { + // coordinates + TCoordSlice aTCoordSlice = aNodeInfo->GetCoordSlice( iNode ); + for(TInt iCoord = 0; iCoord < aSpaceDimension; iCoord++){ + aTCoordSlice[iCoord] = aCoordHelperPtr->GetCoord(iCoord); } + // node number int aNodeID = aCoordHelperPtr->GetID(); - anElemNums[iNode] = aNodeID; + 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(); - if (anElemFamMap.find(aNode) != anElemFamMap.end()) - aFamilyNums[iNode] = anElemFamMap[aNode]; - else - aFamilyNums[iNode] = myNodesDefaultFamilyId; + int famNum = getFamilyId( anElemFamMap, aNode, myNodesDefaultFamilyId ); + aNodeInfo->SetFamNum( iNode, famNum ); } + anElemFamMap.Clear(); - MED::TStringVector aCoordNames(aMeshDimension); - MED::TStringVector aCoordUnits(aMeshDimension); - for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){ - aCoordNames[iCoord] = aCoordHelperPtr->GetName(iCoord); - aCoordUnits[iCoord] = aCoordHelperPtr->GetUnit(iCoord); + // coordinate names and units + for (TInt iCoord = 0; iCoord < aSpaceDimension; iCoord++) { + aNodeInfo->SetCoordName( iCoord, aCoordHelperPtr->GetName(iCoord)); + aNodeInfo->SetCoordUnit( iCoord, aCoordHelperPtr->GetUnit(iCoord)); } - const ERepere SMDS_COORDINATE_SYSTEM = eCART; - - PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo, - SMDS_COORDINATE_SYSTEM, - aCoordinates, - aCoordNames, - aCoordUnits, - aFamilyNums, - anElemNums); - MESSAGE("Perform - aNodeInfo->GetNbElem() = "<GetNbElem() = "<SetNodeInfo(aNodeInfo); + aNodeInfo.reset(); // free memory used for arrays + + // Storing SMDS elements to the MED file for the MED mesh + //------------------------------------------------------- + // Write one element type at once in order to minimize memory usage (PAL19276) + + const SMDS_MeshInfo& nbElemInfo = myMesh->GetMeshInfo(); + + // poly elements are not supported by med-2.1 + bool polyTypesSupported = ( myMed->CrPolygoneInfo(aMeshInfo,eMAILLE,ePOLYGONE,0,0).get() != 0 ); + TInt nbPolygonNodes = 0, nbPolyhedronNodes = 0, nbPolyhedronFaces = 0; - // Storing others SMDS elements to the MED file for the MED mesh - //-------------------------------------------------------------- - EEntiteMaillage SMDS_MED_ENTITY = eMAILLE; - const EConnectivite SMDS_MED_CONNECTIVITY = eNOD; + // 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 )); + } - // Storing SMDS Edges - if(TInt aNbElems = myMesh->NbEdges()){ + // collect info on all geom types + + list< TElemTypeData > aTElemTypeDatas; + + EEntiteMaillage anEntity = eMAILLE; #ifdef _ELEMENTS_BY_DIM_ - SMDS_MED_ENTITY = eARETE; + anEntity = eNOEUD_ELEMENT; #endif - SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator(); - TInt aNbConnectivity = MED::GetNbNodes(eSEG2); - MED::TIntVector anElemNums(aNbElems); - MED::TIntVector aFamilyNums(aNbElems); - MED::TIntVector aConnectivity(aNbElems*aNbConnectivity); - - for(TInt iElem = 0, iConn = 0; anIter->more(); iElem++, iConn+=aNbConnectivity){ - const SMDS_MeshEdge* anElem = anIter->next(); - SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator(); - for(TInt iNode = 0; iNode < aNbConnectivity && aNodesIter->more(); iNode++){ - const SMDS_MeshElement* aNode = aNodesIter->next(); -#ifdef _EDF_NODE_IDS_ - aConnectivity[iConn+iNode] = aNodeIdMap[aNode->GetID()]; -#else - aConnectivity[iConn+iNode] = aNode->GetID(); + aTElemTypeDatas.push_back(TElemTypeData(anEntity, + ePOINT1, + nbElemInfo.Nb0DElements() + nodesOf0D.size(), + SMDSAbs_0DElement)); +#ifdef _ELEMENTS_BY_DIM_ + anEntity = eSTRUCT_ELEMENT; #endif - } - anElemNums[iElem] = anElem->GetID(); - - if (anElemFamMap.find(anElem) != anElemFamMap.end()) - aFamilyNums[iElem] = anElemFamMap[anElem]; - else - aFamilyNums[iElem] = myEdgesDefaultFamilyId; - } - - PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo, - SMDS_MED_ENTITY, - eSEG2, - SMDS_MED_CONNECTIVITY, - aConnectivity, - aFamilyNums, - anElemNums); - myMed->SetCellInfo(aCellInfo); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eBALL, + nbElemInfo.NbBalls(), + SMDSAbs_Ball)); +#ifdef _ELEMENTS_BY_DIM_ + anEntity = eARETE; +#endif + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eSEG2, + nbElemInfo.NbEdges( ORDER_LINEAR ), + SMDSAbs_Edge)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + 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)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eTRIA6, + nbElemInfo.NbTriangles( ORDER_QUADRATIC ) - + nbElemInfo.NbBiQuadTriangles(), + SMDSAbs_Face)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eTRIA7, + nbElemInfo.NbBiQuadTriangles(), + SMDSAbs_Face)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eQUAD4, + nbElemInfo.NbQuadrangles( ORDER_LINEAR ), + SMDSAbs_Face)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eQUAD8, + nbElemInfo.NbQuadrangles( ORDER_QUADRATIC ) - + nbElemInfo.NbBiQuadQuadrangles(), + SMDSAbs_Face)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eQUAD9, + nbElemInfo.NbBiQuadQuadrangles(), + SMDSAbs_Face)); + if ( polyTypesSupported ) { + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + ePOLYGONE, + 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( 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)); } - - // Storing SMDS Faces - if(TInt aNbElems = myMesh->NbFaces()){ - SMDS_FaceIteratorPtr anIter = myMesh->facesIterator(); #ifdef _ELEMENTS_BY_DIM_ - SMDS_MED_ENTITY = eFACE; + anEntity = eMAILLE; #endif - TInt aNbTriaConn = MED::GetNbNodes(eTRIA3); - MED::TIntVector anTriaElemNums; - anTriaElemNums.reserve(aNbElems); - MED::TIntVector aTriaFamilyNums; - aTriaFamilyNums.reserve(aNbElems); - MED::TIntVector aTriaConn; - aTriaConn.reserve(aNbElems*aNbTriaConn); - - TInt aNbQuadConn = MED::GetNbNodes(eQUAD4); - MED::TIntVector aQuadElemNums; - aQuadElemNums.reserve(aNbElems); - MED::TIntVector aQuadFamilyNums; - aQuadFamilyNums.reserve(aNbElems); - MED::TIntVector aQuadConn; - aQuadConn.reserve(aNbElems*aNbQuadConn); - - MED::TIntVector aPolygoneElemNums; - aPolygoneElemNums.reserve(aNbElems); - MED::TIntVector aPolygoneInds; - aPolygoneInds.reserve(aNbElems + 1); - aPolygoneInds.push_back(1); // reference on the first element in the connectivities - MED::TIntVector aPolygoneFamilyNums; - aPolygoneFamilyNums.reserve(aNbElems); - MED::TIntVector aPolygoneConn; - aPolygoneConn.reserve(aNbElems*aNbQuadConn); - - for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){ - const SMDS_MeshFace* anElem = anIter->next(); - TInt aNbNodes = anElem->NbNodes(); - SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator(); - TInt aNbConnectivity; - MED::TIntVector* anElemNums; - MED::TIntVector* aFamilyNums; - MED::TIntVector* aConnectivity; - if (anElem->IsPoly()) { - aNbConnectivity = aNbNodes; - anElemNums = &aPolygoneElemNums; - aFamilyNums = &aPolygoneFamilyNums; - aConnectivity = &aPolygoneConn; - } else { - switch(aNbNodes){ - case 3: - aNbConnectivity = aNbTriaConn; - anElemNums = &anTriaElemNums; - aFamilyNums = &aTriaFamilyNums; - aConnectivity = &aTriaConn; - break; - case 4: - aNbConnectivity = aNbQuadConn; - anElemNums = &aQuadElemNums; - aFamilyNums = &aQuadFamilyNums; - aConnectivity = &aQuadConn; - break; - default: - break; + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eTETRA4, + nbElemInfo.NbTetras( ORDER_LINEAR ), + SMDSAbs_Volume)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eTETRA10, + nbElemInfo.NbTetras( ORDER_QUADRATIC ), + SMDSAbs_Volume)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + ePYRA5, + nbElemInfo.NbPyramids( ORDER_LINEAR ), + SMDSAbs_Volume)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + ePYRA13, + nbElemInfo.NbPyramids( ORDER_QUADRATIC ), + SMDSAbs_Volume)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + ePENTA6, + nbElemInfo.NbPrisms( ORDER_LINEAR ), + SMDSAbs_Volume)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + ePENTA15, + nbElemInfo.NbPrisms( ORDER_QUADRATIC ), + SMDSAbs_Volume)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eHEXA8, + nbElemInfo.NbHexas( ORDER_LINEAR ), + SMDSAbs_Volume)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eHEXA20, + nbElemInfo.NbHexas( ORDER_QUADRATIC )- + nbElemInfo.NbTriQuadHexas(), + SMDSAbs_Volume)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eHEXA27, + nbElemInfo.NbTriQuadHexas(), + SMDSAbs_Volume)); + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + eOCTA12, + nbElemInfo.NbHexPrisms(), + SMDSAbs_Volume)); + if ( polyTypesSupported ) { + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + ePOLYEDRE, + nbElemInfo.NbPolyhedrons(), + SMDSAbs_Volume)); + // we need one more loop on poly elements to count nb of their nodes + aTElemTypeDatas.push_back( TElemTypeData(anEntity, + ePOLYEDRE, + nbElemInfo.NbPolyhedrons(), + SMDSAbs_Volume)); + } + + vector< bool > isElemFamMapBuilt( SMDSAbs_NbElementTypes, false ); + + // loop on all geom types of elements + + list< TElemTypeData >::iterator aElemTypeData = aTElemTypeDatas.begin(); + for ( ; aElemTypeData != aTElemTypeDatas.end(); ++aElemTypeData ) + { + if ( aElemTypeData->_nbElems == 0 ) + continue; + + 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; + default: + continue; + } + + // iterator on elements of a current type + SMDS_ElemIteratorPtr elemIterator; + int iElem = 0; + + // Treat POLYGONs + // --------------- + if ( aElemTypeData->_geomType == ePOLYGONE || + aElemTypeData->_geomType == ePOLYGON2 ) + { + 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() ) { + const SMDS_MeshElement* anElem = elemIterator->next(); + nbPolygonNodes += anElem->NbNodes(); + if ( ++iElem == aElemTypeData->_nbElems ) + break; } } - MED::TIntVector aVector(aNbNodes); - for(TInt iNode = 0; aNodesIter->more(); iNode++){ - const SMDS_MeshElement* aNode = aNodesIter->next(); + else { + // Store in med file + PPolygoneInfo aPolygoneInfo = myMed->CrPolygoneInfo(aMeshInfo, + aElemTypeData->_entity, + aElemTypeData->_geomType, + aElemTypeData->_nbElems, + nbPolygonNodes, + theConnMode, theIsElemNum, + theIsElemNames); + TElemNum & index = *(aPolygoneInfo->myIndex.get()); + index[0] = 1; + + while ( elemIterator->more() ) + { + const SMDS_MeshElement* anElem = elemIterator->next(); + // index + TInt aNbNodes = anElem->NbNodes(); + index[ iElem+1 ] = index[ iElem ] + aNbNodes; + + // connectivity + TConnSlice aTConnSlice = aPolygoneInfo->GetConnSlice( iElem ); + for(TInt iNode = 0; iNode < aNbNodes; iNode++) { + const SMDS_MeshElement* aNode = anElem->GetNode( iNode ); #ifdef _EDF_NODE_IDS_ - aVector[iNode] = aNodeIdMap[aNode->GetID()]; + aTConnSlice[ iNode ] = aNodeIdMap[aNode->GetID()]; #else - aVector[iNode] = aNode->GetID(); + aTConnSlice[ iNode ] = aNode->GetID(); #endif - } - - TInt aSize = aConnectivity->size(); - aConnectivity->resize(aSize+aNbConnectivity); - // There is some differences between SMDS and MED in cells mapping - switch(aNbNodes){ - case 4: - (*aConnectivity)[aSize+0] = aVector[0]; - (*aConnectivity)[aSize+1] = aVector[1]; - (*aConnectivity)[aSize+2] = aVector[3]; - (*aConnectivity)[aSize+3] = aVector[2]; - default: - for(TInt iNode = 0; iNode < aNbNodes; iNode++) - (*aConnectivity)[aSize+iNode] = aVector[iNode]; - } - - if (anElem->IsPoly()) { - // fill indices for polygonal element - TInt aPrevPos = aPolygoneInds.back(); - aPolygoneInds.push_back(aPrevPos + aNbNodes); - } + } + // element number + aPolygoneInfo->SetElemNum( iElem, anElem->GetID() ); - anElemNums->push_back(anElem->GetID()); + // family number + int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId ); + aPolygoneInfo->SetFamNum( iElem, famNum ); - if (anElemFamMap.find(anElem) != anElemFamMap.end()) - aFamilyNums->push_back(anElemFamMap[anElem]); - else - aFamilyNums->push_back(myFacesDefaultFamilyId); - } - if(TInt aNbElems = anTriaElemNums.size()){ - PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo, - SMDS_MED_ENTITY, - eTRIA3, - SMDS_MED_CONNECTIVITY, - aTriaConn, - aTriaFamilyNums, - anTriaElemNums); - MESSAGE("Perform - anEntity = "<SetElemNum( iElem, anElem->GetID() ); + + // family number + int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId ); + aPolyhInfo->SetFamNum( iElem, famNum ); + + if ( ++iElem == aPolyhInfo->GetNbElem() ) + break; } + myMed->SetPolyedreInfo(aPolyhInfo); + } + } // if (aElemTypeData->_geomType == ePOLYEDRE ) - anElemNums = &aPolyedreElemNums; - aFamilyNums = &aPolyedreFamilyNums; + // Treat BALLs + // ---------------- + else if (aElemTypeData->_geomType == eBALL ) + { + // allocate data arrays + PBallInfo aBallInfo = myMed->CrBallInfo( aMeshInfo, aElemTypeData->_nbElems ); + + // build map of family numbers for this type + if ( !isElemFamMapBuilt[ aElemTypeData->_smdsType ]) + { + fillElemFamilyMap( anElemFamMap, aFamilies, aElemTypeData->_smdsType ); + isElemFamMapBuilt[ aElemTypeData->_smdsType ] = true; + } - TInt aNodeId, aNbFaces = aPolyedre->NbFaces(); - for (int iface = 1; iface <= aNbFaces; iface++) { - int aNbFaceNodes = aPolyedre->NbFaceNodes(iface); - for (int inode = 1; inode <= aNbFaceNodes; inode++) { - aNodeId = aPolyedre->GetFaceNode(iface, inode)->GetID(); + elemIterator = myMesh->elementsIterator( SMDSAbs_Ball ); + while ( elemIterator->more() ) + { + const SMDS_MeshElement* anElem = elemIterator->next(); + // connectivity + const SMDS_MeshElement* aNode = anElem->GetNode( 0 ); #ifdef _EDF_NODE_IDS_ - aPolyedreConn.push_back(aNodeIdMap[aNodeId]); + (*aBallInfo->myConn)[ iElem ] = aNodeIdMap[aNode->GetID()]; #else - aPolyedreConn.push_back(aNodeId); + (*aBallInfo->myConn)[ iElem ] = aNode->GetID(); #endif - } - TInt aPrevPos = aPolyedreFaces.back(); - aPolyedreFaces.push_back(aPrevPos + aNbFaceNodes); - } - TInt aPrevPos = aPolyedreInds.back(); - aPolyedreInds.push_back(aPrevPos + aNbFaces); - - } else { - TInt aNbNodes = anElem->NbNodes(); - SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator(); - TInt aNbConnectivity; - MED::TIntVector* aConnectivity; - switch(aNbNodes){ - case 4: - aNbConnectivity = aNbTetraConn; - anElemNums = &anTetraElemNums; - aFamilyNums = &aTetraFamilyNums; - aConnectivity = &aTetraConn; - break; - case 5: - aNbConnectivity = aNbPyraConn; - anElemNums = &anPyraElemNums; - aFamilyNums = &aPyraFamilyNums; - aConnectivity = &aPyraConn; - break; - case 6: - aNbConnectivity = aNbPentaConn; - anElemNums = &anPentaElemNums; - aFamilyNums = &aPentaFamilyNums; - aConnectivity = &aPentaConn; - break; - case 8: - aNbConnectivity = aNbHexaConn; - anElemNums = &aHexaElemNums; - aFamilyNums = &aHexaFamilyNums; - aConnectivity = &aHexaConn; - } + // element number + aBallInfo->SetElemNum( iElem, anElem->GetID() ); - TInt aSize = aConnectivity->size(); - aConnectivity->resize(aSize + aNbConnectivity); + // diameter + aBallInfo->myDiameters[ iElem ] = + static_cast( anElem )->GetDiameter(); - MED::TIntVector aVector(aNbNodes); - for(TInt iNode = 0; aNodesIter->more(); iNode++){ - const SMDS_MeshElement* aNode = aNodesIter->next(); + // family number + int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId ); + aBallInfo->SetFamNum( iElem, famNum ); + ++iElem; + } + // store data in a file + myMed->SetBallInfo(aBallInfo); + } + + else + { + // Treat standard types + // --------------------- + + // allocate data arrays + PCellInfo aCellInfo = myMed->CrCellInfo( aMeshInfo, + aElemTypeData->_entity, + aElemTypeData->_geomType, + aElemTypeData->_nbElems, + theConnMode, + theIsElemNum, + theIsElemNames); + // build map of family numbers for this type + if ( !isElemFamMapBuilt[ aElemTypeData->_smdsType ]) + { + //cout << " fillElemFamilyMap()" << endl; + fillElemFamilyMap( anElemFamMap, aFamilies, aElemTypeData->_smdsType ); + isElemFamMapBuilt[ aElemTypeData->_smdsType ] = true; + } + + 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(); + if ( anElem->NbNodes() != aNbNodes || anElem->IsPoly() ) + continue; // other geometry + + // connectivity + TConnSlice aTConnSlice = aCellInfo->GetConnSlice( iElem ); + for (TInt iNode = 0; iNode < aNbNodes; iNode++) { + const SMDS_MeshElement* aNode = anElem->GetNode( iNode ); #ifdef _EDF_NODE_IDS_ - aVector[iNode] = aNodeIdMap[aNode->GetID()]; + aTConnSlice[ iNode ] = aNodeIdMap[aNode->GetID()]; #else - aVector[iNode] = aNode->GetID(); + aTConnSlice[ iNode ] = aNode->GetID(); #endif } - // There is some difference between SMDS and MED in cells mapping - switch(aNbNodes){ - case 5: - (*aConnectivity)[aSize+0] = aVector[0]; - (*aConnectivity)[aSize+1] = aVector[3]; - (*aConnectivity)[aSize+2] = aVector[2]; - (*aConnectivity)[aSize+3] = aVector[1]; - (*aConnectivity)[aSize+4] = aVector[4]; - default: - for(TInt iNode = 0; iNode < aNbNodes; iNode++) - (*aConnectivity)[aSize+iNode] = aVector[iNode]; - } - } + // element number + aCellInfo->SetElemNum( iElem, anElem->GetID() ); - anElemNums->push_back(anElem->GetID()); + // family number + int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId ); + aCellInfo->SetFamNum( iElem, famNum ); - if (anElemFamMap.find(anElem) != anElemFamMap.end()) - aFamilyNums->push_back(anElemFamMap[anElem]); - else - aFamilyNums->push_back(myVolumesDefaultFamilyId); + if ( ++iElem == aCellInfo->GetNbElem() ) + break; + } + // store data in a file + myMed->SetCellInfo(aCellInfo); } - if(TInt aNbElems = anTetraElemNums.size()){ - PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo, - SMDS_MED_ENTITY, - eTETRA4, - SMDS_MED_CONNECTIVITY, - aTetraConn, - aTetraFamilyNums, - anTetraElemNums); - MESSAGE("Perform - anEntity = "<& 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(); +}