#ifdef NG_PYTHON #ifdef OCCGEOMETRY #include <../general/ngpython.hpp> #include #include "../meshing/python_mesh.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=4 #define OCC_HAVE_DUMP_JSON #endif using namespace netgen; namespace netgen { extern std::shared_ptr ng_geometry; } static string occparameter_description = R"delimiter( OCC Specific Meshing Parameters ------------------------------- closeedgefac: Optional[float] = 2. 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(val); occparam.resthminedgelenenable = true; } } } DLL_HEADER void ExportNgOCC(py::module &m) { m.attr("occ_version") = OCC_VERSION_COMPLETE; // not working, since occ - exceptions don't derive from std::exception // py::register_exception(m, "OCC-Exception"); py::class_, NetgenGeometry> (m, "OCCGeometry", R"raw_string(Use LoadOCCGeometry to load the geometry from a *.step file.)raw_string") .def(py::init<>()) /* .def(py::init(), py::arg("shape"), "Create Netgen OCCGeometry from existing TopoDS_Shape") */ .def(py::init([] (const TopoDS_Shape& shape) { auto geo = make_shared (shape); ng_geometry = geo; // geo->BuildFMap(); // geo->CalcBoundingBox(); return geo; }), py::arg("shape"), "Create Netgen OCCGeometry from existing TopoDS_Shape") .def(py::init([] (const std::vector shapes) { BOPAlgo_Builder builder; for (auto & s : shapes) builder.AddArgument(s); builder.Perform(); cout << "glued together" << endl; #ifdef OCC_HAVE_HISTORY Handle(BRepTools_History) history = builder.History (); for (auto & s : shapes) for (TopExp_Explorer e(s, TopAbs_SOLID); e.More(); e.Next()) if (auto name = OCCGeometry::global_shape_properties[e.Current().TShape()].name) { TopTools_ListOfShape modlist = history->Modified(e.Current()); for (auto mods : modlist) OCCGeometry::global_shape_properties[mods.TShape()].name = *name; } #endif // OCC_HAVE_HISTORY auto geo = make_shared (builder.Shape()); ng_geometry = geo; // geo->BuildFMap(); // geo->CalcBoundingBox(); return geo; }), py::arg("shape"), "Create Netgen OCCGeometry from existing TopoDS_Shape") .def(py::init([] (const string& filename) { shared_ptr geo; if(EndsWith(filename, ".step") || EndsWith(filename, ".stp")) geo.reset(LoadOCC_STEP(filename.c_str())); else if(EndsWith(filename, ".brep")) geo.reset(LoadOCC_BREP(filename.c_str())); else if(EndsWith(filename, ".iges")) geo.reset(LoadOCC_IGES(filename.c_str())); else throw Exception("Cannot load file " + filename + "\nValid formats are: step, stp, brep, iges"); ng_geometry = geo; return geo; }), py::arg("filename"), "Load OCC geometry from step, brep or iges file") .def(NGSPickle()) .def("Glue", &OCCGeometry::GlueGeometry) .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(); },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()) .def("SetFaceMeshsize", [](OCCGeometry& self, size_t fnr, double meshsize) { self.SetFaceMaxH(fnr, meshsize); }, "Set maximum meshsize for face fnr. Face numbers are 0 based.") .def("_visualizationData", [] (shared_ptr occ_geo) { std::vector vertices; std::vector trigs; std::vector normals; std::vector min = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; std::vector max = {std::numeric_limits::lowest(), std::numeric_limits::lowest(), std::numeric_limits::lowest()}; std::vector 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++) { auto triangle = (triangulation->Triangles())(j); for (int k = 1; k < 4; k++) p[k-1] = (triangulation->Nodes())(triangle(k)).Transformed(loc); 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; uv = (triangulation->UVNodes())(triangle(k)); 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()) .def("GenerateMesh", [](shared_ptr geo, MeshingParameters* pars, py::kwargs kwargs) { MeshingParameters mp; OCCParameters occparam; { py::gil_scoped_acquire aq; if(pars) { auto mp_kwargs = CreateDictFromFlags(pars->geometrySpecificParameters); CreateOCCParametersFromKwargs(occparam, mp_kwargs); mp = *pars; } CreateOCCParametersFromKwargs(occparam, kwargs); CreateMPfromKwargs(mp, kwargs); } geo->SetOCCParameters(occparam); auto mesh = make_shared(); mesh->SetGeometry(geo); auto result = geo->GenerateMesh(mesh, mp); if(result != 0) throw Exception("Meshing failed!"); SetGlobalMesh(mesh); ng_geometry = geo; return mesh; }, py::arg("mp") = nullptr, py::call_guard(), (meshingparameter_description + occparameter_description).c_str()) .def_property_readonly("shape", [](const OCCGeometry & self) { return self.GetShape(); }) ; py::enum_(m, "TopAbs_ShapeEnum", "Enumeration of all supported TopoDS_Shapes") .value("COMPOUND", TopAbs_COMPOUND) .value("COMPSOLID", TopAbs_COMPSOLID) .value("SOLID", TopAbs_SOLID) .value("SHELL", TopAbs_SHELL) .value("FACE", TopAbs_FACE) .value("WIRE", TopAbs_WIRE) .value("EDGE", TopAbs_EDGE) .value("VERTEX", TopAbs_VERTEX) .value("SHAPE", TopAbs_SHAPE) .export_values() ; py::class_(m, "gp_Pnt") .def(py::init([] (py::tuple pnt) { if (py::len(pnt) != 3) throw Exception("need 3-tuple to create gp_Pnt"); return gp_Pnt(py::cast(pnt[0]), py::cast(pnt[1]), py::cast(pnt[2])); })) .def(py::init([] (double x, double y, double z) { return gp_Pnt(x, y, z); })) .def_property("x", [](gp_Pnt&p) { return p.X(); }, [](gp_Pnt&p,double x) { p.SetX(x); }) .def_property("y", [](gp_Pnt&p) { return p.Y(); }, [](gp_Pnt&p,double y) { p.SetY(y); }) .def_property("z", [](gp_Pnt&p) { return p.Z(); }, [](gp_Pnt&p,double z) { p.SetZ(z); }) ; py::class_(m, "gp_Vec") .def(py::init([] (py::tuple vec) { return gp_Vec(py::cast(vec[0]), py::cast(vec[1]), py::cast(vec[2])); })) .def(py::init([] (double x, double y, double z) { return gp_Vec(x, y, z); })) ; py::class_(m, "gp_Dir") .def(py::init([] (py::tuple dir) { return gp_Dir(py::cast(dir[0]), py::cast(dir[1]), py::cast(dir[2])); })) ; py::class_(m, "gp_Ax1") .def(py::init([](gp_Pnt p, gp_Dir d) { return gp_Ax1(p,d); })) ; py::class_(m, "gp_Ax2") .def(py::init([](gp_Pnt p, gp_Dir d) { return gp_Ax2(p,d); })) ; py::class_(m, "gp_Pnt2d") .def(py::init([] (py::tuple pnt) { if (py::len(pnt) != 2) throw Exception("need 2-tuple to create gp_Pnt2d"); return gp_Pnt2d(py::cast(pnt[0]), py::cast(pnt[1])); })) .def(py::init([] (double x, double y) { return gp_Pnt2d(x, y); })) ; py::class_(m, "gp_Vec2d") .def(py::init([] (py::tuple vec) { if (py::len(vec) != 2) throw Exception("need 2-tuple to create gp_Vec2d"); return gp_Vec2d(py::cast(vec[0]), py::cast(vec[1])); })) .def(py::init([] (double x, double y) { return gp_Vec2d(x, y); })) ; py::class_(m, "gp_Dir2d") .def(py::init([] (py::tuple dir) { if (py::len(dir) != 2) throw Exception("need 2-tuple to create gp_Dir2d"); return gp_Dir2d(py::cast(dir[0]), py::cast(dir[1])); })) .def(py::init([] (double x, double y) { return gp_Dir2d(x, y); })) ; py::class_(m, "gp_Ax2d") .def(py::init([](gp_Pnt2d p, gp_Dir2d d) { return gp_Ax2d(p,d); })) ; py::class_(m, "gp_Trsf") .def(py::init<>()) .def("SetMirror", [] (gp_Trsf & trafo, const gp_Ax1 & ax) { trafo.SetMirror(ax); return trafo; }) .def_static("Mirror", [] (const gp_Ax1 & ax) { gp_Trsf trafo; trafo.SetMirror(ax); return trafo; }) .def_static("Rotation", [] (const gp_Ax1 & ax, double ang) { gp_Trsf trafo; trafo.SetRotation(ax, ang); return trafo; }) .def("__call__", [] (gp_Trsf & trafo, const TopoDS_Shape & shape) { return BRepBuilderAPI_Transform(shape, trafo).Shape(); }) ; py::implicitly_convertible(); py::implicitly_convertible(); py::implicitly_convertible(); py::implicitly_convertible(); py::implicitly_convertible(); py::implicitly_convertible(); py::class_ (m, "TopoDS_Shape") .def("__str__", [] (const TopoDS_Shape & shape) { stringstream str; #ifdef OCC_HAVE_DUMP_JSON shape.DumpJson(str); #endif // OCC_HAVE_DUMP_JSON return str.str(); }) .def("ShapeType", [] (const TopoDS_Shape & shape) { return shape.ShapeType(); }) .def_property_readonly("type", [](const TopoDS_Shape & shape) { return shape.ShapeType(); }) .def("SubShapes", [] (const TopoDS_Shape & shape, TopAbs_ShapeEnum & type) { py::list sub; TopExp_Explorer e; for (e.Init(shape, type); e.More(); e.Next()) { switch (type) { case TopAbs_FACE: sub.append(TopoDS::Face(e.Current())); break; default: sub.append(e.Current()); } } return sub; }) .def("Properties", [] (const TopoDS_Shape & shape) { GProp_GProps props; switch (shape.ShapeType()) { case TopAbs_FACE: BRepGProp::SurfaceProperties (shape, props); break; default: BRepGProp::LinearProperties(shape, props); // throw Exception("Properties implemented only for FACE"); } double mass = props.Mass(); gp_Pnt center = props.CentreOfMass(); return tuple( py::cast(mass), py::cast(center) ); }) .def("bc", [](const TopoDS_Shape & shape, const string & name) { for (TopExp_Explorer e(shape, TopAbs_FACE); e.More(); e.Next()) OCCGeometry::global_shape_properties[e.Current().TShape()].name = name; return shape; }) .def("mat", [](const TopoDS_Shape & shape, const string & name) { for (TopExp_Explorer e(shape, TopAbs_SOLID); e.More(); e.Next()) OCCGeometry::global_shape_properties[e.Current().TShape()].name = name; return shape; }) .def_property("name", [](const TopoDS_Shape & self) { if (auto name = OCCGeometry::global_shape_properties[self.TShape()].name) return *name; else return string(); }, [](const TopoDS_Shape & self, string name) { OCCGeometry::global_shape_properties[self.TShape()].name = name; }) .def_property("col", [](const TopoDS_Shape & self) { auto it = OCCGeometry::global_shape_properties.find(self.TShape()); Vec<3> col(0.2, 0.2, 0.2); if (it != OCCGeometry::global_shape_properties.end() && it->second.col) col = *it->second.col; // .value(); return std::vector ( { col(0), col(1), col(2) } ); }, [](const TopoDS_Shape & self, std::vector c) { Vec<3> col(c[0], c[1], c[2]); OCCGeometry::global_shape_properties[self.TShape()].col = col; }) .def("__add__", [] (const TopoDS_Shape & shape1, const TopoDS_Shape & shape2) { return BRepAlgoAPI_Fuse(shape1, shape2).Shape(); }) .def("__mul__", [] (const TopoDS_Shape & shape1, const TopoDS_Shape & shape2) { // return BRepAlgoAPI_Common(shape1, shape2).Shape(); BRepAlgoAPI_Common builder(shape1, shape2); #ifdef OCC_HAVE_HISTORY Handle(BRepTools_History) history = builder.History (); /* // work in progress ... TopTools_ListOfShape modlist = history->Modified(shape1); for (auto s : modlist) cout << "modified from list el: " << s.ShapeType() << endl; */ for (auto & s : { shape1, shape2 }) for (TopExp_Explorer e(s, TopAbs_FACE); e.More(); e.Next()) { auto & prop = OCCGeometry::global_shape_properties[e.Current().TShape()]; for (auto smod : history->Modified(e.Current())) OCCGeometry::global_shape_properties[smod.TShape()].Merge(prop); } #endif // OCC_HAVE_HISTORY return builder.Shape(); }) .def("__sub__", [] (const TopoDS_Shape & shape1, const TopoDS_Shape & shape2) { // return BRepAlgoAPI_Cut(shape1, shape2).Shape(); BRepAlgoAPI_Cut builder(shape1, shape2); #ifdef OCC_HAVE_HISTORY Handle(BRepTools_History) history = builder.History (); for (auto s : { shape1, shape2 }) for (TopExp_Explorer e(s, TopAbs_FACE); e.More(); e.Next()) { /* const string & name = OCCGeometry::global_shape_names[e.Current().TShape()]; for (auto s : history->Modified(e.Current())) OCCGeometry::global_shape_names[s.TShape()] = name; */ /* auto it = OCCGeometry::global_shape_cols.find(e.Current().TShape()); if (it != OCCGeometry::global_shape_cols.end()) for (auto s : history->Modified(e.Current())) OCCGeometry::global_shape_cols[s.TShape()] = it->second; */ auto propit = OCCGeometry::global_shape_properties.find(e.Current().TShape()); if (propit != OCCGeometry::global_shape_properties.end()) for (auto s : history->Modified(e.Current())) OCCGeometry::global_shape_properties[s.TShape()].Merge(propit->second); } /* for (TopExp_Explorer e(shape2, TopAbs_FACE); e.More(); e.Next()) { auto it = OCCGeometry::global_shape_cols[e.Current().TShape()]; if (it != OCCGeometry::global_shape_cols.end()) for (auto s : history->Modified(e.Current())) OCCGeometry::global_shape_cols[s.TShape()] = it->second; } */ #endif // OCC_HAVE_HISTORY return builder.Shape(); }) .def("Find", [](const TopoDS_Shape & shape, gp_Pnt p) { // find sub-shape contianing point // BRepClass_FaceClassifier::Perform (p); }) .def("MakeTriangulation", [](const TopoDS_Shape & shape) { BRepTools::Clean (shape); double deflection = 0.01; BRepMesh_IncrementalMesh (shape, deflection, true); }) .def("Triangulation", [](const TopoDS_Shape & shape) { // extracted from vsocc.cpp TopoDS_Face face; try { face = TopoDS::Face(shape); } catch (Standard_Failure & e) { e.Print (cout); throw NgException ("Triangulation: shape is not a face"); } /* BRepTools::Clean (shape); double deflection = 0.01; BRepMesh_IncrementalMesh (shape, deflection, true); */ Handle(Geom_Surface) surf = BRep_Tool::Surface (face); TopLoc_Location loc; Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); if (triangulation.IsNull()) { BRepTools::Clean (shape); double deflection = 0.01; BRepMesh_IncrementalMesh (shape, deflection, true); triangulation = BRep_Tool::Triangulation (face, loc); } // throw Exception("Don't have a triangulation, call 'MakeTriangulation' first"); int ntriangles = triangulation -> NbTriangles(); Array< std::array,3> > triangles; for (int j = 1; j <= ntriangles; j++) { Poly_Triangle triangle = (triangulation -> Triangles())(j); std::array,3> pts; for (int k = 0; k < 3; k++) pts[k] = occ2ng( (triangulation -> Nodes())(triangle(k+1)).Transformed(loc) ); triangles.Append ( pts ); } // return MoveToNumpyArray(triangles); return triangles; }) ; py::class_ (m, "TopoDS_Edge"); py::class_ (m, "TopoDS_Wire"); py::class_ (m, "TopoDS_Face") /* .def("surf", [] (TopoDS_Face face) -> Handle(Geom_Surface) { Handle(Geom_Surface) surf = BRep_Tool::Surface (face); return surf; }) */ ; py::class_ (m, "TopoDS_Solid"); py::class_ (m, "Geom2d_Curve") .def("Trim", [](Handle(Geom2d_Curve) curve, double u1, double u2) -> Handle(Geom2d_Curve) { return new Geom2d_TrimmedCurve (curve, u1, u2); }) .def("Value", [](Handle(Geom2d_Curve) curve, double s) { return curve->Value(s); }) ; m.def("Sphere", [] (gp_Pnt cc, double r) { return BRepPrimAPI_MakeSphere (cc, r).Solid(); }); m.def("Cylinder", [] (gp_Pnt cpnt, gp_Dir cdir, double r, double h) { return BRepPrimAPI_MakeCylinder (gp_Ax2(cpnt, cdir), r, h).Solid(); }); m.def("Cylinder", [] (gp_Ax2 ax, double r, double h) { return BRepPrimAPI_MakeCylinder (ax, r, h).Solid(); }); m.def("Box", [] (gp_Pnt cp1, gp_Pnt cp2) { return BRepPrimAPI_MakeBox (cp1, cp2).Solid(); }); m.def("Prism", [] (const TopoDS_Shape & face, gp_Vec vec) { return BRepPrimAPI_MakePrism (face, vec).Shape(); }); // Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor); m.def("Ellipse", [] (const gp_Ax2d & ax, double major, double minor) -> Handle(Geom2d_Curve) { return new Geom2d_Ellipse(ax, major, minor); }); m.def("Segment", [](gp_Pnt2d p1, gp_Pnt2d p2) -> Handle(Geom2d_Curve) { Handle(Geom2d_TrimmedCurve) curve = GCE2d_MakeSegment(p1, p2); return curve; // return BRepBuilderAPI_MakeEdge(curve).Edge(); // return GCE2d_MakeSegment(p1, p2); }); m.def("Glue", [] (const std::vector shapes) -> TopoDS_Shape { BOPAlgo_Builder builder; for (auto & s : shapes) { for (TopExp_Explorer e(s, TopAbs_SOLID); e.More(); e.Next()) builder.AddArgument(e.Current()); if (s.ShapeType() == TopAbs_FACE) builder.AddArgument(s); } builder.Perform(); #ifdef OCC_HAVE_HISTORY Handle(BRepTools_History) history = builder.History (); for (auto & s : shapes) for (TopExp_Explorer e(s, TopAbs_SOLID); e.More(); e.Next()) { auto prop = OCCGeometry::global_shape_properties[e.Current().TShape()]; for (auto mods : history->Modified(e.Current())) OCCGeometry::global_shape_properties[mods.TShape()].Merge(prop); } /* { auto name = OCCGeometry::global_shape_names[e.Current().TShape()]; for (auto mods : history->Modified(e.Current())) OCCGeometry::global_shape_names[mods.TShape()] = name; } */ #endif // OCC_HAVE_HISTORY return builder.Shape(); }); m.def("Glue", [] (TopoDS_Shape shape) -> TopoDS_Shape { BOPAlgo_Builder builder; for (TopExp_Explorer e(shape, TopAbs_SOLID); e.More(); e.Next()) builder.AddArgument(e.Current()); builder.Perform(); if (builder.HasErrors()) builder.DumpErrors(cout); if (builder.HasWarnings()) builder.DumpWarnings(cout); #ifdef OCC_HAVE_HISTORY Handle(BRepTools_History) history = builder.History (); for (TopExp_Explorer e(shape, TopAbs_SOLID); e.More(); e.Next()) { auto prop = OCCGeometry::global_shape_properties[e.Current().TShape()]; for (auto mods : history->Modified(e.Current())) OCCGeometry::global_shape_properties[mods.TShape()].Merge(prop); } #endif // OCC_HAVE_HISTORY return builder.Shape(); }); // py::class_ (m, "Geom_TrimmedCurve") // ; m.def("Segment", [](gp_Pnt p1, gp_Pnt p2) { Handle(Geom_TrimmedCurve) curve = GC_MakeSegment(p1, p2); return BRepBuilderAPI_MakeEdge(curve).Edge(); }); m.def("Circle", [](gp_Pnt c, gp_Dir n, double r) { Handle(Geom_Circle) curve = GC_MakeCircle (c, n, r); return BRepBuilderAPI_MakeEdge(curve).Edge(); }); m.def("ArcOfCircle", [](gp_Pnt p1, gp_Pnt p2, gp_Pnt p3) { Handle(Geom_TrimmedCurve) curve = GC_MakeArcOfCircle(p1, p2, p3); return BRepBuilderAPI_MakeEdge(curve).Edge(); }); m.def("Edge", [](Handle(Geom2d_Curve) curve2d, TopoDS_Face face) { auto edge = BRepBuilderAPI_MakeEdge(curve2d, BRep_Tool::Surface (face)).Edge(); BRepLib::BuildCurves3d(edge); return edge; }); m.def("Wire", [](std::vector edges) { BRepBuilderAPI_MakeWire builder; for (auto s : edges) switch (s.ShapeType()) { case TopAbs_EDGE: builder.Add(TopoDS::Edge(s)); break; case TopAbs_WIRE: builder.Add(TopoDS::Wire(s)); break; default: throw Exception("can make wire only from edges and wires"); } return builder.Wire(); }); m.def("Face", [](TopoDS_Wire wire) { return BRepBuilderAPI_MakeFace(wire).Face(); }); m.def("MakeFillet", [](TopoDS_Shape shape, std::vector edges, double r) { BRepFilletAPI_MakeFillet mkFillet(shape); for (auto e : edges) mkFillet.Add (r, TopoDS::Edge(e)); return mkFillet.Shape(); }); m.def("MakeThickSolid", [](TopoDS_Shape body, std::vector facestoremove, double offset, double tol) { TopTools_ListOfShape faces; for (auto f : facestoremove) faces.Append(f); BRepOffsetAPI_MakeThickSolid maker; maker.MakeThickSolidByJoin(body, faces, offset, tol); return maker.Shape(); }); m.def("ThruSections", [](std::vector wires) { BRepOffsetAPI_ThruSections aTool(Standard_True); for (auto shape : wires) aTool.AddWire(TopoDS::Wire(shape)); aTool.CheckCompatibility(Standard_False); return aTool.Shape(); }); m.def("LoadOCCGeometry",[] (const string & filename) { 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(instance, NOOP_Deleter); return ng_geometry; },py::call_guard()); m.def("TestXCAF", [] (TopoDS_Shape shape) { /*static*/ Handle(XCAFApp_Application) app = XCAFApp_Application::GetApplication(); cout << endl << endl << endl; cout << "app = " << *reinterpret_cast(&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()); // Handle(XCAFDoc_VisMaterialTool) vismaterial_tool = XCAFDoc_DocumentTool::VisMaterialTool(doc->Main()); cout << "handle(shape) = " << *(void**)(void*)(&(shape.TShape())) << endl; TDF_LabelSequence doc_shapes; shape_tool->GetShapes(doc_shapes); cout << "shape tool nbentities: " << doc_shapes.Size() << endl; 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; // cout << "IsVisMaterial = " << vismaterial_tool->IsMaterial(label) << endl; } }, py::arg("shape")=TopoDS_Shape()); } PYBIND11_MODULE(libNgOCC, m) { ExportNgOCC(m); } #endif // OCCGEOMETRY #endif // NG_PYTHON