X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FNETGENPlugin%2FNETGENPlugin_Mesher.cxx;h=732a2441bc6c4d28bded942e0565bacdde988d20;hb=638fecd6a5b87f817e9df299dfb31b4990332e4d;hp=7da62dceef203c752d7c290bba8e44afaeb0cfbb;hpb=6492334154876aa32c3adc1be151cfb33807eacb;p=plugins%2Fnetgenplugin.git diff --git a/src/NETGENPlugin/NETGENPlugin_Mesher.cxx b/src/NETGENPlugin/NETGENPlugin_Mesher.cxx index 7da62dc..732a244 100644 --- a/src/NETGENPlugin/NETGENPlugin_Mesher.cxx +++ b/src/NETGENPlugin/NETGENPlugin_Mesher.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2022 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 @@ -84,24 +84,14 @@ #include //#include namespace netgen { -#ifdef NETGEN_V5 - extern int OCCGenerateMesh (OCCGeometry&, Mesh*&, MeshingParameters&, int, int); -#else - extern int OCCGenerateMesh (OCCGeometry&, Mesh*&, int, int, char*); -#endif - //extern void OCCSetLocalMeshSize(OCCGeometry & geom, Mesh & mesh); -#if defined(NETGEN_V5) && defined(WIN32) - DLL_HEADER -#endif + + NETGENPLUGIN_DLL_HEADER extern MeshingParameters mparam; -#if defined(NETGEN_V5) && defined(WIN32) - DLL_HEADER -#endif + + NETGENPLUGIN_DLL_HEADER extern volatile multithreadt multithread; -#if defined(NETGEN_V5) && defined(WIN32) - DLL_HEADER -#endif + NETGENPLUGIN_DLL_HEADER extern bool merge_solids; // values used for occgeo.facemeshstatus @@ -144,253 +134,39 @@ std::map SolidId2LocalSize; std::vector ControlPoints; std::set ShapesWithControlPoints; // <-- allows calling SetLocalSize() several times w/o recomputing ControlPoints -//============================================================================= -/*! - * - */ -//============================================================================= - -NETGENPlugin_Mesher::NETGENPlugin_Mesher (SMESH_Mesh* mesh, - const TopoDS_Shape& aShape, - const bool isVolume) - : _mesh (mesh), - _shape (aShape), - _isVolume(isVolume), - _optimize(true), - _fineness(NETGENPlugin_Hypothesis::GetDefaultFineness()), - _isViscousLayers2D(false), - _chordalError(-1), // means disabled - _ngMesh(NULL), - _occgeom(NULL), - _curShapeIndex(-1), - _progressTic(1), - _totalTime(1.0), - _simpleHyp(NULL), - _viscousLayersHyp(NULL), - _ptrToMe(NULL) -{ - SetDefaultParameters(); - ShapesWithLocalSize.Clear(); - VertexId2LocalSize.clear(); - EdgeId2LocalSize.clear(); - FaceId2LocalSize.clear(); - SolidId2LocalSize.clear(); - ControlPoints.clear(); - ShapesWithControlPoints.clear(); -} - -//================================================================================ -/*! - * Destuctor - */ -//================================================================================ - -NETGENPlugin_Mesher::~NETGENPlugin_Mesher() -{ - if ( _ptrToMe ) - *_ptrToMe = NULL; - _ptrToMe = 0; - _ngMesh = NULL; -} - -//================================================================================ -/*! - * Set pointer to NETGENPlugin_Mesher* field of the holder, that will be - * nullified at destruction of this - */ -//================================================================================ - -void NETGENPlugin_Mesher::SetSelfPointer( NETGENPlugin_Mesher ** ptr ) -{ - if ( _ptrToMe ) - *_ptrToMe = NULL; - - _ptrToMe = ptr; - - if ( _ptrToMe ) - *_ptrToMe = this; -} - -//================================================================================ -/*! - * \brief Initialize global NETGEN parameters with default values - */ -//================================================================================ - -void NETGENPlugin_Mesher::SetDefaultParameters() -{ - netgen::MeshingParameters& mparams = netgen::mparam; - // maximal mesh edge size - mparams.maxh = 0;//NETGENPlugin_Hypothesis::GetDefaultMaxSize(); - mparams.minh = 0; - // minimal number of segments per edge - mparams.segmentsperedge = NETGENPlugin_Hypothesis::GetDefaultNbSegPerEdge(); - // rate of growth of size between elements - mparams.grading = NETGENPlugin_Hypothesis::GetDefaultGrowthRate(); - // safety factor for curvatures (elements per radius) - mparams.curvaturesafety = NETGENPlugin_Hypothesis::GetDefaultNbSegPerRadius(); - // create elements of second order - mparams.secondorder = NETGENPlugin_Hypothesis::GetDefaultSecondOrder(); - // quad-dominated surface meshing - if (_isVolume) - mparams.quad = 0; - else - mparams.quad = NETGENPlugin_Hypothesis_2D::GetDefaultQuadAllowed(); - _fineness = NETGENPlugin_Hypothesis::GetDefaultFineness(); - mparams.uselocalh = NETGENPlugin_Hypothesis::GetDefaultSurfaceCurvature(); - netgen::merge_solids = NETGENPlugin_Hypothesis::GetDefaultFuseEdges(); -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -void SetLocalSize(TopoDS_Shape GeomShape, double LocalSize) +namespace { - if ( GeomShape.IsNull() ) return; - TopAbs_ShapeEnum GeomType = GeomShape.ShapeType(); - if (GeomType == TopAbs_COMPOUND) { - for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()) { - SetLocalSize(it.Value(), LocalSize); - } - return; - } - int key; - if (! ShapesWithLocalSize.Contains(GeomShape)) - key = ShapesWithLocalSize.Add(GeomShape); - else - key = ShapesWithLocalSize.FindIndex(GeomShape); - if (GeomType == TopAbs_VERTEX) { - VertexId2LocalSize[key] = LocalSize; - } else if (GeomType == TopAbs_EDGE) { - EdgeId2LocalSize[key] = LocalSize; - } else if (GeomType == TopAbs_FACE) { - FaceId2LocalSize[key] = LocalSize; - } else if (GeomType == TopAbs_SOLID) { - SolidId2LocalSize[key] = LocalSize; - } -} + inline void NOOP_Deleter(void *) { ; } -//============================================================================= -/*! - * Pass parameters to NETGEN - */ -//============================================================================= -void NETGENPlugin_Mesher::SetParameters(const NETGENPlugin_Hypothesis* hyp) -{ - if (hyp) + //============================================================================= + /*! + * Link - a pair of integer numbers + */ + //============================================================================= + struct Link { - netgen::MeshingParameters& mparams = netgen::mparam; - // Initialize global NETGEN parameters: - // maximal mesh segment size - mparams.maxh = hyp->GetMaxSize(); - // maximal mesh element linear size - mparams.minh = hyp->GetMinSize(); - // minimal number of segments per edge - mparams.segmentsperedge = hyp->GetNbSegPerEdge(); - // rate of growth of size between elements - mparams.grading = hyp->GetGrowthRate(); - // safety factor for curvatures (elements per radius) - mparams.curvaturesafety = hyp->GetNbSegPerRadius(); - // create elements of second order - mparams.secondorder = hyp->GetSecondOrder() ? 1 : 0; - // quad-dominated surface meshing - mparams.quad = hyp->GetQuadAllowed() ? 1 : 0; - _optimize = hyp->GetOptimize(); - _fineness = hyp->GetFineness(); - mparams.uselocalh = hyp->GetSurfaceCurvature(); - netgen::merge_solids = hyp->GetFuseEdges(); - _chordalError = hyp->GetChordalErrorEnabled() ? hyp->GetChordalError() : -1.; - _simpleHyp = NULL; - // mesh size file - mparams.meshsizefilename= hyp->GetMeshSizeFile().empty() ? 0 : hyp->GetMeshSizeFile().c_str(); - - const NETGENPlugin_Hypothesis::TLocalSize& localSizes = hyp->GetLocalSizesAndEntries(); - if ( !localSizes.empty() ) + int n1, n2; + Link(int _n1, int _n2) : n1(_n1), n2(_n2) {} + Link() : n1(0), n2(0) {} + bool Contains( int n ) const { return n == n1 || n == n2; } + bool IsConnected( const Link& other ) const { - SMESH_Gen_i* smeshGen_i = SMESH_Gen_i::GetSMESHGen(); - CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager"); - SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject); - SALOMEDS::Study_var myStudy = aStudyMgr->GetStudyByID(hyp->GetStudyId()); - if ( !myStudy->_is_nil() ) - { - NETGENPlugin_Hypothesis::TLocalSize::const_iterator it = localSizes.begin(); - for ( ; it != localSizes.end() ; it++) - { - std::string entry = (*it).first; - double val = (*it).second; - // -- - GEOM::GEOM_Object_var aGeomObj; - SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() ); - if ( !aSObj->_is_nil() ) { - CORBA::Object_var obj = aSObj->GetObject(); - aGeomObj = GEOM::GEOM_Object::_narrow(obj); - aSObj->UnRegister(); - } - TopoDS_Shape S = smeshGen_i->GeomObjectToShape( aGeomObj.in() ); - ::SetLocalSize(S, val); - } - } + return (( Contains( other.n1 ) || Contains( other.n2 )) && ( this != &other )); + } + static int HashCode(const Link& aLink, int aLimit) + { + return ::HashCode(aLink.n1 + aLink.n2, aLimit); } - } -} - -//============================================================================= -/*! - * Pass simple parameters to NETGEN - */ -//============================================================================= - -void NETGENPlugin_Mesher::SetParameters(const NETGENPlugin_SimpleHypothesis_2D* hyp) -{ - _simpleHyp = hyp; - if ( _simpleHyp ) - SetDefaultParameters(); -} - -//================================================================================ -/*! - * \brief Store a Viscous Layers hypothesis - */ -//================================================================================ - -void NETGENPlugin_Mesher::SetParameters(const StdMeshers_ViscousLayers* hyp ) -{ - _viscousLayersHyp = hyp; -} - -//============================================================================= -/*! - * Link - a pair of integer numbers - */ -//============================================================================= -struct Link -{ - int n1, n2; - Link(int _n1, int _n2) : n1(_n1), n2(_n2) {} - Link() : n1(0), n2(0) {} - bool Contains( int n ) const { return n == n1 || n == n2; } - bool IsConnected( const Link& other ) const - { - return (( Contains( other.n1 ) || Contains( other.n2 )) && ( this != &other )); - } -}; -int HashCode(const Link& aLink, int aLimit) -{ - return HashCode(aLink.n1 + aLink.n2, aLimit); -} + static Standard_Boolean IsEqual(const Link& aLink1, const Link& aLink2) + { + return (( aLink1.n1 == aLink2.n1 && aLink1.n2 == aLink2.n2 ) || + ( aLink1.n1 == aLink2.n2 && aLink1.n2 == aLink2.n1 )); + } + }; -Standard_Boolean IsEqual(const Link& aLink1, const Link& aLink2) -{ - return (( aLink1.n1 == aLink2.n1 && aLink1.n2 == aLink2.n2 ) || - ( aLink1.n1 == aLink2.n2 && aLink1.n2 == aLink2.n1 )); -} + typedef NCollection_Map TLinkMap; -namespace -{ //================================================================================ /*! * \brief return id of netgen point corresponding to SMDS node @@ -425,7 +201,7 @@ namespace list< TopoDS_Edge > getConnectedEdges( const TopoDS_Edge& edge, const TopoDS_Face& face, - const set< SMESH_subMesh* > & computedSM, + const set< SMESH_subMesh* > & /*computedSM*/, const SMESH_MesherHelper& helper, map< SMESH_subMesh*, set< int > >& addedEdgeSM2Faces) { @@ -469,7 +245,7 @@ namespace SMESH_subMesh* sm = helper.GetMesh()->GetSubMesh( *eItFwd ); bool connected = TopExp::CommonVertex( *ePrev, *eItFwd, vCommon ); - bool computed = sm->IsMeshComputed(); + bool computed = !sm->IsEmpty(); bool added = addedEdgeSM2Faces[ sm ].count( helper.GetSubShapeID() ); bool doubled = !eAdded.Add( *eItFwd ); bool orientOK = (( ePrev ->Orientation() < TopAbs_INTERNAL ) == @@ -491,7 +267,7 @@ namespace SMESH_subMesh* sm = helper.GetMesh()->GetSubMesh( *eItBack ); bool connected = TopExp::CommonVertex( *ePrev, *eItBack, vCommon ); - bool computed = sm->IsMeshComputed(); + bool computed = !sm->IsEmpty(); bool added = addedEdgeSM2Faces[ sm ].count( helper.GetSubShapeID() ); bool doubled = !eAdded.Add( *eItBack ); bool orientOK = (( ePrev ->Orientation() < TopAbs_INTERNAL ) == @@ -539,7 +315,7 @@ namespace OCC_CATCH_SIGNALS; BRepMesh_IncrementalMesh e(shape, 0.01, true); } - catch (Standard_Failure) + catch (Standard_Failure&) { } // updated.erase( triangulation.operator->() ); @@ -580,82 +356,362 @@ namespace */ //================================================================================ - // void makeQuadratic( const TopTools_IndexedMapOfShape& shapes, - // SMESH_Mesh* mesh ) - // { - // for ( int i = 1; i <= shapes.Extent(); ++i ) - // { - // SMESHDS_SubMesh* smDS = mesh->GetMeshDS()->MeshElements( shapes(i) ); - // if ( !smDS ) continue; - // SMDS_ElemIteratorPtr elemIt = smDS->GetElements(); - // if ( !elemIt->more() ) continue; - // const SMDS_MeshElement* e = elemIt->next(); - // if ( !e || e->IsQuadratic() ) - // continue; + // void makeQuadratic( const TopTools_IndexedMapOfShape& shapes, + // SMESH_Mesh* mesh ) + // { + // for ( int i = 1; i <= shapes.Extent(); ++i ) + // { + // SMESHDS_SubMesh* smDS = mesh->GetMeshDS()->MeshElements( shapes(i) ); + // if ( !smDS ) continue; + // SMDS_ElemIteratorPtr elemIt = smDS->GetElements(); + // if ( !elemIt->more() ) continue; + // const SMDS_MeshElement* e = elemIt->next(); + // if ( !e || e->IsQuadratic() ) + // continue; + + // TIDSortedElemSet elems; + // elems.insert( e ); + // while ( elemIt->more() ) + // elems.insert( elems.end(), elemIt->next() ); + + // SMESH_MeshEditor( mesh ).ConvertToQuadratic( /*3d=*/false, elems, /*biQuad=*/false ); + // } + // } + + //================================================================================ + /*! + * \brief Restrict size of elements on the given edge + */ + //================================================================================ + + void setLocalSize(const TopoDS_Edge& edge, + double size, + netgen::Mesh& mesh, + const bool overrideMinH = true) + { + if ( size <= std::numeric_limits::min() ) + return; + Standard_Real u1, u2; + Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, u1, u2); + if ( curve.IsNull() ) + { + TopoDS_Iterator vIt( edge ); + if ( !vIt.More() ) return; + gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( vIt.Value() )); + NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size, overrideMinH ); + } + else + { + const int nb = (int)( 1.5 * SMESH_Algo::EdgeLength( edge ) / size ); + Standard_Real delta = (u2-u1)/nb; + for(int i=0; iValue(u); + NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size, overrideMinH ); + netgen::Point3d pi(p.X(), p.Y(), p.Z()); + double resultSize = mesh.GetH(pi); + if ( resultSize - size > 0.1*size ) + // netgen does restriction iff oldH/newH > 1.2 (localh.cpp:136) + NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), resultSize/1.201, overrideMinH ); + } + } + } + + //================================================================================ + /*! + * \brief Return triangle size for a given chordalError and radius of curvature + */ + //================================================================================ + + double elemSizeForChordalError( double chordalError, double radius ) + { + if ( 2 * radius < chordalError ) + return 1.5 * radius; + return Sqrt( 3 ) * Sqrt( chordalError * ( 2 * radius - chordalError )); + } + + //============================================================================= + /*! + * + */ + //============================================================================= + + void setLocalSize(const TopoDS_Shape& GeomShape, double LocalSize) + { + if ( GeomShape.IsNull() ) return; + TopAbs_ShapeEnum GeomType = GeomShape.ShapeType(); + if (GeomType == TopAbs_COMPOUND) { + for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()) { + setLocalSize(it.Value(), LocalSize); + } + return; + } + int key; + if (! ShapesWithLocalSize.Contains(GeomShape)) + key = ShapesWithLocalSize.Add(GeomShape); + else + key = ShapesWithLocalSize.FindIndex(GeomShape); + if (GeomType == TopAbs_VERTEX) { + VertexId2LocalSize[key] = LocalSize; + } else if (GeomType == TopAbs_EDGE) { + EdgeId2LocalSize[key] = LocalSize; + } else if (GeomType == TopAbs_FACE) { + FaceId2LocalSize[key] = LocalSize; + } else if (GeomType == TopAbs_SOLID) { + SolidId2LocalSize[key] = LocalSize; + } + return; + } + + //================================================================================ + /*! + * \brief Return faceNgID or faceNgID-1 depending on side the given proxy face lies + * \param [in] f - proxy face + * \param [in] solidSMDSIDs - IDs of SOLIDs sharing the FACE on which face lies + * \param [in] faceNgID - NETGEN ID of the FACE + * \return int - NETGEN ID of the FACE + */ + //================================================================================ + + int getFaceNgID( const SMDS_MeshElement* face, + const int * solidSMDSIDs, + const int faceNgID ) + { + for ( int i = 0; i < 3; ++i ) + { + const SMDS_MeshNode* n = face->GetNode( i ); + const int shapeID = n->GetShapeID(); + if ( shapeID == solidSMDSIDs[0] ) + return faceNgID - 1; + if ( shapeID == solidSMDSIDs[1] ) + return faceNgID; + } + std::vector fNodes( face->begin_nodes(), face->end_nodes() ); + std::vector vols; + if ( SMDS_Mesh::GetElementsByNodes( fNodes, vols, SMDSAbs_Volume )) + for ( size_t i = 0; i < vols.size(); ++i ) + { + const int shapeID = vols[i]->GetShapeID(); + if ( shapeID == solidSMDSIDs[0] ) + return faceNgID - 1; + if ( shapeID == solidSMDSIDs[1] ) + return faceNgID; + } + return faceNgID; + } + +} // namespace + +//============================================================================= +/*! + * + */ +//============================================================================= + +NETGENPlugin_Mesher::NETGENPlugin_Mesher (SMESH_Mesh* mesh, + const TopoDS_Shape& aShape, + const bool isVolume) + : _mesh (mesh), + _shape (aShape), + _isVolume(isVolume), + _optimize(true), + _fineness(NETGENPlugin_Hypothesis::GetDefaultFineness()), + _isViscousLayers2D(false), + _chordalError(-1), // means disabled + _ngMesh(NULL), + _occgeom(NULL), + _curShapeIndex(-1), + _progressTic(1), + _totalTime(1.0), + _simpleHyp(NULL), + _viscousLayersHyp(NULL), + _ptrToMe(NULL) +{ + SetDefaultParameters(); + ShapesWithLocalSize.Clear(); + VertexId2LocalSize.clear(); + EdgeId2LocalSize.clear(); + FaceId2LocalSize.clear(); + SolidId2LocalSize.clear(); + ControlPoints.clear(); + ShapesWithControlPoints.clear(); +} + +//================================================================================ +/*! + * Destructor + */ +//================================================================================ + +NETGENPlugin_Mesher::~NETGENPlugin_Mesher() +{ + if ( _ptrToMe ) + *_ptrToMe = NULL; + _ptrToMe = 0; + _ngMesh = NULL; +} + +//================================================================================ +/*! + * Set pointer to NETGENPlugin_Mesher* field of the holder, that will be + * nullified at destruction of this + */ +//================================================================================ + +void NETGENPlugin_Mesher::SetSelfPointer( NETGENPlugin_Mesher ** ptr ) +{ + if ( _ptrToMe ) + *_ptrToMe = NULL; + + _ptrToMe = ptr; + + if ( _ptrToMe ) + *_ptrToMe = this; +} + +//================================================================================ +/*! + * \brief Initialize global NETGEN parameters with default values + */ +//================================================================================ + +void NETGENPlugin_Mesher::SetDefaultParameters() +{ + netgen::MeshingParameters& mparams = netgen::mparam; + mparams = netgen::MeshingParameters(); + // maximal mesh edge size + mparams.maxh = 0;//NETGENPlugin_Hypothesis::GetDefaultMaxSize(); + mparams.minh = 0; + // minimal number of segments per edge + mparams.segmentsperedge = NETGENPlugin_Hypothesis::GetDefaultNbSegPerEdge(); + // rate of growth of size between elements + mparams.grading = NETGENPlugin_Hypothesis::GetDefaultGrowthRate(); + // safety factor for curvatures (elements per radius) + mparams.curvaturesafety = NETGENPlugin_Hypothesis::GetDefaultNbSegPerRadius(); + // create elements of second order + mparams.secondorder = NETGENPlugin_Hypothesis::GetDefaultSecondOrder(); + // quad-dominated surface meshing + if (_isVolume) + mparams.quad = 0; + else + mparams.quad = NETGENPlugin_Hypothesis_2D::GetDefaultQuadAllowed(); + _fineness = NETGENPlugin_Hypothesis::GetDefaultFineness(); + mparams.uselocalh = NETGENPlugin_Hypothesis::GetDefaultSurfaceCurvature(); + netgen::merge_solids = NETGENPlugin_Hypothesis::GetDefaultFuseEdges(); + +#ifdef NETGEN_V6 - // TIDSortedElemSet elems; - // elems.insert( e ); - // while ( elemIt->more() ) - // elems.insert( elems.end(), elemIt->next() ); + mparams.nthreads = std::thread::hardware_concurrency(); - // SMESH_MeshEditor( mesh ).ConvertToQuadratic( /*3d=*/false, elems, /*biQuad=*/false ); - // } - // } + if ( getenv( "SALOME_NETGEN_DISABLE_MULTITHREADING" )) + { + mparams.nthreads = 1; + mparams.parallel_meshing = false; + } - //================================================================================ - /*! - * \brief Restrict size of elements on the given edge - */ - //================================================================================ +#endif +} - void setLocalSize(const TopoDS_Edge& edge, - double size, - netgen::Mesh& mesh, - const bool overrideMinH = true) +//============================================================================= +/*! + * Pass parameters to NETGEN + */ +//============================================================================= +void NETGENPlugin_Mesher::SetParameters(const NETGENPlugin_Hypothesis* hyp) +{ + if (hyp) { - if ( size <= std::numeric_limits::min() ) - return; - Standard_Real u1, u2; - Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, u1, u2); - if ( curve.IsNull() ) - { - TopoDS_Iterator vIt( edge ); - if ( !vIt.More() ) return; - gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( vIt.Value() )); - NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size, overrideMinH ); - } - else + netgen::MeshingParameters& mparams = netgen::mparam; + // Initialize global NETGEN parameters: + // maximal mesh segment size + mparams.maxh = hyp->GetMaxSize(); + // maximal mesh element linear size + mparams.minh = hyp->GetMinSize(); + // minimal number of segments per edge + mparams.segmentsperedge = hyp->GetNbSegPerEdge(); + // rate of growth of size between elements + mparams.grading = hyp->GetGrowthRate(); + // safety factor for curvatures (elements per radius) + mparams.curvaturesafety = hyp->GetNbSegPerRadius(); + // create elements of second order + mparams.secondorder = hyp->GetSecondOrder() ? 1 : 0; + // quad-dominated surface meshing + mparams.quad = hyp->GetQuadAllowed() ? 1 : 0; + _optimize = hyp->GetOptimize(); + _fineness = hyp->GetFineness(); + mparams.uselocalh = hyp->GetSurfaceCurvature(); + netgen::merge_solids = hyp->GetFuseEdges(); + _chordalError = hyp->GetChordalErrorEnabled() ? hyp->GetChordalError() : -1.; + mparams.optsteps2d = _optimize ? hyp->GetNbSurfOptSteps() : 0; + mparams.optsteps3d = _optimize ? hyp->GetNbVolOptSteps() : 0; + mparams.elsizeweight = hyp->GetElemSizeWeight(); + mparams.opterrpow = hyp->GetWorstElemMeasure(); + mparams.delaunay = hyp->GetUseDelauney(); + mparams.checkoverlap = hyp->GetCheckOverlapping(); + mparams.checkchartboundary = hyp->GetCheckChartBoundary(); + _simpleHyp = NULL; + // mesh size file +#ifdef NETGEN_V6 + // std::string + mparams.meshsizefilename = hyp->GetMeshSizeFile(); +#else + // const char* + mparams.meshsizefilename= hyp->GetMeshSizeFile().empty() ? 0 : hyp->GetMeshSizeFile().c_str(); +#endif + const NETGENPlugin_Hypothesis::TLocalSize& localSizes = hyp->GetLocalSizesAndEntries(); + if ( !localSizes.empty() ) { - const int nb = (int)( 1.5 * SMESH_Algo::EdgeLength( edge ) / size ); - Standard_Real delta = (u2-u1)/nb; - for(int i=0; iValue(u); - NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size, overrideMinH ); - netgen::Point3d pi(p.X(), p.Y(), p.Z()); - double resultSize = mesh.GetH(pi); - if ( resultSize - size > 0.1*size ) - // netgen does restriction iff oldH/newH > 1.2 (localh.cpp:136) - NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), resultSize/1.201, overrideMinH ); + std::string entry = (*it).first; + double val = (*it).second; + // -- + GEOM::GEOM_Object_var aGeomObj; + SALOMEDS::SObject_var aSObj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->FindObjectID( entry.c_str() ); + if ( !aSObj->_is_nil() ) { + CORBA::Object_var obj = aSObj->GetObject(); + aGeomObj = GEOM::GEOM_Object::_narrow(obj); + aSObj->UnRegister(); + } + TopoDS_Shape S = smeshGen_i->GeomObjectToShape( aGeomObj.in() ); + setLocalSize(S, val); } } } - //================================================================================ - /*! - * \brief Return triangle size for a given chordalError and radius of curvature - */ - //================================================================================ +#ifdef NETGEN_V6 - double elemSizeForChordalError( double chordalError, double radius ) - { - if ( 2 * radius < chordalError ) - return 1.5 * radius; - return Sqrt( 3 ) * Sqrt( chordalError * ( 2 * radius - chordalError )); - } + netgen::mparam.closeedgefac = 2; -} // namespace +#endif +} + +//============================================================================= +/*! + * Pass simple parameters to NETGEN + */ +//============================================================================= + +void NETGENPlugin_Mesher::SetParameters(const NETGENPlugin_SimpleHypothesis_2D* hyp) +{ + _simpleHyp = hyp; + if ( _simpleHyp ) + SetDefaultParameters(); +} + +//================================================================================ +/*! + * \brief Store a Viscous Layers hypothesis + */ +//================================================================================ + +void NETGENPlugin_Mesher::SetParameters(const StdMeshers_ViscousLayers* hyp ) +{ + _viscousLayersHyp = hyp; +} //================================================================================ /*! @@ -693,7 +749,11 @@ void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo, int faceNgID = occgeo.fmap.FindIndex(shape); if ( faceNgID >= 1 ) { +#ifdef NETGEN_V6 + occgeo.SetFaceMaxH(faceNgID-1, val, netgen::mparam); +#else occgeo.SetFaceMaxH(faceNgID, val); +#endif for ( TopExp_Explorer edgeExp( shape, TopAbs_EDGE ); edgeExp.More(); edgeExp.Next() ) setLocalSize( TopoDS::Edge( edgeExp.Current() ), val, ngMesh ); } @@ -758,7 +818,11 @@ void NETGENPlugin_Mesher::SetLocalSizeForChordalError( netgen::OCCGeometry& occg surfProp.SetParameters( 0, 0 ); double maxCurv = Max( Abs( surfProp.MaxCurvature()), Abs( surfProp.MinCurvature() )); double size = elemSizeForChordalError( _chordalError, 1 / maxCurv ); +#ifdef NETGEN_V6 + occgeo.SetFaceMaxH( i-1, size * sizeCoef, netgen::mparam ); +#else occgeo.SetFaceMaxH( i, size * sizeCoef ); +#endif // limit size one edges TopTools_MapOfShape edgeMap; for ( TopExp_Explorer eExp( face, TopAbs_EDGE ); eExp.More(); eExp.Next() ) @@ -924,7 +988,7 @@ void NETGENPlugin_Mesher::PrepareOCCgeometry(netgen::OCCGeometry& occgeo, if ( shape.ShapeType() != TopAbs_VERTEX ) shape = subShapes( subShapes.FindIndex( shape ));// shape -> index -> oriented shape if ( shape.Orientation() >= TopAbs_INTERNAL ) - shape.Orientation( TopAbs_FORWARD ); // isuue 0020676 + shape.Orientation( TopAbs_FORWARD ); // issue 0020676 switch ( shape.ShapeType() ) { case TopAbs_FACE : occgeo.fmap.Add( shape ); break; case TopAbs_EDGE : occgeo.emap.Add( shape ); break; @@ -1053,6 +1117,7 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, set< SMESH_subMesh* > computedSM( meshedSM.begin(), meshedSM.end() ); SMESH_MesherHelper helper (*_mesh); + SMESHDS_Mesh* meshDS = _mesh->GetMeshDS(); int faceNgID = ngMesh.GetNFD(); @@ -1082,7 +1147,7 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, if ( faceNgID < 1 ) continue; // meshed face - int faceSMDSId = helper.GetMeshDS()->ShapeToIndex( *anc ); + int faceSMDSId = meshDS->ShapeToIndex( *anc ); if ( visitedEdgeSM2Faces[ sm ].count( faceSMDSId )) continue; // already treated EDGE @@ -1110,12 +1175,12 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, bool isForwad = ( fOri == eNotSeam.Orientation() || fOri >= TopAbs_INTERNAL ); // get all nodes from connected - const bool isQuad = smDS->IsQuadratic(); - StdMeshers_FaceSide fSide( face, edges, _mesh, isForwad, isQuad, &helper ); + const bool skipMedium = netgen::mparam.secondorder;//smDS->IsQuadratic(); + StdMeshers_FaceSide fSide( face, edges, _mesh, isForwad, skipMedium, &helper ); const vector& points = fSide.GetUVPtStruct(); if ( points.empty() ) return false; // invalid node params? - int i, nbSeg = fSide.NbSegments(); + smIdType i, nbSeg = fSide.NbSegments(); // remember EDGEs of fSide to treat only once for ( int iE = 0; iE < fSide.NbEdges(); ++iE ) @@ -1136,7 +1201,7 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, if ( p1.node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX ) //an EDGE begins { isSeam = false; - if ( helper.IsRealSeam( p1.node->getshapeId() )) + if ( helper.IsRealSeam( p1.node->GetShapeID() )) { TopoDS_Edge e = fSide.Edge( fSide.EdgeIndex( 0.5 * ( p1.normParam + p2.normParam ))); isSeam = helper.IsRealSeam( e ); @@ -1171,7 +1236,7 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, RestrictLocalSize( ngMesh, 0.5*(np1+np2), (np1-np2).Modulus() ); #ifdef DUMP_SEGMENTS - cout << "Segment: " << seg.edgenr << " on SMESH face " << helper.GetMeshDS()->ShapeToIndex( face ) << endl + cout << "Segment: " << seg.edgenr << " on SMESH face " << meshDS->ShapeToIndex( face ) << endl << "\tface index: " << seg.si << endl << "\tp1: " << seg[0] << endl << "\tp2: " << seg[1] << endl @@ -1238,7 +1303,8 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, bool isInternalFace = ( geomFace.Orientation() == TopAbs_INTERNAL ); // Find solids the geomFace bounds - int solidID1 = 0, solidID2 = 0; + int solidID1 = 0, solidID2 = 0; // ng IDs + int solidSMDSIDs[2] = { 0,0 }; // smds IDs { PShapeIteratorPtr solidIt = helper.GetAncestors( geomFace, *sm->GetFather(), TopAbs_SOLID); while ( const TopoDS_Shape * solid = solidIt->next() ) @@ -1246,13 +1312,14 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, int id = occgeom.somap.FindIndex ( *solid ); if ( solidID1 && id != solidID1 ) solidID2 = id; else solidID1 = id; + if ( id ) solidSMDSIDs[ bool( solidSMDSIDs[0] )] = meshDS->ShapeToIndex( *solid ); } } + bool isShrunk = true; if ( proxyMesh && proxyMesh->GetProxySubMesh( geomFace )) { // if a proxy sub-mesh contains temporary faces, then these faces // should be used to mesh only one SOLID - bool hasTmp = false; smDS = proxyMesh->GetSubMesh( geomFace ); SMDS_ElemIteratorPtr faces = smDS->GetElements(); while ( faces->more() ) @@ -1260,13 +1327,17 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, const SMDS_MeshElement* f = faces->next(); if ( proxyMesh->IsTemporary( f )) { - hasTmp = true; + isShrunk = false; + if ( solidSMDSIDs[1] && proxyMesh->HasPrismsOnTwoSides( meshDS->MeshElements( geomFace ))) + break; + else + solidSMDSIDs[1] = 0; std::vector fNodes( f->begin_nodes(), f->end_nodes() ); std::vector vols; - if ( _mesh->GetMeshDS()->GetElementsByNodes( fNodes, vols, SMDSAbs_Volume ) == 1 ) + if ( meshDS->GetElementsByNodes( fNodes, vols, SMDSAbs_Volume ) == 1 ) { - int geomID = vols[0]->getshapeId(); - const TopoDS_Shape& solid = helper.GetMeshDS()->IndexToShape( geomID ); + int geomID = vols[0]->GetShapeID(); + const TopoDS_Shape& solid = meshDS->IndexToShape( geomID ); if ( !solid.IsNull() ) solidID1 = occgeom.somap.FindIndex ( solid ); solidID2 = 0; @@ -1274,9 +1345,8 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, } } } - // exclude faces generated by NETGEN from computation of 3D mesh const int fID = occgeom.fmap.FindIndex( geomFace ); - if ( !hasTmp ) // shrunk mesh + if ( isShrunk ) // shrunk mesh { // move netgen points according to moved nodes SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true); @@ -1311,6 +1381,7 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, } } } + // exclude faces generated by NETGEN from computation of 3D mesh //if ( hasTmp ) { faceNgID++; @@ -1322,11 +1393,26 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, const_cast< netgen::Element2d& >( elem ).SetIndex( faceNgID ); } } + } // if proxy + else + { + solidSMDSIDs[1] = 0; } + const bool hasVLOn2Sides = ( solidSMDSIDs[1] > 0 && !isShrunk ); + // Add ng face descriptors of meshed faces faceNgID++; - ngMesh.AddFaceDescriptor( netgen::FaceDescriptor( faceNgID, solidID1, solidID2, 0 )); - + if ( hasVLOn2Sides ) + { + // viscous layers are on two sides of the FACE + ngMesh.AddFaceDescriptor( netgen::FaceDescriptor( faceNgID, solidID1, 0, 0 )); + faceNgID++; + ngMesh.AddFaceDescriptor( netgen::FaceDescriptor( faceNgID, 0, solidID2, 0 )); + } + else + { + ngMesh.AddFaceDescriptor( netgen::FaceDescriptor( faceNgID, solidID1, solidID2, 0 )); + } // if second oreder is required, even already meshed faces must be passed to NETGEN int fID = occgeom.fmap.Add( geomFace ); if ( occgeom.facemeshstatus.Size() < fID ) occgeom.facemeshstatus.SetSize( fID ); @@ -1362,7 +1448,7 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, SMESH_TNodeXYZ xyz[3]; #ifdef DUMP_TRIANGLES - cout << "SMESH face " << helper.GetMeshDS()->ShapeToIndex( geomFace ) + cout << "SMESH face " << meshDS->ShapeToIndex( geomFace ) << " internal="<next(); if ( f->NbNodes() % 3 != 0 ) // not triangle { - PShapeIteratorPtr solidIt=helper.GetAncestors(geomFace,*sm->GetFather(),TopAbs_SOLID); + PShapeIteratorPtr solidIt = helper.GetAncestors( geomFace,*sm->GetFather(),TopAbs_SOLID); if ( const TopoDS_Shape * solid = solidIt->next() ) sm = _mesh->GetSubMesh( *solid ); - SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); - smError.reset( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"Not triangle sub-mesh")); - smError->myBadElements.push_back( f ); + SMESH_BadInputElements* badElems = + new SMESH_BadInputElements( meshDS, COMPERR_BAD_INPUT_MESH, "Not triangle sub-mesh"); + badElems->add( f ); + sm->GetComputeError().reset( badElems ); return false; } + if ( hasVLOn2Sides ) + tri.SetIndex( getFaceNgID( f, solidSMDSIDs, faceNgID )); + for ( int i = 0; i < 3; ++i ) { const SMDS_MeshNode* node = f->GetNode( i ), * inFaceNode=0; xyz[i].Set( node ); // get node UV on face - int shapeID = node->getshapeId(); + int shapeID = node->GetShapeID(); if ( helper.IsSeamShape( shapeID )) { - if ( helper.IsSeamShape( f->GetNodeWrap( i+1 )->getshapeId() )) + if ( helper.IsSeamShape( f->GetNodeWrap( i+1 )->GetShapeID() )) inFaceNode = f->GetNodeWrap( i-1 ); else inFaceNode = f->GetNodeWrap( i+1 ); @@ -1423,7 +1513,7 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom, cout << tri << endl; #endif } - } + } // loop on sub-mesh faces if ( quadHelper ) // remember medium nodes of sub-meshes { @@ -1540,7 +1630,7 @@ bool NETGENPlugin_Mesher::FixFaceMesh(const netgen::OCCGeometry& occgeom, //const TopoDS_Face& face = TopoDS::Face( occgeom.fmap( faceID )); // find free links on the FACE - NCollection_Map linkMap; + TLinkMap linkMap; for ( int iF = 1; iF <= ngMesh.GetNSE(); ++iF ) { const netgen::Element2d& elem = ngMesh.SurfaceElement(iF); @@ -1576,17 +1666,17 @@ bool NETGENPlugin_Mesher::FixFaceMesh(const netgen::OCCGeometry& occgeom, netgen::Element2d tri(3); tri.SetIndex ( faceID ); - NCollection_Map::Iterator linkIt( linkMap ); + TLinkMap::Iterator linkIt( linkMap ); Link link1 = linkIt.Value(); // look for a link connected to link1 - NCollection_Map::Iterator linkIt2 = linkIt; + TLinkMap::Iterator linkIt2 = linkIt; for ( linkIt2.Next(); linkIt2.More(); linkIt2.Next() ) { const Link& link2 = linkIt2.Value(); if ( link2.IsConnected( link1 )) { // look for a link connected to both link1 and link2 - NCollection_Map::Iterator linkIt3 = linkIt2; + TLinkMap::Iterator linkIt3 = linkIt2; for ( linkIt3.Next(); linkIt3.More(); linkIt3.Next() ) { const Link& link3 = linkIt3.Value(); @@ -1663,7 +1753,7 @@ namespace struct TIntVData { gp_XY uv; //!< UV in face parametric space - int ngId; //!< ng id of corrsponding node + int ngId; //!< ng id of corresponding node gp_XY uvClose; //!< UV of closest boundary node int ngIdClose; //!< ng id of closest boundary node }; @@ -1876,6 +1966,7 @@ void NETGENPlugin_Mesher::AddIntVerticesInFaces(const netgen::OCCGeometry& o } } + ngMesh.CalcSurfacesOfNode(); } //================================================================================ @@ -1897,7 +1988,7 @@ void NETGENPlugin_Mesher::AddIntVerticesInSolids(const netgen::OCCGeometry& ofstream py(DUMP_TRIANGLES_SCRIPT); py << "import SMESH"<< endl << "from salome.smesh import smeshBuilder"<getshapeId() )) + if ( subIDs.count( nodeVec[ngID]->GetShapeID() )) node2ngID.insert( make_pair( nodeVec[ngID], ngID )); } @@ -2186,7 +2277,7 @@ NETGENPlugin_Mesher::AddSegmentsToMesh(netgen::Mesh& ngMesh, { StdMeshers_FaceSidePtr wire = wires[ iW ]; const vector& uvPtVec = wire->GetUVPtStruct(); - const int nbSegments = wire->NbPoints() - 1; + const smIdType nbSegments = wire->NbPoints() - 1; // assure the 1st node to be in node2ngID, which is needed to correctly // "close chain of segments" (see below) in case if the 1st node is not @@ -2207,13 +2298,13 @@ NETGENPlugin_Mesher::AddSegmentsToMesh(netgen::Mesh& ngMesh, // Add the first point of a segment const SMDS_MeshNode * n = uvPtVec[ i ].node; - const int posShapeID = n->getshapeId(); + const int posShapeID = n->GetShapeID(); bool onVertex = ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX ); bool onEdge = ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_EDGE ); // skip nodes on degenerated edges if ( helper.IsDegenShape( posShapeID ) && - helper.IsDegenShape( uvPtVec[ i+1 ].node->getshapeId() )) + helper.IsDegenShape( uvPtVec[ i+1 ].node->GetShapeID() )) continue; int ngID1 = ngMesh.GetNP() + 1, ngID2 = ngID1+1; @@ -2278,8 +2369,8 @@ NETGENPlugin_Mesher::AddSegmentsToMesh(netgen::Mesh& ngMesh, SMESH_TNodeXYZ np1( n ), np2( uvPtVec[ i+1 ].node ); // get an average size of adjacent segments to avoid sharp change of // element size (regression on issue 0020452, note 0010898) - int iPrev = SMESH_MesherHelper::WrapIndex( i-1, nbSegments ); - int iNext = SMESH_MesherHelper::WrapIndex( i+1, nbSegments ); + int iPrev = SMESH_MesherHelper::WrapIndex( i-1, (int) nbSegments ); + int iNext = SMESH_MesherHelper::WrapIndex( i+1, (int) nbSegments ); double sumH = segLen[ iPrev ] + segLen[ i ] + segLen[ iNext ]; int nbSeg = ( int( segLen[ iPrev ] > sumH / 100.) + int( segLen[ i ] > sumH / 100.) + @@ -2392,17 +2483,17 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo, if ( quadHelper && !quadHelper->GetIsQuadratic() && quadHelper->GetTLinkNodeMap().empty() ) quadHelper = 0; - int i, nbInitNod = initState._nbNodes; + int ngID, nbInitNod = initState._nbNodes; if ( initState._elementsRemoved ) { // PAL23427. Update nodeVec to track removal of netgen free points as a result // of removal of faces in FillNgMesh() in the case of a shrunk sub-mesh - int ngID, nodeVecSize = nodeVec.size(); + size_t i, nodeVecSize = nodeVec.size(); const double eps = std::numeric_limits::min(); - for ( ngID = i = 1; i < nodeVecSize; ++ngID, ++i ) + for ( i = ngID = 1; i < nodeVecSize; ++ngID, ++i ) { gp_Pnt ngPnt( NGPOINT_COORDS( ngMesh.Point( ngID ))); - gp_Pnt node ( SMESH_NodeXYZ ( nodeVec[ i ])); + gp_Pnt node ( SMESH_NodeXYZ (nodeVec_ACCESS(i) )); if ( ngPnt.SquareDistance( node ) < eps ) { nodeVec[ ngID ] = nodeVec[ i ]; @@ -2419,8 +2510,9 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo, // Create and insert nodes into nodeVec // ------------------------------------- - nodeVec.resize( nbNod + 1 ); - for ( i = nbInitNod+1; i <= nbNod; ++i ) + if ( nbNod > nbInitNod ) + nodeVec.resize( nbNod + 1 ); + for ( int i = nbInitNod+1; i <= nbNod; ++i ) { const netgen::MeshPoint& ngPoint = ngMesh.Point(i); SMDS_MeshNode* node = NULL; @@ -2455,7 +2547,7 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo, // ------------------------------------------- int nbInitSeg = initState._nbSegments; - for (i = nbInitSeg+1; i <= nbSeg; ++i ) + for ( int i = nbInitSeg+1; i <= nbSeg; ++i ) { const netgen::Segment& seg = ngMesh.LineSegment(i); TopoDS_Edge aEdge; @@ -2484,7 +2576,7 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo, { param = param2 * 0.5; } - if (!aEdge.IsNull() && nodeVec_ACCESS(pind)->getshapeId() < 1) + if (!aEdge.IsNull() && nodeVec_ACCESS(pind)->GetShapeID() < 1) { meshDS->SetNodeOnEdge(nodeVec_ACCESS(pind), aEdge, param); } @@ -2516,7 +2608,7 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo, nbSeg = nbFac = nbVol = 0; break; } - if ( !aEdge.IsNull() && edge->getshapeId() < 1 ) + if ( !aEdge.IsNull() && edge->GetShapeID() < 1 ) meshDS->SetMeshElementOnShape(edge, aEdge); } else if ( comment.empty() ) @@ -2537,7 +2629,7 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo, ngMesh.AddFaceDescriptor (netgen::FaceDescriptor(quadFaceID, /*solid1=*/0, /*solid2=*/0, 0)); vector nodes; - for (i = nbInitFac+1; i <= nbFac; ++i ) + for ( int i = nbInitFac+1; i <= nbFac; ++i ) { const netgen::Element2d& elem = ngMesh.SurfaceElement(i); const int aGeomFaceInd = elem.GetIndex(); @@ -2553,7 +2645,7 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo, if ( SMDS_MeshNode* node = nodeVec_ACCESS(pind)) { nodes.push_back( node ); - if (!aFace.IsNull() && node->getshapeId() < 1) + if (!aFace.IsNull() && node->GetShapeID() < 1) { const netgen::PointGeomInfo& pgi = elem.GeomInfoPi(j); meshDS->SetNodeOnFace(node, aFace, pgi.u, pgi.v); @@ -2618,7 +2710,7 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo, // Create tetrahedra // ------------------ - for ( i = 1; i <= nbVol; ++i ) + for ( int i = 1; i <= nbVol; ++i ) { const netgen::Element& elem = ngMesh.VolumeElement(i); int aSolidInd = elem.GetIndex(); @@ -2634,7 +2726,7 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo, if ( SMDS_MeshNode* node = nodeVec_ACCESS(pind) ) { nodes.push_back(node); - if ( !aSolid.IsNull() && node->getshapeId() < 1 ) + if ( !aSolid.IsNull() && node->GetShapeID() < 1 ) meshDS->SetNodeInVolume(node, aSolid); } } @@ -2747,7 +2839,7 @@ namespace while ( nIt->more() ) { const SMDS_MeshNode* n = nIt->next(); - const TopoDS_Shape& s = mesh->IndexToShape( n->getshapeId() ); + const TopoDS_Shape& s = mesh->IndexToShape( n->GetShapeID() ); nbNodesOnSolid += ( !s.IsNull() && solidSubs.Contains( s )); if ( nbNodesOnSolid > 2 || nbNodesOnSolid == nbNodes) @@ -2841,19 +2933,14 @@ bool NETGENPlugin_Mesher::Compute() occgeo.face_maxh = mparams.maxh; // Let netgen create _ngMesh and calculate element size on not meshed shapes -#ifndef NETGEN_V5 - char *optstr = 0; -#endif int startWith = netgen::MESHCONST_ANALYSE; int endWith = netgen::MESHCONST_ANALYSE; try { OCC_CATCH_SIGNALS; -#ifdef NETGEN_V5 - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, mparams, startWith, endWith); -#else - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, startWith, endWith, optstr); -#endif + + err = ngLib.GenerateMesh(occgeo, startWith, endWith, _ngMesh); + if(netgen::multithread.terminate) return false; @@ -2866,7 +2953,12 @@ bool NETGENPlugin_Mesher::Compute() catch (netgen::NgException & ex) { comment << text(ex); - if ( mparams.meshsizefilename ) +#ifdef NETGEN_V6 + bool hasSizeFile = !mparams.meshsizefilename.empty(); +#else + bool hasSizeFile = mparams.meshsizefilename; +#endif + if ( hasSizeFile ) throw SMESH_ComputeError(COMPERR_BAD_PARMETERS, comment ); } err = 0; //- MESHCONST_ANALYSE isn't so important step @@ -2883,7 +2975,7 @@ bool NETGENPlugin_Mesher::Compute() { // Pass 1D simple parameters to NETGEN // -------------------------------- - int nbSeg = _simpleHyp->GetNumberOfSegments(); + double nbSeg = (double) _simpleHyp->GetNumberOfSegments(); double segSize = _simpleHyp->GetLocalLength(); for ( int iE = 1; iE <= occgeo.emap.Extent(); ++iE ) { @@ -2919,12 +3011,9 @@ bool NETGENPlugin_Mesher::Compute() //OCCSetLocalMeshSize(intOccgeo, *_ngMesh); it deletes _ngMesh->localH // let netgen create a temporary mesh -#ifdef NETGEN_V5 - netgen::OCCGenerateMesh(intOccgeo, tmpNgMesh, mparams, startWith, endWith); -#else - netgen::OCCGenerateMesh(intOccgeo, tmpNgMesh, startWith, endWith, optstr); -#endif - if(netgen::multithread.terminate) + ngLib.GenerateMesh(intOccgeo, startWith, endWith, tmpNgMesh); + + if ( netgen::multithread.terminate ) return false; // copy LocalH from the main to temporary mesh @@ -2932,11 +3021,8 @@ bool NETGENPlugin_Mesher::Compute() // compute mesh on internal edges startWith = endWith = netgen::MESHCONST_MESHEDGES; -#ifdef NETGEN_V5 - err = netgen::OCCGenerateMesh(intOccgeo, tmpNgMesh, mparams, startWith, endWith); -#else - err = netgen::OCCGenerateMesh(intOccgeo, tmpNgMesh, startWith, endWith, optstr); -#endif + err = ngLib.GenerateMesh(intOccgeo, startWith, endWith, tmpNgMesh); + comment << text(err); } catch (Standard_Failure& ex) @@ -2969,12 +3055,10 @@ bool NETGENPlugin_Mesher::Compute() try { OCC_CATCH_SIGNALS; -#ifdef NETGEN_V5 - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, mparams, startWith, endWith); -#else - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, startWith, endWith, optstr); -#endif - if(netgen::multithread.terminate) + + err = ngLib.GenerateMesh(occgeo, startWith, endWith); + + if ( netgen::multithread.terminate ) return false; comment << text(err); @@ -3040,8 +3124,9 @@ bool NETGENPlugin_Mesher::Compute() } // Build viscous layers - if ( _isViscousLayers2D || - StdMeshers_ViscousLayers2D::HasProxyMesh( TopoDS::Face( occgeo.fmap(1) ), *_mesh )) + if (( _isViscousLayers2D ) || + ( !occgeo.fmap.IsEmpty() && + StdMeshers_ViscousLayers2D::HasProxyMesh( TopoDS::Face( occgeo.fmap(1) ), *_mesh ))) { if ( !internals.hasInternalVertexInFace() ) { FillSMesh( occgeo, *_ngMesh, initState, *_mesh, nodeVec, comment ); @@ -3082,12 +3167,10 @@ bool NETGENPlugin_Mesher::Compute() try { OCC_CATCH_SIGNALS; -#ifdef NETGEN_V5 - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, mparams, startWith, endWith); -#else - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, startWith, endWith, optstr); -#endif - if(netgen::multithread.terminate) + + err = ngLib.GenerateMesh(occgeo, startWith, endWith); + + if ( netgen::multithread.terminate ) return false; comment << text (err); @@ -3097,7 +3180,7 @@ bool NETGENPlugin_Mesher::Compute() comment << text(ex); //err = 1; -- try to make volumes anyway } - catch (netgen::NgException exc) + catch (netgen::NgException& exc) { comment << text(exc); //err = 1; -- try to make volumes anyway @@ -3119,7 +3202,7 @@ bool NETGENPlugin_Mesher::Compute() FillSMesh( occgeo, *_ngMesh, initState, *_mesh, nodeVec, comment, &quadHelper ); // compute prismatic boundary volumes - int nbQuad = _mesh->NbQuadrangles(); + smIdType nbQuad = _mesh->NbQuadrangles(); SMESH_ProxyMesh::Ptr viscousMesh; if ( _viscousLayersHyp ) { @@ -3163,7 +3246,7 @@ bool NETGENPlugin_Mesher::Compute() // fill _ngMesh with faces of sub-meshes err = ! ( FillNgMesh(occgeo, *_ngMesh, nodeVec, meshedSM[ MeshDim_2D ], &quadHelper)); initState = NETGENPlugin_ngMeshInfo(_ngMesh, /*checkRemovedElems=*/true); - // toPython( _ngMesh ); + // toPython( _ngMesh ) } if (!err && _isVolume) { @@ -3171,6 +3254,7 @@ bool NETGENPlugin_Mesher::Compute() const NETGENPlugin_SimpleHypothesis_3D* simple3d = dynamic_cast< const NETGENPlugin_SimpleHypothesis_3D* > ( _simpleHyp ); if ( simple3d ) { + _ngMesh->Compress(); if ( double vol = simple3d->GetMaxElementVolume() ) { // max volume mparams.maxh = pow( 72, 1/6. ) * pow( vol, 1/3. ); @@ -3182,11 +3266,7 @@ bool NETGENPlugin_Mesher::Compute() } _ngMesh->SetGlobalH (mparams.maxh); mparams.grading = 0.4; -#ifdef NETGEN_V5 - _ngMesh->CalcLocalH(mparams.grading); -#else - _ngMesh->CalcLocalH(); -#endif + ngLib.CalcLocalH( ngLib._ngMesh ); } // Care of vertices internal in solids and internal faces (issue 0020676) if ( internals.hasInternalVertexInSolid() || internals.hasInternalFaces() ) @@ -3205,26 +3285,24 @@ bool NETGENPlugin_Mesher::Compute() try { OCC_CATCH_SIGNALS; -#ifdef NETGEN_V5 - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, mparams, startWith, endWith); -#else - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, startWith, endWith, optstr); -#endif - if(netgen::multithread.terminate) + + err = ngLib.GenerateMesh(occgeo, startWith, endWith); + + if ( netgen::multithread.terminate ) return false; - if ( comment.empty() ) // do not overwrite a previos error + if ( comment.empty() ) // do not overwrite a previous error comment << text(err); } catch (Standard_Failure& ex) { - if ( comment.empty() ) // do not overwrite a previos error + if ( comment.empty() ) // do not overwrite a previous error comment << text(ex); err = 1; } - catch (netgen::NgException exc) + catch (netgen::NgException& exc) { - if ( comment.empty() ) // do not overwrite a previos error + if ( comment.empty() ) // do not overwrite a previous error comment << text(exc); err = 1; } @@ -3237,25 +3315,23 @@ bool NETGENPlugin_Mesher::Compute() try { OCC_CATCH_SIGNALS; -#ifdef NETGEN_V5 - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, mparams, startWith, endWith); -#else - err = netgen::OCCGenerateMesh(occgeo, _ngMesh, startWith, endWith, optstr); -#endif - if(netgen::multithread.terminate) + + err = ngLib.GenerateMesh(occgeo, startWith, endWith); + + if ( netgen::multithread.terminate ) return false; - if ( comment.empty() ) // do not overwrite a previos error + if ( comment.empty() ) // do not overwrite a previous error comment << text(err); } catch (Standard_Failure& ex) { - if ( comment.empty() ) // do not overwrite a previos error + if ( comment.empty() ) // do not overwrite a previous error comment << text(ex); } - catch (netgen::NgException exc) + catch (netgen::NgException& exc) { - if ( comment.empty() ) // do not overwrite a previos error + if ( comment.empty() ) // do not overwrite a previous error comment << text(exc); } } @@ -3272,13 +3348,19 @@ bool NETGENPlugin_Mesher::Compute() { const netgen::Segment & seg = _ngMesh->LineSegment (i); if ( seg.epgeominfo[ 0 ].edgenr == 0 ) + { _ngMesh->DeleteSegment( i ); + initState._nbSegments--; + } } _ngMesh->Compress(); } // convert to quadratic - netgen::OCCRefinementSurfaces ref (occgeo); - ref.MakeSecondOrder (*_ngMesh); +#ifdef NETGEN_V6 + occgeo.GetRefinement().MakeSecondOrder(*_ngMesh); +#else + netgen::OCCRefinementSurfaces(occgeo).MakeSecondOrder(*_ngMesh); +#endif // care of elements already loaded to SMESH // if ( initState._nbSegments > 0 ) @@ -3288,12 +3370,12 @@ bool NETGENPlugin_Mesher::Compute() } catch (Standard_Failure& ex) { - if ( comment.empty() ) // do not overwrite a previos error + if ( comment.empty() ) // do not overwrite a previous error comment << "Exception in netgen at passing to 2nd order "; } - catch (netgen::NgException exc) + catch (netgen::NgException& exc) { - if ( comment.empty() ) // do not overwrite a previos error + if ( comment.empty() ) // do not overwrite a previous error comment << exc.What(); } } @@ -3313,12 +3395,22 @@ bool NETGENPlugin_Mesher::Compute() FillSMesh( occgeo, *_ngMesh, initState, *_mesh, nodeVec, comment, &quadHelper ); if ( quadHelper.GetIsQuadratic() ) // remove free nodes + { for ( size_t i = 0; i < nodeVec.size(); ++i ) if ( nodeVec[i] && nodeVec[i]->NbInverseElements() == 0 ) + { _mesh->GetMeshDS()->RemoveFreeNode( nodeVec[i], 0, /*fromGroups=*/false ); + nodeVec[i]=0; + } + for ( size_t i = nodeVec.size()-1; i > 0; --i ) // remove trailing removed nodes + if ( !nodeVec[i] ) + nodeVec.resize( i ); + else + break; + } } SMESH_ComputeErrorPtr readErr = ReadErrors(nodeVec); - if ( readErr && !readErr->myBadElements.empty() ) + if ( readErr && readErr->HasBadElems() ) { error = readErr; if ( !comment.empty() && !readErr->myComment.empty() ) comment += "\n"; @@ -3368,21 +3460,22 @@ bool NETGENPlugin_Mesher::Compute() bool smComputed = nbVol && !sm->IsEmpty(); if ( smComputed && internals.hasInternalVertexInSolid( sm->GetId() )) { - int nbIntV = internals.getSolidsWithVertices().find( sm->GetId() )->second.size(); + size_t nbIntV = internals.getSolidsWithVertices().find( sm->GetId() )->second.size(); SMESHDS_SubMesh* smDS = sm->GetSubMeshDS(); - smComputed = ( smDS->NbElements() > 0 || smDS->NbNodes() > nbIntV ); + smComputed = ( smDS->NbElements() > 0 || smDS->NbNodes() > (smIdType) nbIntV ); } SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); if ( !smComputed && ( !smError || smError->IsOK() )) { - smError.reset( new SMESH_ComputeError( *error )); + smError = error; if ( nbVol && SMESH_Algo::GetMeshError( sm ) == SMESH_Algo::MEr_OK ) { smError->myName = COMPERR_WARNING; } - else if ( !smError->myBadElements.empty() ) // bad surface mesh + else if ( smError->HasBadElems() ) // bad surface mesh { - if ( !hasBadElemOnSolid( smError->myBadElements, sm )) + if ( !hasBadElemOnSolid + ( static_cast( smError.get() )->myBadElements, sm )) smError.reset(); } } @@ -3411,9 +3504,8 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) // Prepare OCC geometry // ------------------------- netgen::OCCGeometry occgeo; - list< SMESH_subMesh* > meshedSM[4]; // for 0-3 dimensions NETGENPlugin_Internals internals( *_mesh, _shape, _isVolume ); - PrepareOCCgeometry( occgeo, _shape, *_mesh, meshedSM, &internals ); + PrepareOCCgeometry( occgeo, _shape, *_mesh, 0, &internals ); bool tooManyElems = false; const int hugeNb = std::numeric_limits::max() / 100; @@ -3444,16 +3536,9 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) // let netgen create _ngMesh and calculate element size on not meshed shapes NETGENPlugin_NetgenLibWrapper ngLib; netgen::Mesh *ngMesh = NULL; -#ifndef NETGEN_V5 - char *optstr = 0; -#endif int startWith = netgen::MESHCONST_ANALYSE; int endWith = netgen::MESHCONST_MESHEDGES; -#ifdef NETGEN_V5 - int err = netgen::OCCGenerateMesh(occgeo, ngMesh, mparams, startWith, endWith); -#else - int err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr); -#endif + int err = ngLib.GenerateMesh(occgeo, startWith, endWith, ngMesh); if(netgen::multithread.terminate) return false; @@ -3485,7 +3570,7 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) // } // calculate total nb of segments and length of edges double fullLen = 0.0; - int fullNbSeg = 0; + smIdType fullNbSeg = 0; int entity = mparams.secondorder > 0 ? SMDSEntity_Quad_Edge : SMDSEntity_Edge; TopTools_DataMapOfShapeInteger Edge2NbSeg; for (TopExp_Explorer exp(_shape, TopAbs_EDGE); exp.More(); exp.Next()) @@ -3497,7 +3582,7 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) double aLen = SMESH_Algo::EdgeLength(E); fullLen += aLen; - vector& aVec = aResMap[_mesh->GetSubMesh(E)]; + vector& aVec = aResMap[_mesh->GetSubMesh(E)]; if ( aVec.empty() ) aVec.resize( SMDSEntity_Last, 0); else @@ -3505,7 +3590,7 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) } // store nb of segments computed by Netgen - NCollection_Map linkMap; + TLinkMap linkMap; for (int i = 1; i <= ngMesh->GetNSeg(); ++i ) { const netgen::Segment& seg = ngMesh->LineSegment(i); @@ -3514,7 +3599,7 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) int aGeomEdgeInd = seg.epgeominfo[0].edgenr; if (aGeomEdgeInd > 0 && aGeomEdgeInd <= occgeo.emap.Extent()) { - vector& aVec = aResMap[_mesh->GetSubMesh(occgeo.emap(aGeomEdgeInd))]; + vector& aVec = aResMap[_mesh->GetSubMesh(occgeo.emap(aGeomEdgeInd))]; aVec[ entity ]++; } } @@ -3522,12 +3607,12 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) TopTools_DataMapIteratorOfDataMapOfShapeInteger Edge2NbSegIt(Edge2NbSeg); for (; Edge2NbSegIt.More(); Edge2NbSegIt.Next()) { - vector& aVec = aResMap[_mesh->GetSubMesh(Edge2NbSegIt.Key())]; + vector& aVec = aResMap[_mesh->GetSubMesh(Edge2NbSegIt.Key())]; if ( aVec[ entity ] > 1 && aVec[ SMDSEntity_Node ] == 0 ) aVec[SMDSEntity_Node] = mparams.secondorder > 0 ? 2*aVec[ entity ]-1 : aVec[ entity ]-1; fullNbSeg += aVec[ entity ]; - Edge2NbSeg( Edge2NbSegIt.Key() ) = aVec[ entity ]; + Edge2NbSeg( Edge2NbSegIt.Key() ) = (int) aVec[ entity ]; } if ( fullNbSeg == 0 ) return false; @@ -3543,12 +3628,12 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) } else { // length from edges - mparams.maxh = fullLen/fullNbSeg; + mparams.maxh = fullLen / double( fullNbSeg ); mparams.grading = 0.2; // slow size growth } } mparams.maxh = min( mparams.maxh, occgeo.boundingbox.Diam()/2 ); - mparams.maxh = min( mparams.maxh, fullLen/fullNbSeg * (1. + mparams.grading)); + mparams.maxh = min( mparams.maxh, fullLen / double( fullNbSeg ) * (1. + mparams.grading)); for (TopExp_Explorer exp(_shape, TopAbs_FACE); exp.More(); exp.Next()) { @@ -3569,7 +3654,7 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) int nbFaces = tooManyElems ? hugeNb : int( 4*anArea / (mparams.maxh*mparams.maxh*sqrt(3.))); int nbNodes = tooManyElems ? hugeNb : (( nbFaces*3 - (nb1d-1)*2 ) / 6 + 1 ); - vector aVec(SMDSEntity_Last, 0); + vector aVec(SMDSEntity_Last, 0); if( mparams.secondorder > 0 ) { int nb1d_in = (nbFaces*3 - nb1d) / 2; aVec[SMDSEntity_Node] = nbNodes + nb1d_in; @@ -3599,7 +3684,7 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) // using previous length from faces } mparams.grading = 0.4; - mparams.maxh = min( mparams.maxh, fullLen/fullNbSeg * (1. + mparams.grading)); + mparams.maxh = min( mparams.maxh, fullLen / double( fullNbSeg ) * (1. + mparams.grading)); } GProp_GProps G; BRepGProp::VolumeProperties(_shape,G); @@ -3608,7 +3693,7 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) tooManyElems = tooManyElems || ( aVolume/hugeNb > tetrVol ); int nbVols = tooManyElems ? hugeNb : int(aVolume/tetrVol); int nb1d_in = int(( nbVols*6 - fullNbSeg ) / 6 ); - vector aVec(SMDSEntity_Last, 0 ); + vector aVec(SMDSEntity_Last, 0 ); if ( tooManyElems ) // avoid FPE { aVec[SMDSEntity_Node] = hugeNb; @@ -3632,7 +3717,7 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) return true; } -double NETGENPlugin_Mesher::GetProgress(const SMESH_Algo* holder, +double NETGENPlugin_Mesher::GetProgress(const SMESH_Algo* /*holder*/, const int * algoProgressTic, const double * algoProgress) const { @@ -3712,14 +3797,16 @@ double NETGENPlugin_Mesher::GetProgress(const SMESH_Algo* holder, SMESH_ComputeErrorPtr NETGENPlugin_Mesher::ReadErrors(const vector& nodeVec) { - SMESH_ComputeErrorPtr err = SMESH_ComputeError::New - (COMPERR_BAD_INPUT_MESH, "Some edges multiple times in surface mesh"); + if ( nodeVec.size() < 2 ) return SMESH_ComputeErrorPtr(); + SMESH_BadInputElements* err = + new SMESH_BadInputElements( nodeVec.back()->GetMesh(), COMPERR_BAD_INPUT_MESH, + "Some edges multiple times in surface mesh"); SMESH_File file("test.out"); vector two(2); vector three1(3), three2(3); const char* badEdgeStr = " multiple times in surface mesh"; - const int badEdgeStrLen = strlen( badEdgeStr ); - const int nbNodes = nodeVec.size(); + const int badEdgeStrLen = (int) strlen( badEdgeStr ); + const int nbNodes = (int) nodeVec.size(); while( !file.eof() ) { @@ -3729,7 +3816,7 @@ NETGENPlugin_Mesher::ReadErrors(const vector& nodeVec) two[0] < nbNodes && two[1] < nbNodes ) { err->myBadElements.push_back( new SMDS_LinearEdge( nodeVec[ two[0]], nodeVec[ two[1]] )); - file += badEdgeStrLen; + file += (int) badEdgeStrLen; } else if ( strncmp( file, "Intersecting: ", 14 ) == 0 ) { @@ -3745,7 +3832,7 @@ NETGENPlugin_Mesher::ReadErrors(const vector& nodeVec) ok = ok && file.getInts( three2 ); for ( int i = 0; ok && i < 3; ++i ) ok = ( three1[i] < nbNodes && nodeVec[ three1[i]]); - for ( int i = 0; ok && i < 3; ++i ) + for ( int i = 0; ok && i < 3; ++i ) ok = ( three2[i] < nbNodes && nodeVec[ three2[i]]); if ( ok ) { @@ -3773,7 +3860,7 @@ NETGENPlugin_Mesher::ReadErrors(const vector& nodeVec) if ( nbBadElems ) nbBadElems++; // avoid warning: variable set but not used #endif - return err; + return SMESH_ComputeErrorPtr( err ); } //================================================================================ @@ -3790,12 +3877,67 @@ void NETGENPlugin_Mesher::toPython( const netgen::Mesh* ngMesh ) ofstream outfile( pyFile, ios::out ); if ( !outfile ) return; - outfile << "import salome, SMESH" << endl - << "from salome.smesh import smeshBuilder" << endl - << "smesh = smeshBuilder.New(salome.myStudy)" << endl - << "mesh = smesh.Mesh()" << endl << endl; + outfile << "import salome, SMESH" << std::endl + << "from salome.smesh import smeshBuilder" << std::endl + << "smesh = smeshBuilder.New()" << std::endl + << "mesh = smesh.Mesh()" << std::endl << std::endl; using namespace netgen; + +#ifdef NETGEN_V6 + + for ( int i = 1; i <= ngMesh->GetNP(); i++) + { + const Point3d & p = ngMesh->Point(i); + outfile << "mesh.AddNode( "; + outfile << p.X() << ", "; + outfile << p.Y() << ", "; + outfile << p.Z() << ") ## "<< i << std::endl; + } + + int nbDom = ngMesh->GetNDomains(); + for ( int i = 0; i < nbDom; ++i ) + outfile<< "grp" << i+1 << " = mesh.CreateEmptyGroup( SMESH.FACE, 'domain"<< i+1 << "')"<< std::endl; + + int nbDel = 0; + for (int i = 1; i <= ngMesh->GetNSE(); i++) + { + outfile << "mesh.AddFace([ "; + Element2d sel = ngMesh->SurfaceElement(i); + for (int j = 1; j <= sel.GetNP(); j++) + outfile << sel.PNum(j) << ( j < sel.GetNP() ? ", " : " ])"); + if ( sel.IsDeleted() ) outfile << " ## IsDeleted "; + outfile << std::endl; + nbDel += sel.IsDeleted(); + + if (sel.GetIndex()) + { + if ( int dom1 = ngMesh->GetFaceDescriptor(sel.GetIndex ()).DomainIn()) + outfile << "grp"<< dom1 <<".Add([ " << i - nbDel << " ])" << std::endl; + if ( int dom2 = ngMesh->GetFaceDescriptor(sel.GetIndex ()).DomainOut()) + outfile << "grp"<< dom2 <<".Add([ " << i - nbDel << " ])" << std::endl; + } + } + + for (int i = 1; i <= ngMesh->GetNE(); i++) + { + Element el = ngMesh->VolumeElement(i); + outfile << "mesh.AddVolume([ "; + for (int j = 1; j <= el.GetNP(); j++) + outfile << el.PNum(j) << ( j < el.GetNP() ? ", " : " ])"); + outfile << std::endl; + } + + for (int i = 1; i <= ngMesh->GetNSeg(); i++) + { + const Segment & seg = ngMesh->LineSegment (i); + outfile << "mesh.AddEdge([ " + << seg[0]+1 << ", " + << seg[1]+1 << " ])" << std::endl; + } + +#else //////// V 5 + PointIndex pi; for (pi = PointIndex::BASE; pi < ngMesh->GetNP()+PointIndex::BASE; pi++) @@ -3803,13 +3945,14 @@ void NETGENPlugin_Mesher::toPython( const netgen::Mesh* ngMesh ) outfile << "mesh.AddNode( "; outfile << (*ngMesh)[pi](0) << ", "; outfile << (*ngMesh)[pi](1) << ", "; - outfile << (*ngMesh)[pi](2) << ") ## "<< pi << endl; + outfile << (*ngMesh)[pi](2) << ") ## "<< pi << std::endl; } int nbDom = ngMesh->GetNDomains(); for ( int i = 0; i < nbDom; ++i ) - outfile<< "grp" << i+1 << " = mesh.CreateEmptyGroup( SMESH.FACE, 'domain"<< i+1 << "')"<< endl; + outfile<< "grp" << i+1 << " = mesh.CreateEmptyGroup( SMESH.FACE, 'domain"<< i+1 << "')"<< std::endl; + int nbDel = 0; SurfaceElementIndex sei; for (sei = 0; sei < ngMesh->GetNSE(); sei++) { @@ -3818,14 +3961,15 @@ void NETGENPlugin_Mesher::toPython( const netgen::Mesh* ngMesh ) for (int j = 0; j < sel.GetNP(); j++) outfile << sel[j] << ( j+1 < sel.GetNP() ? ", " : " ])"); if ( sel.IsDeleted() ) outfile << " ## IsDeleted "; - outfile << endl; + outfile << std::endl; + nbDel += sel.IsDeleted(); if ((*ngMesh)[sei].GetIndex()) { if ( int dom1 = ngMesh->GetFaceDescriptor((*ngMesh)[sei].GetIndex ()).DomainIn()) - outfile << "grp"<< dom1 <<".Add([ " << (int)sei+1 << " ])" << endl; + outfile << "grp"<< dom1 <<".Add([ " << (int)sei+1 - nbDel << " ])" << std::endl; if ( int dom2 = ngMesh->GetFaceDescriptor((*ngMesh)[sei].GetIndex ()).DomainOut()) - outfile << "grp"<< dom2 <<".Add([ " << (int)sei+1 << " ])" << endl; + outfile << "grp"<< dom2 <<".Add([ " << (int)sei+1 - nbDel << " ])" << std::endl; } } @@ -3835,7 +3979,7 @@ void NETGENPlugin_Mesher::toPython( const netgen::Mesh* ngMesh ) outfile << "mesh.AddVolume([ "; for (int j = 0; j < el.GetNP(); j++) outfile << el[j] << ( j+1 < el.GetNP() ? ", " : " ])"); - outfile << endl; + outfile << std::endl; } for (int i = 1; i <= ngMesh->GetNSeg(); i++) @@ -3843,9 +3987,12 @@ void NETGENPlugin_Mesher::toPython( const netgen::Mesh* ngMesh ) const Segment & seg = ngMesh->LineSegment (i); outfile << "mesh.AddEdge([ " << seg[0] << ", " - << seg[1] << " ])" << endl; + << seg[1] << " ])" << std::endl; } - cout << "Write " << pyFile << endl; + +#endif + + std::cout << "Write " << pyFile << std::endl; } //================================================================================ @@ -3886,11 +4033,7 @@ void NETGENPlugin_ngMeshInfo::transferLocalH( netgen::Mesh* fromMesh, { if ( !fromMesh->LocalHFunctionGenerated() ) return; if ( !toMesh->LocalHFunctionGenerated() ) -#ifdef NETGEN_V5 - toMesh->CalcLocalH(netgen::mparam.grading); -#else - toMesh->CalcLocalH(); -#endif + NETGENPlugin_NetgenLibWrapper::CalcLocalH( toMesh ); const size_t size = sizeof( netgen::LocalH ); _copyOfLocalH = new char[ size ]; @@ -4079,7 +4222,7 @@ void NETGENPlugin_Internals::findBorderElements( TIDSortedElemSet & borderElems { int nbDblNodes = 0; for ( int i = 0; i < nbNodes; ++i ) - nbDblNodes += isInternalShape( f->GetNode(i)->getshapeId() ); + nbDblNodes += isInternalShape( f->GetNode(i)->GetShapeID() ); if ( nbDblNodes ) suspectFaces[ nbDblNodes < 2 ].push_back( f ); nbSuspectFaces++; @@ -4276,10 +4419,15 @@ int& NETGENPlugin_NetgenLibWrapper::instanceCounter() */ //================================================================================ -NETGENPlugin_NetgenLibWrapper::NETGENPlugin_NetgenLibWrapper() +NETGENPlugin_NetgenLibWrapper::NETGENPlugin_NetgenLibWrapper(): + _ngMesh(0) { if ( instanceCounter() == 0 ) + { Ng_Init(); + if ( !netgen::testout ) + netgen::testout = new ofstream( "test.out" ); + } ++instanceCounter(); @@ -4297,13 +4445,13 @@ NETGENPlugin_NetgenLibWrapper::NETGENPlugin_NetgenLibWrapper() netgen::myerr = netgen::mycout; _coutBuffer = std::cout.rdbuf(); #ifdef _DEBUG_ - cout << "NOTE: netgen output is redirected to file " << _outputFileName << endl; + std::cout << "NOTE: netgen output is redirected to file " << _outputFileName << std::endl; #else std::cout.rdbuf( netgen::mycout->rdbuf() ); #endif } - _ngMesh = Ng_NewMesh(); + setMesh( Ng_NewMesh() ); } //================================================================================ @@ -4316,7 +4464,7 @@ NETGENPlugin_NetgenLibWrapper::~NETGENPlugin_NetgenLibWrapper() { --instanceCounter(); - Ng_DeleteMesh( _ngMesh ); + Ng_DeleteMesh( ngMesh() ); Ng_Exit(); RemoveTmpFiles(); if ( _coutBuffer ) @@ -4336,8 +4484,66 @@ NETGENPlugin_NetgenLibWrapper::~NETGENPlugin_NetgenLibWrapper() void NETGENPlugin_NetgenLibWrapper::setMesh( Ng_Mesh* mesh ) { if ( _ngMesh ) - Ng_DeleteMesh( _ngMesh ); - _ngMesh = mesh; + Ng_DeleteMesh( ngMesh() ); + _ngMesh = (netgen::Mesh*) mesh; +} + +//================================================================================ +/*! + * \brief Perform a step of mesh generation + * \param [inout] occgeo - geometry to mesh + * \param [inout] startWith - start step + * \param [inout] endWith - end step + * \param [inout] ngMesh - netgen mesh + * \return int - is error + */ +//================================================================================ + +int NETGENPlugin_NetgenLibWrapper::GenerateMesh( netgen::OCCGeometry& occgeo, + int startWith, int endWith, + netgen::Mesh* & ngMesh ) +{ + int err = 0; + if ( !ngMesh ) + ngMesh = new netgen::Mesh; + +#ifdef NETGEN_V6 + + ngMesh->SetGeometry( shared_ptr( &occgeo, &NOOP_Deleter )); + + netgen::mparam.perfstepsstart = startWith; + netgen::mparam.perfstepsend = endWith; + std::shared_ptr meshPtr( ngMesh, &NOOP_Deleter ); + err = occgeo.GenerateMesh( meshPtr, netgen::mparam ); + +#else + #ifdef NETGEN_V5 + + err = netgen::OCCGenerateMesh(occgeo, ngMesh, netgen::mparam, startWith, endWith); + + #else + + char *optstr = 0; + err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr); + + #endif +#endif + return err; +} + +//================================================================================ +/*! + * \brief Create a mesh size tree + */ +//================================================================================ + +void NETGENPlugin_NetgenLibWrapper::CalcLocalH( netgen::Mesh * ngMesh ) +{ +#if defined( NETGEN_V5 ) || defined( NETGEN_V6 ) + ngMesh->CalcLocalH(netgen::mparam.grading); +#else + ngMesh->CalcLocalH(); +#endif } //================================================================================ @@ -4350,7 +4556,7 @@ std::string NETGENPlugin_NetgenLibWrapper::getOutputFileName() { std::string aTmpDir = SALOMEDS_Tool::GetTmpDir(); - TCollection_AsciiString aGenericName = (char*)aTmpDir.c_str(); + TCollection_AsciiString aGenericName = aTmpDir.c_str(); aGenericName += "NETGEN_"; #ifndef WIN32 aGenericName += getpid(); @@ -4403,10 +4609,10 @@ void NETGENPlugin_NetgenLibWrapper::removeOutputFile() } string tmpDir = SALOMEDS_Tool::GetDirFromPath ( _outputFileName ); string aFileName = SALOMEDS_Tool::GetNameFromPath( _outputFileName ) + ".out"; - SALOMEDS::ListOfFileNames_var aFiles = new SALOMEDS::ListOfFileNames; - aFiles->length(1); - aFiles[0] = aFileName.c_str(); + SALOMEDS_Tool::ListOfFiles aFiles; + aFiles.reserve(1); + aFiles.push_back(aFileName.c_str()); - SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.c_str(), aFiles.in(), true ); + SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.c_str(), aFiles, true ); } }