2017-05-31 22:38:17 +05:00
# ifdef NG_PYTHON
# ifdef OCCGEOMETRY
2024-02-10 13:51:19 +05:00
2021-08-06 17:23:17 +05:00
# include <memory>
2017-05-31 22:38:17 +05:00
2021-11-28 20:14:41 +05:00
# include <general/ngpython.hpp>
# include <core/python_ngcore.hpp>
# include <meshing/python_mesh.hpp>
2017-05-31 22:38:17 +05:00
# include <meshing.hpp>
2021-08-02 02:17:39 +05:00
2021-11-28 20:14:41 +05:00
# include "occgeom.hpp"
2017-05-31 22:38:17 +05:00
2021-11-28 20:14:41 +05:00
# include <BOPAlgo_Builder.hxx>
# include <BRepLProp_SLProps.hxx>
2021-11-04 15:54:33 +05:00
# include <Message.hxx>
2021-11-28 20:14:41 +05:00
# include <Standard_GUID.hxx>
# include <Standard_Version.hxx>
# include <TDF_Attribute.hxx>
# include <XCAFApp_Application.hxx>
# include <XCAFDoc_DocumentTool.hxx>
# include <XCAFDoc_MaterialTool.hxx>
# include <XCAFDoc_ShapeTool.hxx>
2021-07-26 19:39:33 +05:00
2017-05-31 22:38:17 +05:00
using namespace netgen ;
namespace netgen
{
extern std : : shared_ptr < NetgenGeometry > ng_geometry ;
2022-08-04 13:31:33 +05:00
extern std : : shared_ptr < Mesh > mesh ;
2017-05-31 22:38:17 +05:00
}
2019-08-27 13:10:17 +05:00
static string occparameter_description = R " delimiter(
OCC Specific Meshing Parameters
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2019-09-16 15:48:27 +05:00
closeedgefac : Optional [ float ] = 2.
2019-08-27 13:10:17 +05:00
Factor for meshing close edges , if None it is disabled .
minedgelen : Optional [ float ] = 0.001
Minimum edge length to be used for dividing edges to mesh points . If
None this is disabled .
) delimiter " ;
void CreateOCCParametersFromKwargs ( OCCParameters & occparam , py : : dict kwargs )
{
if ( kwargs . contains ( " minedgelen " ) )
{
auto val = kwargs . attr ( " pop " ) ( " minedgelen " ) ;
if ( val . is_none ( ) )
occparam . resthminedgelenenable = false ;
else
{
occparam . resthminedgelen = py : : cast < double > ( val ) ;
occparam . resthminedgelenenable = true ;
}
}
}
2021-08-06 13:41:18 +05:00
extern py : : object CastShape ( const TopoDS_Shape & s ) ;
2017-05-31 22:38:17 +05:00
2021-08-06 13:41:18 +05:00
DLL_HEADER void ExportNgOCCBasic ( py : : module & m ) ;
DLL_HEADER void ExportNgOCCShapes ( py : : module & m ) ;
2021-08-06 02:52:03 +05:00
2021-08-06 17:23:17 +05:00
2017-05-31 22:38:17 +05:00
DLL_HEADER void ExportNgOCC ( py : : module & m )
{
2019-10-28 19:11:42 +05:00
m . attr ( " occ_version " ) = OCC_VERSION_COMPLETE ;
2021-08-06 13:41:18 +05:00
2021-11-04 15:54:33 +05:00
// suppress info messages from occ (like statistics on Transfer)
Message_Gravity aGravity = Message_Alarm ;
for ( Message_SequenceOfPrinters : : Iterator aPrinterIter ( Message : : DefaultMessenger ( ) - > Printers ( ) ) ;
aPrinterIter . More ( ) ; aPrinterIter . Next ( ) )
{
aPrinterIter . Value ( ) - > SetTraceLevel ( aGravity ) ;
}
2021-08-06 13:41:18 +05:00
ExportNgOCCBasic ( m ) ;
ExportNgOCCShapes ( m ) ;
2021-08-06 17:23:17 +05:00
2021-09-02 17:58:07 +05:00
static py : : exception < Standard_Failure > exc ( m , " OCCException " ) ;
py : : register_exception_translator ( [ ] ( std : : exception_ptr p )
{
try {
if ( p ) std : : rethrow_exception ( p ) ;
} catch ( const Standard_Failure & e ) {
exc ( ( string ( e . DynamicType ( ) - > Name ( ) ) + " : " + e . GetMessageString ( ) ) . c_str ( ) ) ;
}
} ) ;
2021-07-30 12:43:29 +05:00
2018-04-17 22:37:29 +05:00
py : : class_ < OCCGeometry , shared_ptr < OCCGeometry > , NetgenGeometry > ( m , " OCCGeometry " , R " raw_string(Use LoadOCCGeometry to load the geometry from a *.step file.)raw_string " )
2021-07-24 14:07:39 +05:00
/*
2020-07-13 21:54:55 +05:00
. def ( py : : init < const TopoDS_Shape & > ( ) , py : : arg ( " shape " ) ,
" Create Netgen OCCGeometry from existing TopoDS_Shape " )
2021-07-24 14:07:39 +05:00
*/
2021-11-06 00:26:43 +05:00
. def ( py : : init ( [ ] ( const TopoDS_Shape & shape , int occdim , bool copy )
2021-07-24 14:07:39 +05:00
{
2021-09-09 16:19:34 +05:00
auto geo = make_shared < OCCGeometry > ( shape , occdim ) ;
2021-11-04 00:49:34 +05:00
// ng_geometry = geo;
2021-07-24 14:07:39 +05:00
2021-07-26 12:10:50 +05:00
// geo->BuildFMap();
// geo->CalcBoundingBox();
2021-07-24 14:07:39 +05:00
return geo ;
2021-11-06 00:26:43 +05:00
} ) , py : : arg ( " shape " ) , py : : arg ( " dim " ) = 3 , py : : arg ( " copy " ) = false ,
2021-07-24 14:07:39 +05:00
" Create Netgen OCCGeometry from existing TopoDS_Shape " )
2021-07-25 04:26:09 +05:00
. def ( py : : init ( [ ] ( const std : : vector < TopoDS_Shape > shapes )
{
2021-07-26 12:10:50 +05:00
BOPAlgo_Builder builder ;
for ( auto & s : shapes )
builder . AddArgument ( s ) ;
builder . Perform ( ) ;
2023-02-17 12:47:01 +05:00
for ( auto & s : shapes )
PropagateProperties ( builder , s ) ;
2021-07-26 12:10:50 +05:00
auto geo = make_shared < OCCGeometry > ( builder . Shape ( ) ) ;
2021-07-25 04:26:09 +05:00
ng_geometry = geo ;
2021-07-26 12:10:50 +05:00
// geo->BuildFMap();
// geo->CalcBoundingBox();
2021-07-25 04:26:09 +05:00
return geo ;
} ) , py : : arg ( " shape " ) ,
" Create Netgen OCCGeometry from existing TopoDS_Shape " )
2022-08-08 14:11:15 +05:00
. def ( py : : init ( [ ] ( const string & filename , int dim )
2019-07-26 02:25:58 +05:00
{
shared_ptr < OCCGeometry > geo ;
if ( EndsWith ( filename , " .step " ) | | EndsWith ( filename , " .stp " ) )
2022-02-17 20:52:07 +05:00
geo . reset ( LoadOCC_STEP ( filename ) ) ;
2019-07-26 02:25:58 +05:00
else if ( EndsWith ( filename , " .brep " ) )
2022-02-17 20:52:07 +05:00
geo . reset ( LoadOCC_BREP ( filename ) ) ;
2019-07-26 02:25:58 +05:00
else if ( EndsWith ( filename , " .iges " ) )
2022-02-17 20:52:07 +05:00
geo . reset ( LoadOCC_IGES ( filename ) ) ;
2019-07-26 02:25:58 +05:00
else
throw Exception ( " Cannot load file " + filename + " \n Valid formats are: step, stp, brep, iges " ) ;
2022-08-08 14:11:15 +05:00
if ( dim < 3 )
geo - > SetDimension ( dim ) ;
2019-07-26 02:25:58 +05:00
ng_geometry = geo ;
return geo ;
2022-08-08 14:11:15 +05:00
} ) , py : : arg ( " filename " ) , py : : arg ( " dim " ) = 3 ,
2019-07-26 02:25:58 +05:00
" Load OCC geometry from step, brep or iges file " )
2018-12-20 21:01:27 +05:00
. def ( NGSPickle < OCCGeometry > ( ) )
2020-06-01 00:58:21 +05:00
. def ( " Glue " , & OCCGeometry : : GlueGeometry )
2017-11-03 21:44:01 +05:00
. def ( " Heal " , [ ] ( OCCGeometry & self , double tolerance , bool fixsmalledges , bool fixspotstripfaces , bool sewfaces , bool makesolids , bool splitpartitions )
{
self . tolerance = tolerance ;
self . fixsmalledges = fixsmalledges ;
self . fixspotstripfaces = fixspotstripfaces ;
self . sewfaces = sewfaces ;
self . makesolids = makesolids ;
self . splitpartitions = splitpartitions ;
self . HealGeometry ( ) ;
self . BuildFMap ( ) ;
2018-03-13 02:38:21 +05:00
} , py : : arg ( " tolerance " ) = 1e-3 , py : : arg ( " fixsmalledges " ) = true , py : : arg ( " fixspotstripfaces " ) = true , py : : arg ( " sewfaces " ) = true , py : : arg ( " makesolids " ) = true , py : : arg ( " splitpartitions " ) = false , R " raw_string(Heal the OCCGeometry.)raw_string " , py : : call_guard < py : : gil_scoped_release > ( ) )
2019-08-13 21:45:27 +05:00
. def ( " SetFaceMeshsize " , [ ] ( OCCGeometry & self , size_t fnr , double meshsize )
{
self . SetFaceMaxH ( fnr , meshsize ) ;
} , " Set maximum meshsize for face fnr. Face numbers are 0 based. " )
2021-12-02 16:10:57 +05:00
. def ( " Draw " , [ ] ( shared_ptr < OCCGeometry > geo )
{
ng_geometry = geo ;
} )
2018-07-12 19:35:52 +05:00
. def ( " _visualizationData " , [ ] ( shared_ptr < OCCGeometry > occ_geo )
{
std : : vector < float > vertices ;
std : : vector < int > trigs ;
std : : vector < float > normals ;
std : : vector < float > min = { std : : numeric_limits < float > : : max ( ) ,
std : : numeric_limits < float > : : max ( ) ,
std : : numeric_limits < float > : : max ( ) } ;
std : : vector < float > max = { std : : numeric_limits < float > : : lowest ( ) ,
std : : numeric_limits < float > : : lowest ( ) ,
std : : numeric_limits < float > : : lowest ( ) } ;
std : : vector < string > surfnames ;
auto box = occ_geo - > GetBoundingBox ( ) ;
for ( int i = 0 ; i < 3 ; i + + )
{
min [ i ] = box . PMin ( ) [ i ] ;
max [ i ] = box . PMax ( ) [ i ] ;
}
occ_geo - > BuildVisualizationMesh ( 0.01 ) ;
gp_Pnt2d uv ;
gp_Pnt pnt ;
gp_Vec n ;
gp_Pnt p [ 3 ] ;
int count = 0 ;
for ( int i = 1 ; i < = occ_geo - > fmap . Extent ( ) ; i + + )
{
surfnames . push_back ( " occ_surface " + to_string ( i ) ) ;
auto face = TopoDS : : Face ( occ_geo - > fmap ( i ) ) ;
auto surf = BRep_Tool : : Surface ( face ) ;
TopLoc_Location loc ;
BRepAdaptor_Surface sf ( face , Standard_False ) ;
BRepLProp_SLProps prop ( sf , 1 , 1e-5 ) ;
Handle ( Poly_Triangulation ) triangulation = BRep_Tool : : Triangulation ( face , loc ) ;
if ( triangulation . IsNull ( ) )
cout < < " cannot visualize face " < < i < < endl ;
trigs . reserve ( trigs . size ( ) + triangulation - > NbTriangles ( ) * 4 ) ;
vertices . reserve ( vertices . size ( ) + triangulation - > NbTriangles ( ) * 3 * 3 ) ;
normals . reserve ( normals . size ( ) + triangulation - > NbTriangles ( ) * 3 * 3 ) ;
for ( int j = 1 ; j < triangulation - > NbTriangles ( ) + 1 ; j + + )
{
2021-08-31 16:16:30 +05:00
auto triangle = triangulation - > Triangle ( j ) ;
2018-07-12 19:35:52 +05:00
for ( int k = 1 ; k < 4 ; k + + )
2021-08-31 16:16:30 +05:00
p [ k - 1 ] = triangulation - > Node ( triangle ( k ) ) . Transformed ( loc ) ;
2018-07-12 19:35:52 +05:00
for ( int k = 1 ; k < 4 ; k + + )
{
vertices . insert ( vertices . end ( ) , { float ( p [ k - 1 ] . X ( ) ) , float ( p [ k - 1 ] . Y ( ) ) , float ( p [ k - 1 ] . Z ( ) ) } ) ;
trigs . insert ( trigs . end ( ) , { count , count + 1 , count + 2 , i } ) ;
count + = 3 ;
2021-08-31 16:16:30 +05:00
uv = triangulation - > UVNode ( triangle ( k ) ) ;
2018-07-12 19:35:52 +05:00
prop . SetParameters ( uv . X ( ) , uv . Y ( ) ) ;
if ( prop . IsNormalDefined ( ) )
n = prop . Normal ( ) ;
else
{
gp_Vec a ( p [ 0 ] , p [ 1 ] ) ;
gp_Vec b ( p [ 0 ] , p [ 2 ] ) ;
n = b ^ a ;
}
if ( face . Orientation ( ) = = TopAbs_REVERSED ) n * = - 1 ;
normals . insert ( normals . end ( ) , { float ( n . X ( ) ) , float ( n . Y ( ) ) , float ( n . Z ( ) ) } ) ;
}
}
}
py : : gil_scoped_acquire ac ;
py : : dict res ;
py : : list snames ;
for ( auto name : surfnames )
snames . append ( py : : cast ( name ) ) ;
res [ " vertices " ] = MoveToNumpy ( vertices ) ;
res [ " triangles " ] = MoveToNumpy ( trigs ) ;
res [ " normals " ] = MoveToNumpy ( normals ) ;
res [ " surfnames " ] = snames ;
res [ " min " ] = MoveToNumpy ( min ) ;
res [ " max " ] = MoveToNumpy ( max ) ;
return res ;
} , py : : call_guard < py : : gil_scoped_release > ( ) )
2019-07-29 10:11:57 +05:00
. def ( " GenerateMesh " , [ ] ( shared_ptr < OCCGeometry > geo ,
2022-09-01 13:43:16 +05:00
MeshingParameters * pars , NgMPI_Comm comm ,
2022-09-02 00:24:42 +05:00
shared_ptr < Mesh > mesh , py : : kwargs kwargs )
2019-07-26 02:25:58 +05:00
{
MeshingParameters mp ;
2019-08-27 13:10:17 +05:00
OCCParameters occparam ;
2019-07-26 02:25:58 +05:00
{
py : : gil_scoped_acquire aq ;
2019-08-27 13:10:17 +05:00
if ( pars )
{
auto mp_kwargs = CreateDictFromFlags ( pars - > geometrySpecificParameters ) ;
CreateOCCParametersFromKwargs ( occparam , mp_kwargs ) ;
mp = * pars ;
}
CreateOCCParametersFromKwargs ( occparam , kwargs ) ;
2019-07-29 10:11:57 +05:00
CreateMPfromKwargs ( mp , kwargs ) ;
2019-07-26 02:25:58 +05:00
}
2019-10-02 20:20:13 +05:00
geo - > SetOCCParameters ( occparam ) ;
2022-09-01 13:43:16 +05:00
if ( ! mesh )
mesh = make_shared < Mesh > ( ) ;
2022-03-15 13:13:01 +05:00
mesh - > SetCommunicator ( comm ) ;
2019-07-26 02:25:58 +05:00
mesh - > SetGeometry ( geo ) ;
2022-03-15 13:13:01 +05:00
if ( comm . Rank ( ) = = 0 )
{
SetGlobalMesh ( mesh ) ;
auto result = geo - > GenerateMesh ( mesh , mp ) ;
if ( result ! = 0 )
2022-08-04 17:14:39 +05:00
{
2022-08-04 17:16:16 +05:00
netgen : : mesh = mesh ; // keep mesh for debugging
2022-08-04 17:14:39 +05:00
throw Exception ( " Meshing failed! " ) ;
}
2022-03-15 13:13:01 +05:00
ng_geometry = geo ;
if ( comm . Size ( ) > 1 )
mesh - > Distribute ( ) ;
}
else
{
mesh - > SendRecvMesh ( ) ;
}
2019-07-26 02:25:58 +05:00
return mesh ;
2022-03-15 13:13:01 +05:00
} , py : : arg ( " mp " ) = nullptr , py : : arg ( " comm " ) = NgMPI_Comm { } ,
2022-09-01 13:43:16 +05:00
py : : arg ( " mesh " ) = nullptr , py : : call_guard < py : : gil_scoped_release > ( ) ,
2019-08-27 13:10:17 +05:00
( meshingparameter_description + occparameter_description ) . c_str ( ) )
2021-07-24 16:14:21 +05:00
. def_property_readonly ( " shape " , [ ] ( const OCCGeometry & self ) { return self . GetShape ( ) ; } )
2019-07-26 02:25:58 +05:00
;
2021-08-02 02:17:39 +05:00
2021-07-24 14:07:39 +05:00
2022-02-17 20:52:07 +05:00
m . def ( " LoadOCCGeometry " , [ ] ( filesystem : : path filename )
2021-07-27 01:35:33 +05:00
{
cout < < " WARNING: LoadOCCGeometry is deprecated! Just use the OCCGeometry(filename) constructor. It is able to read brep and iges files as well! " < < endl ;
ifstream ist ( filename ) ;
OCCGeometry * instance = new OCCGeometry ( ) ;
instance = LoadOCC_STEP ( filename . c_str ( ) ) ;
ng_geometry = shared_ptr < OCCGeometry > ( instance , NOOP_Deleter ) ;
return ng_geometry ;
} , py : : call_guard < py : : gil_scoped_release > ( ) ) ;
2021-07-26 01:16:21 +05:00
m . def ( " TestXCAF " , [ ] ( TopoDS_Shape shape ) {
/*static*/ Handle ( XCAFApp_Application ) app = XCAFApp_Application : : GetApplication ( ) ;
cout < < endl < < endl < < endl ;
cout < < " app = " < < * reinterpret_cast < void * * > ( & app ) < < endl ;
Handle ( TDocStd_Document ) doc ;
cout < < " nbdocs = " < < app - > NbDocuments ( ) < < endl ;
if ( app - > NbDocuments ( ) > 0 )
{
app - > GetDocument ( 1 , doc ) ;
// app->Close(doc);
}
else
app - > NewDocument ( " STEP-XCAF " , doc ) ;
Handle ( XCAFDoc_ShapeTool ) shape_tool = XCAFDoc_DocumentTool : : ShapeTool ( doc - > Main ( ) ) ;
Handle ( XCAFDoc_MaterialTool ) material_tool = XCAFDoc_DocumentTool : : MaterialTool ( doc - > Main ( ) ) ;
2021-07-26 12:10:50 +05:00
// Handle(XCAFDoc_VisMaterialTool) vismaterial_tool = XCAFDoc_DocumentTool::VisMaterialTool(doc->Main());
2021-07-26 01:16:21 +05:00
2021-08-12 11:31:06 +05:00
// TDF_LabelSequence doc_shapes;
// shape_tool->GetShapes(doc_shapes);
// cout << "shape tool nbentities: " << doc_shapes.Size() << endl;
2021-07-26 01:16:21 +05:00
TDF_Label label = shape_tool - > FindShape ( shape ) ;
cout < < " shape label = " < < endl < < label < < endl ;
if ( label . IsNull ( ) ) return ;
cout < < " nbattr = " < < label . NbAttributes ( ) < < endl ;
if ( ! label . IsNull ( ) )
{
Handle ( TDF_Attribute ) attribute ;
cout < < " create guid " < < endl ;
// Standard_GUID guid("c4ef4200-568f-11d1-8940-080009dc3333");
Standard_GUID guid ( " 2a96b608-ec8b-11d0-bee7-080009dc3333 " ) ;
cout < < " have guid " < < endl ;
cout < < " find attrib " < < label . FindAttribute ( guid , attribute ) < < endl ;
cout < < " attrib = " < < attribute < < endl ;
cout < < " tag = " < < label . Tag ( ) < < endl ;
cout < < " father.tag = " < < label . Father ( ) . Tag ( ) < < endl ;
cout < < " Data = " < < label . Data ( ) < < endl ;
cout < < " nbchild = " < < label . NbChildren ( ) < < endl ;
for ( auto i : Range ( label . NbChildren ( ) ) )
{
TDF_Label child = label . FindChild ( i + 1 ) ;
cout < < " child[ " < < i < < " ] = " < < child < < endl ;
cout < < " find attrib " < < child . FindAttribute ( guid , attribute ) < < endl ;
cout < < " attrib = " < < attribute < < endl ;
}
// cout << "findshape = " << shape_tool -> FindShape(shape) << endl;
cout < < " IsMaterial = " < < material_tool - > IsMaterial ( label ) < < endl ;
2021-07-26 12:10:50 +05:00
// cout << "IsVisMaterial = " << vismaterial_tool->IsMaterial(label) << endl;
2021-07-26 01:16:21 +05:00
}
} , py : : arg ( " shape " ) = TopoDS_Shape ( ) ) ;
2017-05-31 22:38:17 +05:00
}
2017-09-01 12:33:57 +05:00
PYBIND11_MODULE ( libNgOCC , m ) {
2017-05-31 22:38:17 +05:00
ExportNgOCC ( m ) ;
}
# endif // OCCGEOMETRY
# endif // NG_PYTHON