From bebbfc434c82d14ce8064118e2e8aaa650524444 Mon Sep 17 00:00:00 2001 From: Joachim Schoeberl Date: Fri, 6 Aug 2021 10:41:18 +0200 Subject: [PATCH] split python-occ files, Rotation angle in degrees --- libsrc/occ/CMakeLists.txt | 1 + libsrc/occ/python_occ.cpp | 861 +------------------------------ libsrc/occ/python_occ_shapes.cpp | 765 +++++++++++++++++++++++++++ 3 files changed, 773 insertions(+), 854 deletions(-) create mode 100644 libsrc/occ/python_occ_shapes.cpp diff --git a/libsrc/occ/CMakeLists.txt b/libsrc/occ/CMakeLists.txt index ea5a756e..3219f07c 100644 --- a/libsrc/occ/CMakeLists.txt +++ b/libsrc/occ/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(occ ${NG_LIB_TYPE} Partition_Inter2d.cxx Partition_Inter3d.cxx Partition_Loop.cxx Partition_Loop2d.cxx Partition_Loop3d.cxx Partition_Spliter.cxx occgenmesh.cpp occgeom.cpp occmeshsurf.cpp python_occ.cpp + python_occ_basic.cpp python_occ_shapes.cpp ) if(USE_GUI) add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) diff --git a/libsrc/occ/python_occ.cpp b/libsrc/occ/python_occ.cpp index fd3cf295..2faf3dc6 100644 --- a/libsrc/occ/python_occ.cpp +++ b/libsrc/occ/python_occ.cpp @@ -83,34 +83,18 @@ void CreateOCCParametersFromKwargs(OCCParameters& occparam, py::dict kwargs) } } +extern py::object CastShape(const TopoDS_Shape & s); -py::object CastShape(const TopoDS_Shape & s) -{ - switch (s.ShapeType()) - { - case TopAbs_VERTEX: - return py::cast(TopoDS::Vertex(s)); - case TopAbs_FACE: - return py::cast(TopoDS::Face(s)); - case TopAbs_EDGE: - return py::cast(TopoDS::Edge(s)); - case TopAbs_WIRE: - return py::cast(TopoDS::Wire(s)); - - case TopAbs_COMPOUND: - case TopAbs_COMPSOLID: - case TopAbs_SOLID: - case TopAbs_SHELL: - case TopAbs_SHAPE: - return py::cast(s); - } -}; - - +DLL_HEADER void ExportNgOCCBasic(py::module &m); +DLL_HEADER void ExportNgOCCShapes(py::module &m); DLL_HEADER void ExportNgOCC(py::module &m) { m.attr("occ_version") = OCC_VERSION_COMPLETE; + + ExportNgOCCBasic(m); + ExportNgOCCShapes(m); + // not working, since occ - exceptions don't derive from std::exception // py::register_exception(m, "OCC-Exception"); @@ -300,838 +284,7 @@ DLL_HEADER void ExportNgOCC(py::module &m) .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); }) - .def("__str__", [] (const gp_Pnt & p) { - stringstream str; - str << "(" << p.X() << ", " << p.Y() << ", " << p.Z() << ")"; - return str.str(); - }) - // .def(py::self - py::self) - .def("__sub__", [](gp_Pnt p1, gp_Pnt p2) { return gp_Vec(p1.X()-p2.X(), p1.Y()-p2.Y(), p1.Z()-p2.Z()); }) - .def("__add__", [](gp_Pnt p, gp_Vec v) { return gp_Pnt(p.X()+v.X(), p.Y()+v.Y(), p.Z()+v.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); - })) - .def_property("x", [](gp_Vec&p) { return p.X(); }, [](gp_Vec&p,double x) { p.SetX(x); }) - .def_property("y", [](gp_Vec&p) { return p.Y(); }, [](gp_Vec&p,double y) { p.SetY(y); }) - .def_property("z", [](gp_Vec&p) { return p.Z(); }, [](gp_Vec&p,double z) { p.SetZ(z); }) - .def("__str__", [] (const gp_Vec & p) { - stringstream str; - str << "(" << p.X() << ", " << p.Y() << ", " << p.Z() << ")"; - return str.str(); - }) - .def("__add__", [](gp_Vec v1, gp_Vec v2) { return gp_Vec(v1.X()+v2.X(), v1.Y()+v2.Y(), v1.Z()+v2.Z()); }) - .def("__sub__", [](gp_Vec v1, gp_Vec v2) { return gp_Vec(v1.X()-v2.X(), v1.Y()-v2.Y(), v1.Z()-v2.Z()); }) - .def("__rmul__", [](gp_Vec v, double s) { return gp_Vec(s*v.X(), s*v.Y(), s*v.Z()); }) - .def("__neg__", [](gp_Vec v) { return gp_Vec(-v.X(), -v.Y(), -v.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])); - })) - .def(py::init([] (double x, double y, double z) { - return gp_Dir(x, y, z); - })) - .def(py::init()) - .def("__str__", [] (const gp_Dir & p) { - stringstream str; - str << "(" << p.X() << ", " << p.Y() << ", " << p.Z() << ")"; - return str.str(); - }) - ; - - 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); - })) - .def(py::init([](const gp_Ax3 & ax3) { - return gp_Ax2(ax3.Ax2()); - })) - ; - - py::class_(m, "gp_Ax3") - .def(py::init([](gp_Pnt p, gp_Dir N, gp_Dir Vx) { - return gp_Ax3(p,N, Vx); - }), py::arg("p"), py::arg("n"), py::arg("x")) - .def(py::init()) - .def_property("p", [](gp_Ax3 & ax) { return ax.Location(); }, [](gp_Ax3&ax, gp_Pnt p) { ax.SetLocation(p); }) - ; - - - 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("Translation", [] (const gp_Vec & v) { gp_Trsf trafo; trafo.SetTranslation(v); return trafo; }) - .def_static("Scale", [] (const gp_Pnt & p, double s) { gp_Trsf trafo; trafo.SetScale(p,s); 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_static("Rotation", [] (const gp_Pnt & p, const gp_Dir & d, double ang) - { gp_Trsf trafo; trafo.SetRotation(gp_Ax1(p,d), ang); return trafo; }) - .def_static("Transformation", [] (const gp_Ax3 & ax) { gp_Trsf trafo; trafo.SetTransformation(ax); return trafo; }) - .def_static("Transformation", [] (const gp_Ax3 & from, const gp_Ax3 to) - { gp_Trsf trafo; trafo.SetTransformation(from, to); return trafo; }) - .def(py::self * py::self) - .def("__call__", [] (gp_Trsf & trafo, const TopoDS_Shape & shape) { - return BRepBuilderAPI_Transform(shape, trafo).Shape(); - }) - .def("__str__", [](gp_Trsf & trafo) - { - stringstream str; - gp_XYZ xyz = trafo.TranslationPart(); - str << xyz.X() << ", " << xyz.Y() << ", " << xyz.Z(); - return str.str(); - }) - ; - - py::class_(m, "TopLoc_Location") - .def(py::init()) - .def("Transformation", [](const TopLoc_Location & loc) { return loc.Transformation(); }) - ; - - py::implicitly_convertible(); - py::implicitly_convertible(); - py::implicitly_convertible(); - py::implicitly_convertible(); - py::implicitly_convertible(); - py::implicitly_convertible(); - py::implicitly_convertible(); - - - py::implicitly_convertible(); - - static gp_Vec ex(1,0,0), ey(0,1,0), ez(0,0,1); - m.attr("X") = py::cast(&ex); - m.attr("Y") = py::cast(&ey); - m.attr("Z") = py::cast(&ez); - - class ListOfShapes : public std::vector { }; - - - 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; - */ - ListOfShapes sub; - for (TopExp_Explorer e(shape, type); e.More(); e.Next()) - sub.push_back(e.Current()); - return sub; - }) - - .def_property_readonly("faces", [] (const TopoDS_Shape & shape) - { - ListOfShapes sub; - for (TopExp_Explorer e(shape, TopAbs_FACE); e.More(); e.Next()) - sub.push_back(e.Current()); - return sub; - }) - .def_property_readonly("edges", [] (const TopoDS_Shape & shape) - { - ListOfShapes sub; - for (TopExp_Explorer e(shape, TopAbs_EDGE); e.More(); e.Next()) - sub.push_back(e.Current()); - return sub; - }) - .def_property_readonly("vertices", [] (const TopoDS_Shape & shape) - { - ListOfShapes sub; - for (TopExp_Explorer e(shape, TopAbs_VERTEX); e.More(); e.Next()) - sub.push_back(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_property_readonly("center", [](const TopoDS_Shape & shape) { - GProp_GProps props; - switch (shape.ShapeType()) - { - case TopAbs_FACE: - BRepGProp::SurfaceProperties (shape, props); break; - default: - BRepGProp::LinearProperties(shape, props); - } - return props.CentreOfMass(); - }) - - .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_property("location", - [](const TopoDS_Shape & shape) { return shape.Location(); }, - [](TopoDS_Shape & shape, const TopLoc_Location & loc) - { shape.Location(loc); }) - .def("Located", [](const TopoDS_Shape & shape, const TopLoc_Location & loc) - { return shape.Located(loc); }) - - .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("Reversed", [](const TopoDS_Shape & shape) { - return CastShape(shape.Reversed()); }) - - .def("Find", [](const TopoDS_Shape & shape, gp_Pnt p) - { - // find sub-shape contianing point - // BRepClass_FaceClassifier::Perform (p); - }) - - .def("MakeFillet", [](const 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(); - }) - - .def("MakeThickSolid", [](const 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(); - }) - - .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_Vertex") - .def(py::init([] (const TopoDS_Shape & shape) { - return TopoDS::Vertex(shape); - })) - .def_property_readonly("p", [] (const TopoDS_Vertex & v) -> gp_Pnt { - return BRep_Tool::Pnt (v); }) - ; - - py::class_ (m, "TopoDS_Edge") - .def(py::init([] (const TopoDS_Shape & shape) { - return TopoDS::Edge(shape); - })) - .def_property_readonly("start", - [](const TopoDS_Edge & e) { - double s0, s1; - auto curve = BRep_Tool::Curve(e, s0, s1); - return curve->Value(s0); - }) - .def_property_readonly("end", - [](const TopoDS_Edge & e) { - double s0, s1; - auto curve = BRep_Tool::Curve(e, s0, s1); - return curve->Value(s1); - }) - ; - py::class_ (m, "TopoDS_Wire"); - py::class_ (m, "TopoDS_Face") - .def(py::init([] (const TopoDS_Shape & shape) { - return TopoDS::Face(shape); - })) - /* - .def("surf", [] (TopoDS_Face face) -> Handle(Geom_Surface) - { - Handle(Geom_Surface) surf = BRep_Tool::Surface (face); - return surf; - }) - */ - ; - py::class_ (m, "TopoDS_Solid"); - - - - py::implicitly_convertible(); - - class ListOfShapesIterator - { - TopoDS_Shape * ptr; - public: - ListOfShapesIterator (TopoDS_Shape * aptr) : ptr(aptr) { } - ListOfShapesIterator operator++ () { return ListOfShapesIterator(++ptr); } - auto operator*() const { return CastShape(*ptr); } - bool operator!=(ListOfShapesIterator it2) const { return ptr != it2.ptr; } - bool operator==(ListOfShapesIterator it2) const { return ptr == it2.ptr; } - - }; - - py::class_ (m, "ListOfShapes") - .def("__iter__", [](ListOfShapes &s) { - return py::make_iterator(ListOfShapesIterator(&*s.begin()), - ListOfShapesIterator(&*s.end())); - }, - py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */) - .def("__getitem__", [](const ListOfShapes & list, size_t i) { - return CastShape(list[i]); }) - .def("__add__", [](const ListOfShapes & l1, const ListOfShapes & l2) { - ListOfShapes l = l1; - for (auto s : l2) l.push_back(s); - return l; - } ) - .def("__add__", [](const ListOfShapes & l1, py::list l2) { - ListOfShapes l = l1; - for (auto s : l2) l.push_back(py::cast(s)); - return l; - } ) - .def("__len__", [](const ListOfShapes & l) { return l.size(); }) - .def("Max", [] (ListOfShapes & shapes, gp_Vec dir) - { - double maxval = -1e99; - TopoDS_Shape maxshape; - for (auto shape : shapes) - { - GProp_GProps props; - gp_Pnt center; - - switch (shape.ShapeType()) - { - case TopAbs_VERTEX: - center = BRep_Tool::Pnt (TopoDS::Vertex(shape)); break; - case TopAbs_FACE: - BRepGProp::SurfaceProperties (shape, props); - center = props.CentreOfMass(); - break; - default: - BRepGProp::LinearProperties(shape, props); - center = props.CentreOfMass(); - } - - double val = center.X()*dir.X() + center.Y()*dir.Y() + center.Z() * dir.Z(); - if (val > maxval) - { - maxval = val; - maxshape = shape; - } - } - return CastShape(maxshape); - }) - - ; - - - 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); - }) - .def_property_readonly("start", [](Handle(Geom2d_Curve) curve) { - return curve->Value(curve->FirstParameter()); - }) - .def_property_readonly("end", [](Handle(Geom2d_Curve) curve) { - return curve->Value(curve->LastParameter()); - }) - ; - - - 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(); - }, py::arg("p"), py::arg("d"), py::arg("r"), py::arg("h")); - m.def("Cylinder", [] (gp_Ax2 ax, double r, double h) { - return BRepPrimAPI_MakeCylinder (ax, r, h).Solid(); - }, py::arg("axis"), py::arg("r"), py::arg("h")); - - 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(); - }); - - m.def("Pipe", [] (const TopoDS_Wire & spine, const TopoDS_Shape & profile) { - return BRepOffsetAPI_MakePipe (spine, profile).Shape(); - }, py::arg("spine"), py::arg("profile")); - - // 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("Circle", [](gp_Pnt2d p1, double r) -> Handle(Geom2d_Curve) { - Handle(Geom2d_Circle) curve = GCE2d_MakeCircle(p1, r); - return curve; - // gp_Ax2d ax; ax.SetLocation(p1); - // return new Geom2d_Circle(ax, r); - }); - - 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(); - }, py::arg("p1"), py::arg("p2"), py::arg("p3")); - - m.def("ArcOfCircle", [](gp_Pnt p1, gp_Vec v, gp_Pnt p2) { - Handle(Geom_TrimmedCurve) curve = GC_MakeArcOfCircle(p1, v, p2); - return BRepBuilderAPI_MakeEdge(curve).Edge(); - }, py::arg("p1"), py::arg("v"), py::arg("p2")); - - - 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: - try - { - builder.Add(TopoDS::Edge(s)); break; - } - catch (Standard_Failure & e) - { - e.Print(cout); - throw NgException("cannot add to wire"); - } - case TopAbs_WIRE: - builder.Add(TopoDS::Wire(s)); break; - default: - throw Exception("can make wire only from edges and wires"); - } - try - { - return builder.Wire(); - } - catch (Standard_Failure & e) - { - e.Print(cout); - throw NgException("error in wire builder"); - } - }); - - m.def("Face", [](TopoDS_Wire wire) { - return BRepBuilderAPI_MakeFace(wire).Face(); - }, py::arg("w")); - m.def("Face", [](const TopoDS_Face & face, const TopoDS_Wire & wire) { - // return BRepBuilderAPI_MakeFace(face, wire).Face(); - return BRepBuilderAPI_MakeFace(BRep_Tool::Surface (face), wire).Face(); - }, py::arg("f"), py::arg("w")); - m.def("Face", [](const TopoDS_Face & face, std::vector wires) { - // return BRepBuilderAPI_MakeFace(face, wire).Face(); - cout << "build from list of wires" << endl; - auto surf = BRep_Tool::Surface (face); - BRepBuilderAPI_MakeFace builder(surf, 1e-8); - for (auto w : wires) - builder.Add(w); - return builder.Face(); - }, py::arg("f"), py::arg("w")); - /* - not yet working .... ? - m.def("Face", [](std::vector wires) { - cout << "face from wires" << endl; - BRepBuilderAPI_MakeFace builder; - for (auto w : wires) - { - cout << "add wire" << endl; - builder.Add(w); - } - return builder.Face(); - }, py::arg("w")); - */ - - m.def("MakeFillet", [](TopoDS_Shape shape, std::vector edges, double r) { - throw Exception("call 'shape.MakeFilled'"); - 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) { - throw Exception("call 'shape.MakeThickSolid'"); - 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) { diff --git a/libsrc/occ/python_occ_shapes.cpp b/libsrc/occ/python_occ_shapes.cpp new file mode 100644 index 00000000..08914eca --- /dev/null +++ b/libsrc/occ/python_occ_shapes.cpp @@ -0,0 +1,765 @@ +#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 +#include +#include + +#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=4 +#define OCC_HAVE_DUMP_JSON +#endif + +using namespace netgen; + + +py::object CastShape(const TopoDS_Shape & s) +{ + switch (s.ShapeType()) + { + case TopAbs_VERTEX: + return py::cast(TopoDS::Vertex(s)); + case TopAbs_FACE: + return py::cast(TopoDS::Face(s)); + case TopAbs_EDGE: + return py::cast(TopoDS::Edge(s)); + case TopAbs_WIRE: + return py::cast(TopoDS::Wire(s)); + + case TopAbs_COMPOUND: + case TopAbs_COMPSOLID: + case TopAbs_SOLID: + case TopAbs_SHELL: + case TopAbs_SHAPE: + return py::cast(s); + } +}; + + +DLL_HEADER void ExportNgOCCShapes(py::module &m) +{ + cout << "export shapes" << endl; + 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() + ; + + + class ListOfShapes : public std::vector { }; + + + 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) + { + cout << "WARNING: pls use 'shape' instead of 'ShapeType()'" << endl; + 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; + */ + ListOfShapes sub; + for (TopExp_Explorer e(shape, type); e.More(); e.Next()) + sub.push_back(e.Current()); + return sub; + }) + + .def_property_readonly("faces", [] (const TopoDS_Shape & shape) + { + ListOfShapes sub; + for (TopExp_Explorer e(shape, TopAbs_FACE); e.More(); e.Next()) + sub.push_back(e.Current()); + return sub; + }) + .def_property_readonly("edges", [] (const TopoDS_Shape & shape) + { + ListOfShapes sub; + for (TopExp_Explorer e(shape, TopAbs_EDGE); e.More(); e.Next()) + sub.push_back(e.Current()); + return sub; + }) + .def_property_readonly("vertices", [] (const TopoDS_Shape & shape) + { + ListOfShapes sub; + for (TopExp_Explorer e(shape, TopAbs_VERTEX); e.More(); e.Next()) + sub.push_back(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_property_readonly("center", [](const TopoDS_Shape & shape) { + GProp_GProps props; + switch (shape.ShapeType()) + { + case TopAbs_FACE: + BRepGProp::SurfaceProperties (shape, props); break; + default: + BRepGProp::LinearProperties(shape, props); + } + return props.CentreOfMass(); + }) + + .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_property("location", + [](const TopoDS_Shape & shape) { return shape.Location(); }, + [](TopoDS_Shape & shape, const TopLoc_Location & loc) + { shape.Location(loc); }) + .def("Located", [](const TopoDS_Shape & shape, const TopLoc_Location & loc) + { return shape.Located(loc); }) + + .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("Reversed", [](const TopoDS_Shape & shape) { + return CastShape(shape.Reversed()); }) + + .def("Find", [](const TopoDS_Shape & shape, gp_Pnt p) + { + // find sub-shape contianing point + // BRepClass_FaceClassifier::Perform (p); + }) + + .def("MakeFillet", [](const 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(); + }) + + .def("MakeThickSolid", [](const 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(); + }) + + .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_Vertex") + .def(py::init([] (const TopoDS_Shape & shape) { + return TopoDS::Vertex(shape); + })) + .def_property_readonly("p", [] (const TopoDS_Vertex & v) -> gp_Pnt { + return BRep_Tool::Pnt (v); }) + ; + + py::class_ (m, "TopoDS_Edge") + .def(py::init([] (const TopoDS_Shape & shape) { + return TopoDS::Edge(shape); + })) + .def_property_readonly("start", + [](const TopoDS_Edge & e) { + double s0, s1; + auto curve = BRep_Tool::Curve(e, s0, s1); + return curve->Value(s0); + }) + .def_property_readonly("end", + [](const TopoDS_Edge & e) { + double s0, s1; + auto curve = BRep_Tool::Curve(e, s0, s1); + return curve->Value(s1); + }) + ; + py::class_ (m, "TopoDS_Wire"); + py::class_ (m, "TopoDS_Face") + .def(py::init([] (const TopoDS_Shape & shape) { + return TopoDS::Face(shape); + })) + /* + .def("surf", [] (TopoDS_Face face) -> Handle(Geom_Surface) + { + Handle(Geom_Surface) surf = BRep_Tool::Surface (face); + return surf; + }) + */ + ; + py::class_ (m, "TopoDS_Solid"); + + + + py::implicitly_convertible(); + + + + class ListOfShapesIterator + { + TopoDS_Shape * ptr; + public: + ListOfShapesIterator (TopoDS_Shape * aptr) : ptr(aptr) { } + ListOfShapesIterator operator++ () { return ListOfShapesIterator(++ptr); } + auto operator*() const { return CastShape(*ptr); } + bool operator!=(ListOfShapesIterator it2) const { return ptr != it2.ptr; } + bool operator==(ListOfShapesIterator it2) const { return ptr == it2.ptr; } + + }; + + py::class_ (m, "ListOfShapes") + .def("__iter__", [](ListOfShapes &s) { + return py::make_iterator(ListOfShapesIterator(&*s.begin()), + ListOfShapesIterator(&*s.end())); + }, + py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */) + .def("__getitem__", [](const ListOfShapes & list, size_t i) { + return CastShape(list[i]); }) + + .def("__getitem__", [](const ListOfShapes & self, py::slice inds) { + size_t start, step, n, stop; + if (!inds.compute(self.size(), &start, &stop, &step, &n)) + throw py::error_already_set(); + ListOfShapes sub; + sub.reserve(n); + for (size_t i = 0; i < n; i++) + sub.push_back (self[start+i*step]); + return sub; + }) + + .def("__add__", [](const ListOfShapes & l1, const ListOfShapes & l2) { + ListOfShapes l = l1; + for (auto s : l2) l.push_back(s); + return l; + } ) + .def("__add__", [](const ListOfShapes & l1, py::list l2) { + ListOfShapes l = l1; + for (auto s : l2) l.push_back(py::cast(s)); + return l; + } ) + .def("__len__", [](const ListOfShapes & l) { return l.size(); }) + .def("Max", [] (ListOfShapes & shapes, gp_Vec dir) + { + double maxval = -1e99; + TopoDS_Shape maxshape; + for (auto shape : shapes) + { + GProp_GProps props; + gp_Pnt center; + + switch (shape.ShapeType()) + { + case TopAbs_VERTEX: + center = BRep_Tool::Pnt (TopoDS::Vertex(shape)); break; + case TopAbs_FACE: + BRepGProp::SurfaceProperties (shape, props); + center = props.CentreOfMass(); + break; + default: + BRepGProp::LinearProperties(shape, props); + center = props.CentreOfMass(); + } + + double val = center.X()*dir.X() + center.Y()*dir.Y() + center.Z() * dir.Z(); + if (val > maxval) + { + maxval = val; + maxshape = shape; + } + } + return CastShape(maxshape); + }) + + ; + + + + + + + + + + + + + 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); + }) + .def_property_readonly("start", [](Handle(Geom2d_Curve) curve) { + return curve->Value(curve->FirstParameter()); + }) + .def_property_readonly("end", [](Handle(Geom2d_Curve) curve) { + return curve->Value(curve->LastParameter()); + }) + ; + + + 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(); + }, py::arg("p"), py::arg("d"), py::arg("r"), py::arg("h")); + m.def("Cylinder", [] (gp_Ax2 ax, double r, double h) { + return BRepPrimAPI_MakeCylinder (ax, r, h).Solid(); + }, py::arg("axis"), py::arg("r"), py::arg("h")); + + 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(); + }); + + m.def("Pipe", [] (const TopoDS_Wire & spine, const TopoDS_Shape & profile) { + return BRepOffsetAPI_MakePipe (spine, profile).Shape(); + }, py::arg("spine"), py::arg("profile")); + + // 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("Circle", [](gp_Pnt2d p1, double r) -> Handle(Geom2d_Curve) { + Handle(Geom2d_Circle) curve = GCE2d_MakeCircle(p1, r); + return curve; + // gp_Ax2d ax; ax.SetLocation(p1); + // return new Geom2d_Circle(ax, r); + }); + + 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(); + }, py::arg("p1"), py::arg("p2"), py::arg("p3")); + + m.def("ArcOfCircle", [](gp_Pnt p1, gp_Vec v, gp_Pnt p2) { + Handle(Geom_TrimmedCurve) curve = GC_MakeArcOfCircle(p1, v, p2); + return BRepBuilderAPI_MakeEdge(curve).Edge(); + }, py::arg("p1"), py::arg("v"), py::arg("p2")); + + + 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: + try + { + builder.Add(TopoDS::Edge(s)); break; + } + catch (Standard_Failure & e) + { + e.Print(cout); + throw NgException("cannot add to wire"); + } + case TopAbs_WIRE: + builder.Add(TopoDS::Wire(s)); break; + default: + throw Exception("can make wire only from edges and wires"); + } + try + { + return builder.Wire(); + } + catch (Standard_Failure & e) + { + e.Print(cout); + throw NgException("error in wire builder"); + } + }); + + m.def("Face", [](TopoDS_Wire wire) { + return BRepBuilderAPI_MakeFace(wire).Face(); + }, py::arg("w")); + m.def("Face", [](const TopoDS_Face & face, const TopoDS_Wire & wire) { + // return BRepBuilderAPI_MakeFace(face, wire).Face(); + return BRepBuilderAPI_MakeFace(BRep_Tool::Surface (face), wire).Face(); + }, py::arg("f"), py::arg("w")); + m.def("Face", [](const TopoDS_Face & face, std::vector wires) { + // return BRepBuilderAPI_MakeFace(face, wire).Face(); + cout << "build from list of wires" << endl; + auto surf = BRep_Tool::Surface (face); + BRepBuilderAPI_MakeFace builder(surf, 1e-8); + for (auto w : wires) + builder.Add(w); + return builder.Face(); + }, py::arg("f"), py::arg("w")); + /* + not yet working .... ? + m.def("Face", [](std::vector wires) { + cout << "face from wires" << endl; + BRepBuilderAPI_MakeFace builder; + for (auto w : wires) + { + cout << "add wire" << endl; + builder.Add(w); + } + return builder.Face(); + }, py::arg("w")); + */ + + m.def("MakeFillet", [](TopoDS_Shape shape, std::vector edges, double r) { + throw Exception("call 'shape.MakeFilled'"); + 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) { + throw Exception("call 'shape.MakeThickSolid'"); + 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(); + }); + + + + + +} + +#endif // OCCGEOMETRY +#endif // NG_PYTHON