From 58c0c7e37e3fd5bfa1538a87adb470c2a5d50a9c Mon Sep 17 00:00:00 2001 From: Yoann Audouin Date: Mon, 25 Jul 2022 10:34:43 +0200 Subject: [PATCH] Using provider for occgeom and nglib --- src/NETGENPlugin/CMakeLists.txt | 41 +++---- src/NETGENPlugin/NETGENPluginBuilder.py | 23 ++-- .../NETGENPlugin_NETGEN_2D_ONLY.cxx | 89 ++++++++------ src/NETGENPlugin/NETGENPlugin_NETGEN_3D.cxx | 14 ++- src/NETGENPlugin/NETGENPlugin_Provider.hxx | 112 ++++++++++++++++++ 5 files changed, 204 insertions(+), 75 deletions(-) create mode 100644 src/NETGENPlugin/NETGENPlugin_Provider.hxx diff --git a/src/NETGENPlugin/CMakeLists.txt b/src/NETGENPlugin/CMakeLists.txt index c882e14..83febb3 100644 --- a/src/NETGENPlugin/CMakeLists.txt +++ b/src/NETGENPlugin/CMakeLists.txt @@ -34,7 +34,7 @@ INCLUDE_DIRECTORIES( ) # additional preprocessor / compiler flags -ADD_DEFINITIONS( +ADD_DEFINITIONS( ${OMNIORB_DEFINITIONS} ${OpenCASCADE_DEFINITIONS} ${BOOST_DEFINITIONS} @@ -70,27 +70,28 @@ SET(_link_LIBRARIES # header files SET(NETGENEngine_HEADERS - NETGENPlugin_NETGEN_3D.hxx - NETGENPlugin_NETGEN_3D_i.hxx - NETGENPlugin_NETGEN_2D.hxx - NETGENPlugin_NETGEN_2D_i.hxx - NETGENPlugin_NETGEN_2D3D.hxx - NETGENPlugin_NETGEN_2D3D_i.hxx - NETGENPlugin_NETGEN_2D_ONLY.hxx - NETGENPlugin_NETGEN_2D_ONLY_i.hxx - NETGENPlugin_Hypothesis.hxx - NETGENPlugin_Hypothesis_i.hxx - NETGENPlugin_Hypothesis_2D.hxx - NETGENPlugin_Hypothesis_2D_i.hxx - NETGENPlugin_Hypothesis_3D_i.hxx - NETGENPlugin_Hypothesis_2D_ONLY_i.hxx - NETGENPlugin_SimpleHypothesis_2D.hxx - NETGENPlugin_SimpleHypothesis_3D.hxx - NETGENPlugin_SimpleHypothesis_2D_i.hxx - NETGENPlugin_SimpleHypothesis_3D_i.hxx - NETGENPlugin_Mesher.hxx + NETGENPlugin_NETGEN_3D.hxx + NETGENPlugin_NETGEN_3D_i.hxx + NETGENPlugin_NETGEN_2D.hxx + NETGENPlugin_NETGEN_2D_i.hxx + NETGENPlugin_NETGEN_2D3D.hxx + NETGENPlugin_NETGEN_2D3D_i.hxx + NETGENPlugin_NETGEN_2D_ONLY.hxx + NETGENPlugin_NETGEN_2D_ONLY_i.hxx + NETGENPlugin_Hypothesis.hxx + NETGENPlugin_Hypothesis_i.hxx + NETGENPlugin_Hypothesis_2D.hxx + NETGENPlugin_Hypothesis_2D_i.hxx + NETGENPlugin_Hypothesis_3D_i.hxx + NETGENPlugin_Hypothesis_2D_ONLY_i.hxx + NETGENPlugin_SimpleHypothesis_2D.hxx + NETGENPlugin_SimpleHypothesis_3D.hxx + NETGENPlugin_SimpleHypothesis_2D_i.hxx + NETGENPlugin_SimpleHypothesis_3D_i.hxx + NETGENPlugin_Mesher.hxx NETGENPlugin_Remesher_2D.hxx NETGENPlugin_Defs.hxx + NETGENPlugin_Provider.hxx ) # --- sources --- diff --git a/src/NETGENPlugin/NETGENPluginBuilder.py b/src/NETGENPlugin/NETGENPluginBuilder.py index 56e1f37..3a6f3c7 100644 --- a/src/NETGENPlugin/NETGENPluginBuilder.py +++ b/src/NETGENPlugin/NETGENPluginBuilder.py @@ -40,19 +40,19 @@ NETGEN_VERSION_MAJOR = NETGENPlugin.NETGEN_VERSION_MAJOR # Mesh algo type identifiers #---------------------------- -## Algorithm type: Netgen tetrahedron 3D algorithm, see NETGEN_3D_Algorithm +## Algorithm type: Netgen tetrahedron 3D algorithm, see NETGEN_3D_Algorithm NETGEN_3D = "NETGEN_3D" -## Algorithm type: Netgen tetrahedron 1D-2D-3D algorithm, see NETGEN_1D2D3D_Algorithm +## Algorithm type: Netgen tetrahedron 1D-2D-3D algorithm, see NETGEN_1D2D3D_Algorithm NETGEN_1D2D3D = "NETGEN_2D3D" -## Algorithm type: Netgen triangle 1D-2D algorithm, see NETGEN_1D2D_Algorithm +## Algorithm type: Netgen triangle 1D-2D algorithm, see NETGEN_1D2D_Algorithm NETGEN_1D2D = "NETGEN_2D" ## Algorithm type: Netgen triangle 2D algorithm, see NETGEN_2D_Only_Algorithm NETGEN_2D = "NETGEN_2D_ONLY" -## Algorithm type: Synonim of NETGEN_1D2D3D, see NETGEN_1D2D3D_Algorithm +## Algorithm type: Synonim of NETGEN_1D2D3D, see NETGEN_1D2D3D_Algorithm NETGEN_FULL = NETGEN_1D2D3D -## Algorithm type: Synonim of NETGEN_3D, see NETGEN_3D_Algorithm +## Algorithm type: Synonim of NETGEN_3D, see NETGEN_3D_Algorithm NETGEN = NETGEN_3D -## Algorithm type: Synonim of NETGEN_1D2D3D, see NETGEN_1D2D3D_Algorithm +## Algorithm type: Synonim of NETGEN_1D2D3D, see NETGEN_1D2D3D_Algorithm FULL_NETGEN = NETGEN_FULL #---------------------------- @@ -190,7 +190,7 @@ class NETGEN_Algorithm(Mesh_Algorithm): def SetLocalSizeOnShape(self, shape, size ): self.Parameters().SetLocalSizeOnShape(shape, size) pass - + pass # end of NETGEN_Algorithm class @@ -310,7 +310,7 @@ class NETGEN_1D2D3D_Algorithm(NETGEN_Algorithm): pass # end of NETGEN_1D2D3D_Algorithm class -## Triangle NETGEN 1D-2D algorithm. +## Triangle NETGEN 1D-2D algorithm. # # It can be created by calling smeshBuilder.Mesh.Triangle( smeshBuilder.NETGEN_1D2D, geom=0 ) # @@ -328,6 +328,7 @@ class NETGEN_1D2D_Algorithm(NETGEN_1D2D3D_Algorithm): # @internal docHelper = "Creates triangle 2D algorithm for faces" + ## Private constructor. # @param mesh parent mesh object algorithm is assigned to # @param geom geometry (shape/sub-shape) algorithm is assigned to; @@ -357,7 +358,9 @@ class NETGEN_2D_Only_Algorithm(NETGEN_Algorithm): ## doc string of the method # @internal docHelper = "Creates triangle 2D algorithm for faces" - + + isDefault = True + ## Private constructor. # @param mesh parent mesh object algorithm is assigned to # @param geom geometry (shape/sub-shape) algorithm is assigned to; @@ -385,7 +388,7 @@ class NETGEN_2D_Only_Algorithm(NETGEN_Algorithm): def LengthFromEdges(self): hyp = self.Hypothesis("LengthFromEdges", UseExisting=1, CompareMethod=self.CompareEqualHyp) return hyp - + ## Sets @c UseSurfaceCurvature flag # @param toUse new value of the @c UseSurfaceCurvature parameter (@c True by default) def SetUseSurfaceCurvature(self, toUse=True): diff --git a/src/NETGENPlugin/NETGENPlugin_NETGEN_2D_ONLY.cxx b/src/NETGENPlugin/NETGENPlugin_NETGEN_2D_ONLY.cxx index cef4819..a94d728 100644 --- a/src/NETGENPlugin/NETGENPlugin_NETGEN_2D_ONLY.cxx +++ b/src/NETGENPlugin/NETGENPlugin_NETGEN_2D_ONLY.cxx @@ -25,6 +25,7 @@ #include "NETGENPlugin_Mesher.hxx" #include "NETGENPlugin_Hypothesis_2D.hxx" +#include "NETGENPlugin_Provider.hxx" #include #include @@ -76,7 +77,7 @@ using namespace nglib; //============================================================================= /*! - * + * */ //============================================================================= @@ -85,7 +86,7 @@ NETGENPlugin_NETGEN_2D_ONLY::NETGENPlugin_NETGEN_2D_ONLY(int hypId, : SMESH_2D_Algo(hypId, gen) { _name = "NETGEN_2D_ONLY"; - + _shapeType = (1 << TopAbs_FACE);// 1 bit /shape type _onlyUnaryInput = false; // treat all FACEs at once @@ -103,7 +104,7 @@ NETGENPlugin_NETGEN_2D_ONLY::NETGENPlugin_NETGEN_2D_ONLY(int hypId, //============================================================================= /*! - * + * */ //============================================================================= @@ -114,7 +115,7 @@ NETGENPlugin_NETGEN_2D_ONLY::~NETGENPlugin_NETGEN_2D_ONLY() //============================================================================= /*! - * + * */ //============================================================================= @@ -128,6 +129,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::CheckHypothesis (SMESH_Mesh& aMesh, _hypParameters = 0; _progressByTic = -1; + const list& hyps = GetUsedHypothesis(aMesh, aShape, false); if (hyps.empty()) @@ -226,6 +228,11 @@ bool NETGENPlugin_NETGEN_2D_ONLY::CheckHypothesis (SMESH_Mesh& aMesh, bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { + aMesh.Lock(); + SMESH_Hypothesis::Hypothesis_Status hypStatus; + this->CheckHypothesis(aMesh, aShape, hypStatus); + aMesh.Unlock(); + netgen::multithread.terminate = 0; //netgen::multithread.task = "Surface meshing"; @@ -233,12 +240,14 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, SMESH_MesherHelper helper(aMesh); helper.SetElementsOnShape( true ); - NETGENPlugin_NetgenLibWrapper ngLib; - ngLib._isComputeOk = false; + NETGENPlugin_NetgenLibWrapper *ngLib; + int id_ngLib = nglib_provider.take(&ngLib); + ngLib->_isComputeOk = false; netgen::Mesh ngMeshNoLocSize; - netgen::Mesh * ngMeshes[2] = { (netgen::Mesh*) ngLib._ngMesh, & ngMeshNoLocSize }; - netgen::OCCGeometry occgeoComm; + netgen::Mesh * ngMeshes[2] = { (netgen::Mesh*) ngLib->_ngMesh, & ngMeshNoLocSize }; + netgen::OCCGeometry *occgeoComm; + int id_occgeoComm = occgeom_provider.take(&occgeoComm); // min / max sizes are set as follows: // if ( _hypParameters ) @@ -252,7 +261,6 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, // else // min = aMesher.GetDefaultMinSize() // max = max segment len of a FACE - NETGENPlugin_Mesher aMesher( &aMesh, aShape, /*isVolume=*/false); aMesher.SetParameters( _hypParameters ); // _hypParameters -> netgen::mparam const bool toOptimize = _hypParameters ? _hypParameters->GetOptimize() : true; @@ -270,14 +278,14 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, if ( isCommonLocalSize ) // compute common local size in ngMeshes[0] { //list< SMESH_subMesh* > meshedSM[4]; --> all sub-shapes are added to occgeoComm - aMesher.PrepareOCCgeometry( occgeoComm, aShape, aMesh );//, meshedSM ); + aMesher.PrepareOCCgeometry( *occgeoComm, aShape, aMesh );//, meshedSM ); // local size set at MESHCONST_ANALYSE step depends on // minh, face_maxh, grading and curvaturesafety; find minh if not set by the user if ( !_hypParameters || netgen::mparam.minh < DBL_MIN ) { if ( !_hypParameters ) - netgen::mparam.maxh = occgeoComm.GetBoundingBox().Diam() / 3.; + netgen::mparam.maxh = occgeoComm->GetBoundingBox().Diam() / 3.; netgen::mparam.minh = aMesher.GetDefaultMinSize( aShape, netgen::mparam.maxh ); } // set local size depending on curvature and NOT closeness of EDGEs @@ -288,15 +296,15 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, netgen::occparam.resthcloseedgeenable = false; netgen::occparam.resthcloseedgefac = 1.0 + netgen::mparam.grading; #endif - occgeoComm.face_maxh = netgen::mparam.maxh; + occgeoComm->face_maxh = netgen::mparam.maxh; #ifdef NETGEN_V6 netgen::OCCParameters occparam; - netgen::OCCSetLocalMeshSize( occgeoComm, *ngMeshes[0], netgen::mparam, occparam ); + netgen::OCCSetLocalMeshSize( *occgeoComm, *ngMeshes[0], netgen::mparam, occparam ); #else - netgen::OCCSetLocalMeshSize( occgeoComm, *ngMeshes[0] ); + netgen::OCCSetLocalMeshSize( *occgeoComm, *ngMeshes[0] ); #endif - occgeoComm.emap.Clear(); - occgeoComm.vmap.Clear(); + occgeoComm->emap.Clear(); + occgeoComm->vmap.Clear(); // set local size according to size of existing segments TopTools_IndexedMapOfShape edgeMap; @@ -321,8 +329,8 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, } // set local size defined on shapes - aMesher.SetLocalSize( occgeoComm, *ngMeshes[0] ); - aMesher.SetLocalSizeForChordalError( occgeoComm, *ngMeshes[0] ); + aMesher.SetLocalSize( *occgeoComm, *ngMeshes[0] ); + aMesher.SetLocalSizeForChordalError( *occgeoComm, *ngMeshes[0] ); try { ngMeshes[0]->LoadLocalMeshSize( mparam.meshsizefilename ); } catch (NgException & ex) { @@ -330,7 +338,6 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, } } netgen::mparam.uselocalh = toOptimize; // restore as it is used at surface optimization - // ================== // Loop on all FACEs // ================== @@ -419,7 +426,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, netgen::mparam.maxh = edgeLength; } if ( netgen::mparam.maxh < DBL_MIN ) - netgen::mparam.maxh = occgeoComm.GetBoundingBox().Diam(); + netgen::mparam.maxh = occgeoComm->GetBoundingBox().Diam(); if ( !isCommonLocalSize ) { @@ -428,16 +435,17 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, } // prepare occgeom - netgen::OCCGeometry occgeom; - occgeom.shape = F; - occgeom.fmap.Add( F ); - occgeom.CalcBoundingBox(); - occgeom.facemeshstatus.SetSize(1); - occgeom.facemeshstatus = 0; - occgeom.face_maxh_modified.SetSize(1); - occgeom.face_maxh_modified = 0; - occgeom.face_maxh.SetSize(1); - occgeom.face_maxh = netgen::mparam.maxh; + netgen::OCCGeometry *occgeom; + int id_occgeom = occgeom_provider.take(&occgeom); + occgeom->shape = F; + occgeom->fmap.Add( F ); + occgeom->CalcBoundingBox(); + occgeom->facemeshstatus.SetSize(1); + occgeom->facemeshstatus = 0; + occgeom->face_maxh_modified.SetSize(1); + occgeom->face_maxh_modified = 0; + occgeom->face_maxh.SetSize(1); + occgeom->face_maxh = netgen::mparam.maxh; // ------------------------- // Fill netgen mesh @@ -460,11 +468,11 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, { ngMesh->SetGlobalH ( mparam.maxh ); ngMesh->SetMinimalH( mparam.minh ); - Box<3> bb = occgeom.GetBoundingBox(); + Box<3> bb = occgeom->GetBoundingBox(); bb.Increase (bb.Diam()/10); ngMesh->SetLocalH (bb.PMin(), bb.PMax(), mparam.grading); - aMesher.SetLocalSize( occgeom, *ngMesh ); - aMesher.SetLocalSizeForChordalError( occgeoComm, *ngMesh ); + aMesher.SetLocalSize( *occgeom, *ngMesh ); + aMesher.SetLocalSizeForChordalError( *occgeoComm, *ngMesh ); try { ngMesh->LoadLocalMeshSize( mparam.meshsizefilename ); } catch (NgException & ex) { @@ -473,7 +481,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, } nodeVec.clear(); - faceErr = aMesher.AddSegmentsToMesh( *ngMesh, occgeom, wires, helper, nodeVec, + faceErr = aMesher.AddSegmentsToMesh( *ngMesh, *occgeom, wires, helper, nodeVec, /*overrideMinH=*/!_hypParameters); if ( faceErr && !faceErr->IsOK() ) break; @@ -491,9 +499,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, SMESH_Comment str; try { OCC_CATCH_SIGNALS; - - err = ngLib.GenerateMesh(occgeom, startWith, endWith, ngMesh); - + err = ngLib->GenerateMesh(*occgeom, startWith, endWith, ngMesh); if ( netgen::multithread.terminate ) return false; if ( err ) @@ -515,7 +521,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, } if ( err ) { - if ( aMesher.FixFaceMesh( occgeom, *ngMesh, 1 )) + if ( aMesher.FixFaceMesh( *occgeom, *ngMesh, 1 )) break; if ( iLoop == LOC_SIZE ) { @@ -546,7 +552,9 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, } } - + occgeom_provider.release(id_occgeoComm, true); + occgeom_provider.release(id_occgeom, true); + aMesh.Lock(); // ---------------------------------------------------- // Fill the SMESHDS with the generated nodes and faces // ---------------------------------------------------- @@ -596,6 +604,9 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, break; } // two attempts } // loop on FACEs + aMesh.Unlock(); + nglib_provider.release(id_ngLib, true); + return true; } diff --git a/src/NETGENPlugin/NETGENPlugin_NETGEN_3D.cxx b/src/NETGENPlugin/NETGENPlugin_NETGEN_3D.cxx index 88abe10..f9d4711 100644 --- a/src/NETGENPlugin/NETGENPlugin_NETGEN_3D.cxx +++ b/src/NETGENPlugin/NETGENPlugin_NETGEN_3D.cxx @@ -95,7 +95,7 @@ using namespace std; //============================================================================= /*! - * + * */ //============================================================================= @@ -119,7 +119,7 @@ NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D(int hypId, SMESH_Gen* gen) //============================================================================= /*! - * + * */ //============================================================================= @@ -129,7 +129,7 @@ NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D() //============================================================================= /*! - * + * */ //============================================================================= @@ -544,7 +544,7 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh& aMesh, if ( ce && ce->HasBadElems() ) error( ce ); } - + aMesh.Lock(); bool isOK = ( /*status == NG_OK &&*/ Netgen_NbOfTetra > 0 );// get whatever built if ( isOK ) { @@ -576,6 +576,8 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh& aMesh, } } } + aMesh.Unlock(); + return !err; } @@ -641,7 +643,7 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh, return error( COMPERR_BAD_INPUT_MESH, "Null element encounters"); if ( elem->NbCornerNodes() != 3 ) return error( COMPERR_BAD_INPUT_MESH, "Not triangle element encounters"); - + // add three nodes of triangle for ( int iN = 0; iN < 3; ++iN ) { @@ -797,7 +799,7 @@ bool NETGENPlugin_NETGEN_3D::Evaluate(SMESH_Mesh& aMesh, } SMESH_subMesh *sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aVec)); - + return true; } diff --git a/src/NETGENPlugin/NETGENPlugin_Provider.hxx b/src/NETGENPlugin/NETGENPlugin_Provider.hxx new file mode 100644 index 0000000..0d2b2ae --- /dev/null +++ b/src/NETGENPlugin/NETGENPlugin_Provider.hxx @@ -0,0 +1,112 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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. +// +// 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 +// + +// File : NETGENPlugin_Provider.hxx +// Author : Yoann AUDOUIN (EDF) +// Project : SALOME +// +#include +#include +#include +#include +#include +#include + +namespace nglib { +#include +} +#ifndef OCCGEOMETRY +#define OCCGEOMETRY +#endif +#include +#include + +template +class ProviderPtr{ + public: + + ProviderPtr(){ + for(int i=0;i_mydata[i] = nullptr; + this->_useddata[i] = false; + } + } + + ProviderPtr(std::array is, std::array ds){ + for(int i=0;i_mydata[i] = new T(is[i], ds[i]); + this->_useddata[i] = false; + } + } + + int take(T** data){ + + this->_mymutex.lock(); + *data = nullptr; + for(int i=0;i_useddata[i]){ + if (this->_mydata[i] == nullptr) + this->_mydata[i] = new T(); + this->_useddata[i] = true; + *data = this->_mydata[i]; + this->_mymutex.unlock(); + return i; + } + } + this->_mymutex.unlock(); + return -1; + }; + + + bool release(int i, bool clean){ + + this->_mymutex.lock(); + + if(clean){ + delete this->_mydata[i]; + this->_mydata[i] = nullptr; + } + + this->_useddata[i] = false; + + this->_mymutex.unlock(); + + return true; + }; + + void dump(){ + std::cout << "Dumping provider:" << std::endl; + for(int i=0;i_useddata[i] << std::endl; + std::cout << " - adress: " << this->_mydata[i] << std::endl; + if (this->_mydata[i] != nullptr) + std::cout << " - i: " << this->_mydata[i]->i << " d: " << this->_mydata[i]->d << std::endl; + } + }; + + private: + std::array _mydata; + std::array _useddata; + std::mutex _mymutex; + +}; + +ProviderPtr occgeom_provider; +ProviderPtr nglib_provider; + -- 2.39.2