#ifdef NG_PYTHON #include <../general/ngpython.hpp> #include using namespace netgen; namespace netgen { extern shared_ptr ng_geometry; } // a shadow solid tree using shared pointers. class SPSolid { shared_ptr s1, s2; Solid * solid; int bc = -1; string bcname = ""; double maxh = -1; string material; bool owner; double red, green, blue; bool transp = false; public: enum optyp { TERM, SECTION, UNION, SUB }; SPSolid (Solid * as) : solid(as), owner(true), op(TERM) { ; } ~SPSolid () { ; // if (owner) delete solid; } SPSolid (optyp aop, shared_ptr as1, shared_ptr as2) : s1(as1), s2(as2), owner(true), op(aop) { if (aop == UNION) solid = new Solid (Solid::UNION, s1->GetSolid(), s2->GetSolid()); else if (aop == SECTION) solid = new Solid (Solid::SECTION, s1->GetSolid(), s2->GetSolid()); else if (aop == SUB) solid = new Solid (Solid::SUB, s1->GetSolid()); // , s2->GetSolid()); } Solid * GetSolid() { return solid; } const Solid * GetSolid() const { return solid; } void GiveUpOwner() { owner = false; if (s1) s1 -> GiveUpOwner(); if (s2) s2 -> GiveUpOwner(); } void AddSurfaces(CSGeometry & geom) { if (op == TERM) geom.AddSurfaces (solid->GetPrimitive()); if (s1) s1 -> AddSurfaces (geom); if (s2) s2 -> AddSurfaces (geom); } void SetMaterial (string mat) { material = mat; } string GetMaterial () { if (!material.empty()) return material; if (s1) { string s1mat = s1->GetMaterial(); if (!s1mat.empty()) return s1mat; } if (s2) { string s2mat = s2->GetMaterial(); if (!s2mat.empty()) return s2mat; } return material; } void SetBC(int abc) { if (bc == -1) { bc = abc; if (s1) s1 -> SetBC(bc); if (s2) s2 -> SetBC(bc); if (op == TERM) { Primitive * prim = solid -> GetPrimitive(); for (int i = 0; i < prim->GetNSurfaces(); i++) prim->GetSurface(i).SetBCProperty (abc); // cout << "set " << prim->GetNSurfaces() << " surfaces to bc " << bc << endl; } } } void SetBCName(string name) { if (bcname == "") { bcname = name; if (s1) s1 -> SetBCName(name); if (s2) s2 -> SetBCName(name); if (op == TERM) { Primitive * prim = solid -> GetPrimitive(); for (int i = 0; i < prim->GetNSurfaces(); i++) prim->GetSurface(i).SetBCName (name); // cout << "set " << prim->GetNSurfaces() << " surfaces to bc " << bc << endl; } } } void SetMaxH(double amaxh) { if (maxh == -1) { maxh = amaxh; if (s1) s1 -> SetMaxH(maxh); if (s2) s2 -> SetMaxH(maxh); if (op == TERM) { Primitive * prim = solid -> GetPrimitive(); for (int i = 0; i < prim->GetNSurfaces(); i++) prim->GetSurface(i).SetMaxH (maxh); } } } void SetColor(double ared, double agreen, double ablue) { red = ared; green = agreen; blue = ablue; } double GetRed() const { return red; } double GetGreen() const { return green; } double GetBlue() const { return blue; } void SetTransparent() { transp = true; } bool IsTransparent() { return transp; } private: optyp op; }; inline ostream & operator<< (ostream & ost, const SPSolid & sol) { ost << *sol.GetSolid(); return ost; } namespace netgen { extern CSGeometry * ParseCSG (istream & istr, CSGeometry *instance=nullptr); } static Transformation<3> global_trafo(Vec<3> (0,0,0)); DLL_HEADER void ExportCSG(py::module &m) { py::class_(m, "NGDummyArgument") .def("__bool__", []( NGDummyArgument &self ) { return false; } ) ; py::class_> (m, "Point2d") .def(py::init()) .def ("__str__", &ToString>) .def(py::self-py::self) .def(py::self+Vec<2>()) .def(py::self-Vec<2>()) ; py::class_> (m, "Point3d") .def(py::init()) .def ("__str__", &ToString>) .def(py::self-py::self) .def(py::self+Vec<3>()) .def(py::self-Vec<3>()) ; m.def ("Pnt", FunctionPointer ([](double x, double y, double z) { return global_trafo(Point<3>(x,y,z)); })); m.def ("Pnt", FunctionPointer ([](double x, double y) { return Point<2>(x,y); })); m.def ("Pnt", FunctionPointer ([](double x, double y, double z) { return Point<3>(x,y,z); })); m.def ("Pnt", FunctionPointer ([](double x, double y) { return Point<2>(x,y); })); m.def ("SetTransformation", FunctionPointer ([](int dir, double angle) { if (dir > 0) global_trafo.SetAxisRotation (dir, angle*M_PI/180); else global_trafo = Transformation<3> (Vec<3>(0,0,0)); }), py::arg("dir")=int(0), py::arg("angle")=int(0)); py::class_> (m, "Vec2d") .def(py::init()) .def ("__str__", &ToString>) .def(py::self+py::self) .def(py::self-py::self) .def(-py::self) .def(double()*py::self) .def("Norm", &Vec<2>::Length) ; py::class_> (m, "Vec3d") .def(py::init()) .def ("__str__", &ToString>) .def(py::self+py::self) .def(py::self-py::self) .def(-py::self) .def(double()*py::self) .def("Norm", &Vec<3>::Length) ; m.def ("Vec", FunctionPointer ([] (double x, double y, double z) { return global_trafo(Vec<3>(x,y,z)); })); m.def ("Vec", FunctionPointer ([] (double x, double y) { return Vec<2>(x,y); })); py::class_> (m, "SplineCurve2d") .def(py::init<>()) .def ("AddPoint", FunctionPointer ([] (SplineGeometry<2> & self, double x, double y) { self.geompoints.Append (GeomPoint<2> (Point<2> (x,y))); return self.geompoints.Size()-1; })) .def ("AddSegment", FunctionPointer ([] (SplineGeometry<2> & self, int i1, int i2) { self.splines.Append (new LineSeg<2> (self.geompoints[i1], self.geompoints[i2])); })) .def ("AddSegment", FunctionPointer ([] (SplineGeometry<2> & self, int i1, int i2, int i3) { self.splines.Append (new SplineSeg3<2> (self.geompoints[i1], self.geompoints[i2], self.geompoints[i3])); })) ; py::class_,shared_ptr>> (m,"SplineCurve3d") .def ("AddPoint", FunctionPointer ([] (SplineGeometry<3> & self, double x, double y, double z) { self.geompoints.Append (GeomPoint<3> (Point<3> (x,y,z))); return self.geompoints.Size()-1; })) .def ("AddSegment", FunctionPointer ([] (SplineGeometry<3> & self, int i1, int i2) { self.splines.Append (new LineSeg<3> (self.geompoints[i1], self.geompoints[i2])); })) .def ("AddSegment", FunctionPointer ([] (SplineGeometry<3> & self, int i1, int i2, int i3) { self.splines.Append (new SplineSeg3<3> (self.geompoints[i1], self.geompoints[i2], self.geompoints[i3])); })) ; py::class_> (m, "SplineSurface", "A surface for co dim 2 integrals on the splines") .def("__init__", FunctionPointer ([](SplineSurface* instance, shared_ptr base, py::list cuts) { auto primitive = dynamic_cast (base->GetSolid()->GetPrimitive()); auto acuts = new Array(); for(int i = 0; i> sps(cuts[i]); if(!sps.check()) throw NgException("Cut must be SurfacePrimitive in constructor of SplineSurface!"); auto sp = dynamic_cast(sps()->GetSolid()->GetPrimitive()); if(sp) acuts->Append(sp); else throw NgException("Cut must be SurfacePrimitive in constructor of SplineSurface!"); } if(!primitive) throw NgException("Base is not a SurfacePrimitive in constructor of SplineSurface!"); new (instance) SplineSurface(primitive,acuts); }),py::arg("base"), py::arg("cuts")=py::list()) .def("AddPoint", FunctionPointer ([] (SplineSurface & self, double x, double y, double z, bool hpref) { self.AppendPoint(Point<3>(x,y,z),hpref); return self.GetNP()-1; }), py::arg("x"),py::arg("y"),py::arg("z"),py::arg("hpref")=false) .def("AddSegment", FunctionPointer ([] (SplineSurface & self, int i1, int i2, string bcname, double maxh) { auto str = new string(bcname); self.AppendSegment(new LineSeg<3>(self.GetPoint(i1),self.GetPoint(i2)),str,maxh); }), py::arg("pnt1"),py::arg("pnt2"),py::arg("bcname")="default", py::arg("maxh")=-1.) ; py::class_> (m, "Solid") .def ("__str__", &ToString) .def ("__add__", FunctionPointer( [] ( shared_ptr self, shared_ptr other) { return make_shared (SPSolid::UNION, self, other); })) .def ("__mul__", FunctionPointer( [] ( shared_ptr self, shared_ptr other) { return make_shared (SPSolid::SECTION, self, other); })) .def ("__sub__", FunctionPointer ([] ( shared_ptr self, shared_ptr other) { return make_shared (SPSolid::SECTION, self, make_shared (SPSolid::SUB, other, nullptr)); })) .def ("bc", FunctionPointer([](shared_ptr & self, int nr) -> shared_ptr { self->SetBC(nr); return self; })) .def ("bc", FunctionPointer([](shared_ptr & self, string name) -> shared_ptr { self->SetBCName(name); return self; })) .def ("maxh", FunctionPointer([](shared_ptr & self, double maxh) -> shared_ptr { self->SetMaxH(maxh); return self; })) .def ("mat", FunctionPointer([](shared_ptr & self, string mat) -> shared_ptr { self->SetMaterial(mat); return self; })) .def ("mat", &SPSolid::GetMaterial) .def("col", FunctionPointer([](shared_ptr & self, py::list rgb) -> shared_ptr { py::extract red(rgb[0]); py::extract green(rgb[1]); py::extract blue(rgb[2]); self->SetColor(red(),green(),blue()); return self; })) .def("transp", FunctionPointer([](shared_ptr & self)->shared_ptr < SPSolid > { self->SetTransparent(); return self; })) ; m.def ("Sphere", FunctionPointer([](Point<3> c, double r) { Sphere * sp = new Sphere (c, r); Solid * sol = new Solid (sp); return make_shared (sol); })); m.def ("Plane", FunctionPointer([](Point<3> p, Vec<3> n) { Plane * sp = new Plane (p,n); Solid * sol = new Solid (sp); return make_shared (sol); })); m.def ("Cone", FunctionPointer([](Point<3> a, Point<3> b, double ra, double rb) { Cone * cyl = new Cone (a, b, ra, rb); Solid * sol = new Solid (cyl); return make_shared (sol); })); m.def ("Cylinder", FunctionPointer([](Point<3> a, Point<3> b, double r) { Cylinder * cyl = new Cylinder (a, b, r); Solid * sol = new Solid (cyl); return make_shared (sol); })); m.def ("OrthoBrick", FunctionPointer([](Point<3> p1, Point<3> p2) { OrthoBrick * brick = new OrthoBrick (p1,p2); Solid * sol = new Solid (brick); return make_shared (sol); })); m.def ("Revolution", FunctionPointer([](Point<3> p1, Point<3> p2, const SplineGeometry<2> & spline) { Revolution * rev = new Revolution (p1, p2, spline); Solid * sol = new Solid(rev); return make_shared (sol); })); m.def ("Or", FunctionPointer([](shared_ptr s1, shared_ptr s2) { return make_shared (SPSolid::UNION, s1, s2); })); m.def ("And", FunctionPointer([](shared_ptr s1, shared_ptr s2) { return make_shared (SPSolid::SECTION, s1, s2); })); py::class_> (m, "CSGeometry") .def(py::init<>()) .def("__init__", [](CSGeometry *instance, const string & filename) { cout << "load geometry"; ifstream ist(filename); ParseCSG(ist, instance); instance -> FindIdenticSurfaces(1e-8 * instance->MaxSize()); }) .def("__init__", [](CSGeometry *instance, const py::list & solidlist) { cout << "csg from list"; new (instance) CSGeometry(); for (int i = 0; i < len(solidlist); i++) { py::object obj = solidlist[i]; cout << "obj " << i << endl; py::extract> solid(solidlist[i]); if(solid.check()) { cout << "its a solid" << endl; solid()->AddSurfaces (*instance); solid()->GiveUpOwner(); int tlonr = instance->SetTopLevelObject (solid()->GetSolid()); instance->GetTopLevelObject(tlonr) -> SetMaterial(solid()->GetMaterial()); } } instance -> FindIdenticSurfaces(1e-8 * instance->MaxSize()); }) .def("Save", FunctionPointer([] (CSGeometry & self, string filename) { cout << "save geometry to file " << filename << endl; self.Save (filename); })) .def("Add", [] (CSGeometry & self, shared_ptr solid, py::list bcmod) { solid->AddSurfaces (self); solid->GiveUpOwner(); int tlonr = self.SetTopLevelObject (solid->GetSolid()); self.GetTopLevelObject(tlonr) -> SetMaterial(solid->GetMaterial()); self.GetTopLevelObject(tlonr) -> SetRGB(solid->GetRed(),solid->GetGreen(),solid->GetBlue()); self.GetTopLevelObject(tlonr)->SetTransparent(solid->IsTransparent()); // bcmod is list of tuples ( solid, bcnr ) for (int i = 0; i < py::len(bcmod); i++) { py::tuple tup = py::extract (bcmod[i]) (); auto mod_solid = py::extract> (tup[0]) (); int mod_nr = -1; string * bcname = nullptr; py::object val = tup[1]; if (py::extract(val).check()) mod_nr = py::extract (val)(); if (py::extract(val).check()) bcname = new string ( py::extract (val)()); Array si; mod_solid -> GetSolid() -> GetSurfaceIndices (si); // cout << "change bc on surfaces: " << si << " to " << mod_nr << endl; for (int j = 0; j < si.Size(); j++) { CSGeometry::BCModification bcm; bcm.bcname = bcname ? new string (*bcname) : nullptr; bcm.tlonr = tlonr; bcm.si = si[j]; bcm.bcnr = mod_nr; self.bcmodifications.Append (bcm); } delete bcname; } return tlonr; }, py::arg("solid"), py::arg("bcmod")=py::list() ) .def("AddSurface", FunctionPointer ([] (CSGeometry & self, shared_ptr surface, shared_ptr solid) { solid->AddSurfaces (self); solid->GiveUpOwner(); Surface & surf = surface->GetSolid()->GetPrimitive()->GetSurface(); int tlonr = self.SetTopLevelObject (solid->GetSolid(), &surf); // self.GetTopLevelObject(tlonr) -> SetMaterial(solid->GetMaterial()); self.GetTopLevelObject(tlonr) -> SetBCProp(surf.GetBCProperty()); self.GetTopLevelObject(tlonr) -> SetBCName(surf.GetBCName()); self.GetTopLevelObject(tlonr) -> SetRGB(solid->GetRed(),solid->GetGreen(),solid->GetBlue()); self.GetTopLevelObject(tlonr)->SetTransparent(solid->IsTransparent()); }), py::arg("surface"), py::arg("solid") ) .def("AddSplineSurface", FunctionPointer ([] (CSGeometry & self, shared_ptr surf) { auto cuttings = surf->CreateCuttingSurfaces(); auto spsol = make_shared(new Solid(&*surf)); for(auto cut : (*cuttings)){ spsol = make_shared(SPSolid::SECTION,spsol,make_shared(new Solid(cut))); } spsol->AddSurfaces(self); int tlonr = self.SetTopLevelObject(spsol->GetSolid(), &*surf); for(auto p : surf->GetPoints()) self.AddUserPoint(p); }), py::arg("SplineSurface")) .def("CloseSurfaces", FunctionPointer ([] (CSGeometry & self, shared_ptr s1, shared_ptr s2, py::list aslices ) { Array si1, si2; s1->GetSolid()->GetSurfaceIndices (si1); s2->GetSolid()->GetSurfaceIndices (si2); cout << "surface ids1 = " << si1 << endl; cout << "surface ids2 = " << si2 << endl; Flags flags; try { int n = py::len(aslices); Array slices(n); for(int i=0; i(aslices[i])(); } flags.SetFlag("slices", slices); } catch( py::error_already_set const & ) { cout << "caught python error:" << endl; PyErr_Print(); } const TopLevelObject * domain = nullptr; self.AddIdentification (new CloseSurfaceIdentification (self.GetNIdentifications()+1, self, self.GetSurface (si1[0]), self.GetSurface (si2[0]), domain, flags)); }), py::arg("solid1"), py::arg("solid2"), py::arg("slices") ) .def("CloseSurfaces", FunctionPointer ([] (CSGeometry & self, shared_ptr s1, shared_ptr s2, int reflevels) { Array si1, si2; s1->GetSolid()->GetSurfaceIndices (si1); s2->GetSolid()->GetSurfaceIndices (si2); cout << "surface ids1 = " << si1 << endl; cout << "surface ids2 = " << si2 << endl; Flags flags; const TopLevelObject * domain = nullptr; self.AddIdentification (new CloseSurfaceIdentification (self.GetNIdentifications()+1, self, self.GetSurface (si1[0]), self.GetSurface (si2[0]), domain, flags)); }), py::arg("solid1"), py::arg("solid2"), py::arg("reflevels")=2 ) .def("PeriodicSurfaces", FunctionPointer ([] (CSGeometry & self, shared_ptr s1, shared_ptr s2) { Array si1, si2; s1->GetSolid()->GetSurfaceIndices (si1); s2->GetSolid()->GetSurfaceIndices (si2); cout << "identify surfaces " << si1[0] << " and " << si2[0] << endl; self.AddIdentification (new PeriodicIdentification (self.GetNIdentifications()+1, self, self.GetSurface (si1[0]), self.GetSurface (si2[0]))); }), py::arg("solid1"), py::arg("solid2") ) .def("GetTransparent", FunctionPointer ([] (CSGeometry & self, int tlonr) { return self.GetTopLevelObject(tlonr)->GetTransparent(); }), py::arg("tlonr") ) .def("SetTransparent", FunctionPointer ([] (CSGeometry & self, int tlonr, bool transparent) { self.GetTopLevelObject(tlonr)->SetTransparent(transparent); }), py::arg("tlonr"), py::arg("transparent") ) .def("GetVisible", FunctionPointer ([] (CSGeometry & self, int tlonr) { return self.GetTopLevelObject(tlonr)->GetVisible(); }), py::arg("tlonr") ) .def("SetVisible", FunctionPointer ([] (CSGeometry & self, int tlonr, bool visible) { self.GetTopLevelObject(tlonr)->SetVisible(visible); }), py::arg("tlonr"), py::arg("visible") ) .def("SetBoundingBox", FunctionPointer ([] (CSGeometry & self, Point<3> pmin, Point<3> pmax) { self.SetBoundingBox(Box<3> (pmin, pmax)); }), py::arg("pmin"), py::arg("pmax") ) .def("Draw", FunctionPointer ([] (shared_ptr self) { self->FindIdenticSurfaces(1e-6); self->CalcTriangleApproximation(0.01, 20); ng_geometry = self; }) ) .def_property_readonly ("ntlo", &CSGeometry::GetNTopLevelObjects) ; m.def("GenerateMesh", FunctionPointer ([](shared_ptr geo, MeshingParameters & param) { auto dummy = make_shared(); SetGlobalMesh (dummy); dummy->SetGeometry(geo); ng_geometry = geo; geo->FindIdenticSurfaces(1e-8 * geo->MaxSize()); try { geo->GenerateMesh (dummy, param); } catch (NgException ex) { cout << "Caught NgException: " << ex.What() << endl; } return dummy; })) ; m.def("Save", FunctionPointer ([](const Mesh & self, const string & filename, const CSGeometry & geom) { ostream * outfile; if (filename.substr (filename.length()-3, 3) == ".gz") outfile = new ogzstream (filename.c_str()); else outfile = new ofstream (filename.c_str()); self.Save (*outfile); *outfile << endl << endl << "endmesh" << endl << endl; geom.SaveToMeshFile (*outfile); delete outfile; })) ; m.def("ZRefinement", FunctionPointer ([](Mesh & mesh, CSGeometry & geom) { ZRefinementOptions opt; opt.minref = 5; ZRefinement (mesh, &geom, opt); })) ; } PYBIND11_PLUGIN(libcsg) { py::module m("csg", "pybind csg"); ExportCSG(m); return m.ptr(); } #endif