From fdfb596e9cc533914b715b9db9deff421372a245 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Thu, 6 Dec 2018 17:53:44 +0100 Subject: [PATCH] archive for CSGeometry --- libsrc/core/CMakeLists.txt | 2 +- libsrc/core/archive.hpp | 59 +++++++++++++++--------- libsrc/core/basearchive.cpp | 10 +++- libsrc/core/basearchive.hpp | 15 +++++- libsrc/core/ngcore.hpp | 1 + libsrc/core/type_traits.hpp | 8 ++++ libsrc/core/version.hpp | 30 ++++++------ libsrc/csg/algprim.cpp | 11 ++++- libsrc/csg/algprim.hpp | 67 +++++++++++++++++++++++++++ libsrc/csg/brick.cpp | 4 ++ libsrc/csg/brick.hpp | 26 ++++++++++- libsrc/csg/csgeom.cpp | 6 ++- libsrc/csg/csgeom.hpp | 2 + libsrc/csg/extrusion.cpp | 11 +++-- libsrc/csg/extrusion.hpp | 25 ++++++++-- libsrc/csg/python_csg.cpp | 5 +- libsrc/csg/revolution.cpp | 21 +++++---- libsrc/csg/revolution.hpp | 20 ++++++-- libsrc/csg/solid.hpp | 2 + libsrc/csg/surface.cpp | 4 ++ libsrc/geom2d/geom2dmesh.cpp | 4 +- libsrc/geom2d/geometry2d.hpp | 36 +++++++++------ libsrc/gprim/spline.cpp | 13 +++--- libsrc/gprim/spline.hpp | 36 +++++++++++++++ libsrc/gprim/splinegeometry.hpp | 4 ++ libsrc/linalg/vector.hpp | 8 ++++ tests/catch/archive.cpp | 82 ++++++++++++++++++++++++++------- tests/pytest/test_pickling.py | 40 ++++++++++++++++ 28 files changed, 444 insertions(+), 108 deletions(-) create mode 100644 libsrc/core/type_traits.hpp create mode 100644 tests/pytest/test_pickling.py diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 332740bb..04efdf01 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -5,6 +5,6 @@ set_target_properties(ngcore PROPERTIES POSITION_INDEPENDENT_CODE ON ) install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) -install(FILES ngcore.hpp archive.hpp basearchive.hpp version.hpp +install(FILES ngcore.hpp archive.hpp basearchive.hpp version.hpp type_traits.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel ) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 7da24f98..4a25748c 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -39,18 +39,20 @@ namespace ngcore { return Write(b); } virtual Archive & operator & (std::string & str) { - if (ptr > 0) FlushBuffer(); int len = str.length(); - fout->write (reinterpret_cast(&len), sizeof(int)); - fout->write (&str[0], len); + (*this) & len; + FlushBuffer(); + if(len) + fout->write (&str[0], len); return *this; } virtual Archive & operator & (char *& str) { - if (ptr > 0) FlushBuffer(); - int len = strlen (str); - fout->write (reinterpret_cast(&len), sizeof(int)); - fout->write (&str[0], len); + long len = str ? strlen (str) : -1; + (*this) & len; + FlushBuffer(); + if(len > 0) + fout->write (&str[0], len); return *this; } void FlushBuffer() @@ -113,18 +115,24 @@ namespace ngcore virtual Archive & operator & (std::string & str) { int len; - Read(len); + (*this) & len; str.resize(len); - fin->read(&str[0], len); + if(len) + fin->read(&str[0], len); return *this; } virtual Archive & operator & (char *& str) { - int len; - Read(len); - str = new char[len+1]; - fin->read(&str[0], len); - str[len] = '\0'; + long len; + (*this) & len; + if(len == -1) + str = nullptr; + else + { + str = new char[len+1]; + fin->read(&str[0], len); + str[len] = '\0'; + } return *this; } @@ -184,9 +192,9 @@ namespace ngcore } virtual Archive & operator & (char *& str) { - int len = strlen (str); - *fout << len << '\n'; - if(len) + long len = str ? strlen (str) : -1; + *this & len; + if(len > 0) { fout->write (&str[0], len); *fout << '\n'; @@ -239,14 +247,21 @@ namespace ngcore } virtual Archive & operator & (char *& str) { - int len; - *fin >> len; + long len; + (*this) & len; char ch; - fin->get(ch); // '\n' + if(len == -1) + { + str = nullptr; + return (*this); + } str = new char[len+1]; if(len) - fin->get(&str[0], len, '\0'); - str[len] = 0; + { + fin->get(ch); // \n + fin->get(&str[0], len+1, '\0'); + } + str[len] = '\0'; return *this; } }; diff --git a/libsrc/core/basearchive.cpp b/libsrc/core/basearchive.cpp index 975006fc..30f493bb 100644 --- a/libsrc/core/basearchive.cpp +++ b/libsrc/core/basearchive.cpp @@ -7,11 +7,17 @@ namespace ngcore { - std::map& GetLibraryVersions() + static std::map library_versions; + std::map& Archive :: GetLibraryVersions() { - static std::map library_versions; return library_versions; } + VersionInfo GetLibraryVersion(const std::string& library) + { return library_versions[library]; } + + void SetLibraryVersion(const std::string& library, VersionInfo version) + { library_versions[library] = version; } + #ifdef WIN // windows does demangling in typeid(T).name() std::string demangle(const char* typeinfo) { return typeinfo; } diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index 9fdf95e0..249c6e22 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -5,7 +5,8 @@ namespace ngcore { class VersionInfo; // Libraries using this archive can store their version here to implement backwards compatibility - std::map& GetLibraryVersions(); + VersionInfo GetLibraryVersion(const std::string& library); + void SetLibraryVersion(const std::string& library, VersionInfo version); class Archive; std::string demangle(const char* typeinfo); @@ -376,6 +377,13 @@ namespace ngcore return *this; } + // const ptr + template + Archive& operator &(const T*& t) + { + return (*this) & const_cast(t); + } + // Write a read only variable template Archive & operator << (const T & t) @@ -386,6 +394,9 @@ namespace ngcore } virtual void FlushBuffer() {} + + protected: + static std::map& GetLibraryVersions(); }; template @@ -394,6 +405,8 @@ namespace ngcore public: RegisterClassForArchive() { + static_assert(all_of_tmpl::value...>, + "Variadic template arguments must be base classes of T"); ClassArchiveInfo info; info.creator = [this,&info](const std::type_info& ti) -> void* { return typeid(T) == ti ? constructIfPossible() diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index 0a37c977..9d600991 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -28,6 +28,7 @@ namespace ngcore } // own includes +#include "type_traits.hpp" #include "basearchive.hpp" #include "version.hpp" #include "archive.hpp" diff --git a/libsrc/core/type_traits.hpp b/libsrc/core/type_traits.hpp new file mode 100644 index 00000000..3d515c08 --- /dev/null +++ b/libsrc/core/type_traits.hpp @@ -0,0 +1,8 @@ + + +namespace ngcore +{ + template struct _BoolArray{}; + template + constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(T || true)...>>::value; +} diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index bf11b3e9..81932695 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -4,13 +4,13 @@ namespace ngcore class VersionInfo { private: - size_t mayor, minor, date, commit_offset; + size_t mayor, minor, release, patch; std::string git_hash; public: - VersionInfo() : mayor(0), minor(0), date(0), commit_offset(0), git_hash("") {} + VersionInfo() : mayor(0), minor(0), release(0), patch(0), git_hash("") {} VersionInfo(std::string vstring) { - minor = date = commit_offset = 0; + minor = release = patch = 0; git_hash = ""; if(vstring.substr(0,1) == "v") vstring = vstring.substr(1,vstring.size()-1); @@ -27,13 +27,13 @@ namespace ngcore if(vstring.size()) { dot = vstring.find("-"); - date = std::stoi(vstring.substr(0,dot)); + release = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1,vstring.size()-dot-1); if(vstring.size()) { dot = vstring.find("-"); - commit_offset = std::stoi(vstring.substr(0,dot)); + patch = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); if(vstring.size()) @@ -46,15 +46,15 @@ namespace ngcore std::string to_string() const { std::string vstring = "v" + std::to_string(mayor); - if(minor || date || commit_offset || git_hash.size()) + if(minor || release || patch || git_hash.size()) { vstring += "." + std::to_string(minor); - if(date || commit_offset || git_hash.size()) + if(release || patch || git_hash.size()) { - vstring += "." + std::to_string(date); - if(commit_offset || git_hash.size()) + vstring += "." + std::to_string(release); + if(patch || git_hash.size()) { - vstring += "-" + std::to_string(commit_offset); + vstring += "-" + std::to_string(patch); if(git_hash.size()) vstring += "-" + git_hash; } @@ -64,13 +64,13 @@ namespace ngcore } bool operator <(const VersionInfo& other) const { - return std::tie(mayor, minor, date, commit_offset) < - std::tie(other.mayor, other.minor, other.date, other.commit_offset); + return std::tie(mayor, minor, release, patch) < + std::tie(other.mayor, other.minor, other.release, other.patch); } bool operator ==(const VersionInfo& other) const { - return mayor == other.mayor && minor == other.minor && date == other.date - && commit_offset == other.commit_offset; + return mayor == other.mayor && minor == other.minor && release == other.release + && patch == other.patch; } bool operator >(const VersionInfo& other) const { return other < (*this); } bool operator <=(const VersionInfo& other) const { return !((*this) > other); } @@ -78,7 +78,7 @@ namespace ngcore void DoArchive(Archive& ar) { - ar & mayor & minor & date & commit_offset & git_hash; + ar & mayor & minor & release & patch & git_hash; } }; } diff --git a/libsrc/csg/algprim.cpp b/libsrc/csg/algprim.cpp index 30dd780e..c324e460 100644 --- a/libsrc/csg/algprim.cpp +++ b/libsrc/csg/algprim.cpp @@ -1941,6 +1941,13 @@ void EllipticCone :: GetTriangleApproximation << R << " " << r << endl; } - - +RegisterClassForArchive regqs; +RegisterClassForArchive regpl; +RegisterClassForArchive regsph; +RegisterClassForArchive regcyl; +RegisterClassForArchive regelcyl; +RegisterClassForArchive regell; +RegisterClassForArchive regcone; +RegisterClassForArchive regellcone; +RegisterClassForArchive regtorus; } diff --git a/libsrc/csg/algprim.hpp b/libsrc/csg/algprim.hpp index 98715fd3..ab496cc7 100644 --- a/libsrc/csg/algprim.hpp +++ b/libsrc/csg/algprim.hpp @@ -47,6 +47,11 @@ namespace netgen virtual void Print (ostream & str) const; virtual void Read (istream & ist); void PrintCoeff (ostream & ost) const; + virtual void DoArchive(Archive& ar) + { + OneSurfacePrimitive::DoArchive(ar); + ar & cxx & cyy & czz & cxy & cxz & cyz & cx & cy & cz & c1; + } }; @@ -64,6 +69,14 @@ namespace netgen public: /// Plane (const Point<3> & ap, Vec<3> an); + // default constructor for archive + Plane() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & p & n & eps_base; + } Point<3> P() const { return p; } Vec<3> N() const { return n; } virtual void GetPrimitiveData (const char *& classname, @@ -130,6 +143,14 @@ namespace netgen public: /// Sphere (const Point<3> & ac, double ar); + // default constructor for archive + Sphere() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & c & r & invr; + } virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; @@ -188,6 +209,14 @@ namespace netgen public: Cylinder (const Point<3> & aa, const Point<3> & ab, double ar); Cylinder (Array & coeffs); + // default constructor for archive + Cylinder() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & b & r & vab; + } Point<3> A() const { return a; } Point<3> B() const { return b; } double R() const { return r; } @@ -250,7 +279,14 @@ namespace netgen EllipticCylinder (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs); EllipticCylinder (Array & coeffs); + // default constructor for archive + EllipticCylinder() {} + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & vl & vs & vab & t0vec & t1vec & vabl & t0 & t1; + } // static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; @@ -299,6 +335,14 @@ namespace netgen const Vec<3> & av1, const Vec<3> & av2, const Vec<3> & av3); + // default constructor for archive + Ellipsoid() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & v1 & v2 & v3 & rmin; + } /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// @@ -339,6 +383,14 @@ namespace netgen /// Cone (const Point<3> & aa, const Point<3> & ab, double ara, double arb); /// + // default constructor for archive + Cone() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & b & ra & rb & minr & vab & t0vec & t1vec & vabl & t0 & t1 & cosphi; + } static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); @@ -383,7 +435,14 @@ namespace netgen /// EllipticCone (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs, double ah, double avlr); + // default constructor for archive + EllipticCone() {} + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & vl & vs & h & vlr; + } static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); @@ -425,6 +484,14 @@ namespace netgen public: /// OK Torus (const Point<3> & ac, const Vec<3> & an, double aR, double ar); + // default constructor for archive + Torus() {} + + virtual void DoArchive(Archive& ar) + { + OneSurfacePrimitive::DoArchive(ar); + ar & c & n & R & r; + } /// OK const Point<3> & Center () const { return c; } /// OK diff --git a/libsrc/csg/brick.cpp b/libsrc/csg/brick.cpp index 54c23b17..b9508fba 100644 --- a/libsrc/csg/brick.cpp +++ b/libsrc/csg/brick.cpp @@ -523,4 +523,8 @@ void OrthoBrick :: Reduce (const BoxSphere<3> & box) surfaceactive.Elem(6) = (box.PMin()(0) < pmax(0)) && (pmax(0) < box.PMax()(0)); } + +RegisterClassForArchive regpar; +RegisterClassForArchive regbrick; +RegisterClassForArchive regob; } diff --git a/libsrc/csg/brick.hpp b/libsrc/csg/brick.hpp index 25b003e0..7db7b02d 100644 --- a/libsrc/csg/brick.hpp +++ b/libsrc/csg/brick.hpp @@ -28,8 +28,16 @@ namespace netgen public: Parallelogram3d (Point<3> ap1, Point<3> ap2, Point<3> ap3); + // default constructor for archive + Parallelogram3d() {} virtual ~Parallelogram3d (); + virtual void DoArchive(Archive& ar) + { + Surface::DoArchive(ar); + ar & p1 & p2 & p3 & p4 & v12 & v13 & n; + } + void SetPoints (Point<3> ap1, Point<3> ap2, Point<3> ap3); virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; @@ -60,7 +68,15 @@ namespace netgen public: Brick (Point<3> ap1, Point<3> ap2, Point<3> ap3, Point<3> ap4); + // default constructor for archive + Brick() {} virtual ~Brick (); + + virtual void DoArchive(Archive& ar) + { + Primitive::DoArchive(ar); + ar & p1 & p2 & p3 & p4 & v12 & v13 & v14 & faces; + } static Primitive * CreateDefault (); virtual Primitive * Copy () const; @@ -116,7 +132,15 @@ namespace netgen Point<3> pmin, pmax; public: OrthoBrick (const Point<3> & ap1, const Point<3> & ap2); - + // default constructor for archive + OrthoBrick() {} + + virtual void DoArchive(Archive& ar) + { + Brick::DoArchive(ar); + ar & pmin & pmax; + } + virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual void Reduce (const BoxSphere<3> & box); }; diff --git a/libsrc/csg/csgeom.cpp b/libsrc/csg/csgeom.cpp index 3662966d..b861d451 100644 --- a/libsrc/csg/csgeom.cpp +++ b/libsrc/csg/csgeom.cpp @@ -327,8 +327,10 @@ namespace netgen void CSGeometry :: DoArchive(Archive& archive) { archive & surfaces & solids & toplevelobjects & userpoints & userpoints_ref_factor - & identpoints & boundingbox & identicsurfaces & isidenticto & ideps - & filename & spline_surfaces; // TODO: & splinecurves2d & splinecurves3d & surf2prim + & identpoints & boundingbox & isidenticto & ideps + & filename & spline_surfaces & splinecurves2d & splinecurves3d & surf2prim; + if(archive.Input()) + FindIdenticSurfaces(1e-6); } void CSGeometry :: SaveSurfaces (ostream & out) const diff --git a/libsrc/csg/csgeom.hpp b/libsrc/csg/csgeom.hpp index ab91b08a..f1a8d8b6 100644 --- a/libsrc/csg/csgeom.hpp +++ b/libsrc/csg/csgeom.hpp @@ -39,6 +39,8 @@ namespace netgen public: TopLevelObject (Solid * asolid, Surface * asurface = NULL); + // default constructor for archive + TopLevelObject() {} void DoArchive(Archive& archive) { diff --git a/libsrc/csg/extrusion.cpp b/libsrc/csg/extrusion.cpp index 8b257c20..61446b0c 100644 --- a/libsrc/csg/extrusion.cpp +++ b/libsrc/csg/extrusion.cpp @@ -653,15 +653,15 @@ namespace netgen Extrusion :: Extrusion(const SplineGeometry<3> & path_in, const SplineGeometry<2> & profile_in, const Vec<3> & z_dir) : - path(path_in), profile(profile_in), z_direction(z_dir) + path(&path_in), profile(&profile_in), z_direction(z_dir) { surfaceactive.SetSize(0); surfaceids.SetSize(0); - for(int j=0; jGetNSplines(); j++) { - ExtrusionFace * face = new ExtrusionFace(&(profile.GetSpline(j)), - &path, + ExtrusionFace * face = new ExtrusionFace(&((*profile).GetSpline(j)), + path, z_direction); faces.Append(face); surfaceactive.Append(true); @@ -872,5 +872,6 @@ namespace netgen surfaceactive[i] = true; } - + RegisterClassForArchive regexf; + RegisterClassForArchive regextr; } diff --git a/libsrc/csg/extrusion.hpp b/libsrc/csg/extrusion.hpp index e80ac244..2d6b3bbe 100644 --- a/libsrc/csg/extrusion.hpp +++ b/libsrc/csg/extrusion.hpp @@ -49,9 +49,18 @@ namespace netgen const Vec<3> & z_direction); ExtrusionFace(const Array & raw_data); - + // default constructor for archive + ExtrusionFace() {} ~ExtrusionFace(); + + virtual void DoArchive(Archive& ar) + { + Surface::DoArchive(ar); + ar & profile & path & glob_z_direction & deletable & spline3_path & line_path & + x_dir & y_dir & z_dir & loc_z_dir & p0 & profile_tangent & profile_par & + profile_spline_coeff & latest_seg & latest_t & latest_point2d & latest_point3d; + } virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; @@ -109,10 +118,10 @@ namespace netgen class Extrusion : public Primitive { private: - const SplineGeometry<3> & path; - const SplineGeometry<2> & profile; // closed, clockwise oriented curve + const SplineGeometry<3>* path; + const SplineGeometry<2>* profile; // closed, clockwise oriented curve - const Vec<3> & z_direction; + Vec<3> z_direction; Array faces; @@ -122,7 +131,15 @@ namespace netgen Extrusion(const SplineGeometry<3> & path_in, const SplineGeometry<2> & profile_in, const Vec<3> & z_dir); + // default constructor for archive + Extrusion() {} ~Extrusion(); + + virtual void DoArchive(Archive& ar) + { + Primitive::DoArchive(ar); + ar & path & profile & z_direction & faces & latestfacenum; + } virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; diff --git a/libsrc/csg/python_csg.cpp b/libsrc/csg/python_csg.cpp index e9895738..b84bb3e1 100644 --- a/libsrc/csg/python_csg.cpp +++ b/libsrc/csg/python_csg.cpp @@ -374,12 +374,13 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails! auto ss = make_shared(); BinaryOutArchive archive(ss); archive & self; - return py::make_tuple(ss->str()); + archive.FlushBuffer(); + return py::make_tuple(py::bytes(ss->str())); }, [](py::tuple state) { auto geo = make_shared(); - auto ss = make_shared (py::cast(state[0])); + auto ss = make_shared (py::cast(state[0])); BinaryInArchive archive(ss); archive & (*geo); return geo; diff --git a/libsrc/csg/revolution.cpp b/libsrc/csg/revolution.cpp index 4c13c109..dac2e277 100644 --- a/libsrc/csg/revolution.cpp +++ b/libsrc/csg/revolution.cpp @@ -640,9 +640,9 @@ namespace netgen Revolution :: Revolution(const Point<3> & p0_in, const Point<3> & p1_in, const SplineGeometry<2> & spline_in) : - p0(p0_in), p1(p1_in), splinecurve(spline_in), - nsplines(spline_in.GetNSplines()) + p0(p0_in), p1(p1_in) { + auto nsplines = spline_in.GetNSplines(); surfaceactive.SetSize(0); surfaceids.SetSize(0); @@ -650,21 +650,21 @@ namespace netgen v_axis.Normalize(); - if(splinecurve.GetSpline(0).StartPI()(1) <= 0. && - splinecurve.GetSpline(nsplines-1).EndPI()(1) <= 0.) + if(spline_in.GetSpline(0).StartPI()(1) <= 0. && + spline_in.GetSpline(nsplines-1).EndPI()(1) <= 0.) type = 2; - else if (Dist(splinecurve.GetSpline(0).StartPI(), - splinecurve.GetSpline(nsplines-1).EndPI()) < 1e-7) + else if (Dist(spline_in.GetSpline(0).StartPI(), + spline_in.GetSpline(nsplines-1).EndPI()) < 1e-7) type = 1; else cerr << "Surface of revolution cannot be constructed" << endl; - for(int i=0; i regrevf; + RegisterClassForArchive regrev; } diff --git a/libsrc/csg/revolution.hpp b/libsrc/csg/revolution.hpp index c9b4cb92..879829fd 100644 --- a/libsrc/csg/revolution.hpp +++ b/libsrc/csg/revolution.hpp @@ -45,9 +45,18 @@ namespace netgen const int id_in = 0); RevolutionFace(const Array & raw_data); + // default constructor for archive + RevolutionFace() {} ~RevolutionFace(); + virtual void DoArchive(Archive& ar) + { + Surface::DoArchive(ar); + ar & isfirst & islast & spline & deletable & p0 & v_axis & id & spline_coefficient + & spline_coefficient_shifted & checklines_vec & checklines_start & checklines_normal; + } + virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; virtual double CalcFunctionValue (const Point<3> & point) const; @@ -96,8 +105,6 @@ namespace netgen private: Point<3> p0,p1; Vec<3> v_axis; - const SplineGeometry<2> & splinecurve; - const int nsplines; // 1 ... torus-like // 2 ... sphere-like @@ -112,9 +119,16 @@ namespace netgen Revolution(const Point<3> & p0_in, const Point<3> & p1_in, const SplineGeometry<2> & spline_in); + // default constructor for archive + Revolution() {} ~Revolution(); - + + virtual void DoArchive(Archive& ar) + { + Primitive::DoArchive(ar); + ar & p0 & p1 & v_axis & type & faces & intersecting_face; + } /* Check, whether box intersects solid defined by surface. diff --git a/libsrc/csg/solid.hpp b/libsrc/csg/solid.hpp index 928f8985..4d620c04 100644 --- a/libsrc/csg/solid.hpp +++ b/libsrc/csg/solid.hpp @@ -55,6 +55,8 @@ namespace netgen public: Solid (Primitive * aprim); Solid (optyp aop, Solid * as1, Solid * as2 = NULL); + // default constructor for archive + Solid () {} ~Solid (); void DoArchive(Archive& archive) diff --git a/libsrc/csg/surface.cpp b/libsrc/csg/surface.cpp index db315e99..f829840b 100644 --- a/libsrc/csg/surface.cpp +++ b/libsrc/csg/surface.cpp @@ -566,4 +566,8 @@ void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp) if (Abs2 (rs) < 1e-24 && i > 1) i = 1; } } + +RegisterClassForArchive regsurf; +RegisterClassForArchive regprim; +RegisterClassForArchive regosf; } diff --git a/libsrc/geom2d/geom2dmesh.cpp b/libsrc/geom2d/geom2dmesh.cpp index 3de7f97f..be1fc6c9 100644 --- a/libsrc/geom2d/geom2dmesh.cpp +++ b/libsrc/geom2d/geom2dmesh.cpp @@ -47,8 +47,8 @@ namespace netgen auto ext = dynamic_cast(spline); if(ext) { - ss3 = dynamic_cast *>(&ext->seg); - ls = dynamic_cast *>(&ext->seg); + ss3 = dynamic_cast *>(ext->seg); + ls = dynamic_cast *>(ext->seg); } else { diff --git a/libsrc/geom2d/geometry2d.hpp b/libsrc/geom2d/geometry2d.hpp index ad02f754..d9704577 100644 --- a/libsrc/geom2d/geometry2d.hpp +++ b/libsrc/geom2d/geometry2d.hpp @@ -21,7 +21,7 @@ namespace netgen class SplineSegExt : public SplineSeg<2> { public: - const SplineSeg<2> & seg; + SplineSeg<2>* seg; /// left domain int leftdom; @@ -42,35 +42,43 @@ namespace netgen /// int layer; - SplineSegExt (const SplineSeg<2> & hseg) - : seg(hseg) + SplineSegExt (SplineSeg<2> & hseg) + : seg(&hseg) { layer = 1; } + // default constructor for archive + SplineSegExt() {} ~SplineSegExt () { - delete &seg; + delete seg; + } + + virtual void DoArchive(Archive& ar) + { + ar & seg & leftdom & rightdom & reffak & hmax & bc & copyfrom + & hpref_left & hpref_right & layer; } virtual const GeomPoint<2> & StartPI () const { - return seg.StartPI(); + return seg->StartPI(); } virtual const GeomPoint<2> & EndPI () const { - return seg.EndPI(); + return seg->EndPI(); } virtual Point<2> GetPoint (double t) const { - return seg.GetPoint(t); + return seg->GetPoint(t); } virtual Vec<2> GetTangent (const double t) const { - return seg.GetTangent(t); + return seg->GetTangent(t); } virtual void GetDerivatives (const double t, @@ -78,27 +86,27 @@ namespace netgen Vec<2> & first, Vec<2> & second) const { - seg.GetDerivatives (t, point, first, second); + seg->GetDerivatives (t, point, first, second); } virtual void GetCoeff (Vector & coeffs) const { - seg.GetCoeff (coeffs); + seg->GetCoeff (coeffs); } virtual void GetPoints (int n, Array > & points) const { - seg.GetPoints (n, points); + seg->GetPoints (n, points); } virtual double MaxCurvature () const { - return seg.MaxCurvature(); + return seg->MaxCurvature(); } virtual string GetType () const { - return seg.GetType(); + return seg->GetType(); } virtual double CalcCurvature (double t) const @@ -112,7 +120,7 @@ namespace netgen virtual bool InConvexHull (Point<2> p, double eps) const { - return seg.InConvexHull (p, eps); + return seg->InConvexHull (p, eps); } }; diff --git a/libsrc/gprim/spline.cpp b/libsrc/gprim/spline.cpp index 5b4afc33..2d888f9e 100644 --- a/libsrc/gprim/spline.cpp +++ b/libsrc/gprim/spline.cpp @@ -551,11 +551,10 @@ namespace netgen template class SplineSeg3<2>; template class SplineSeg3<3>; - - - - - - - + RegisterClassForArchive> regss2; + RegisterClassForArchive> regss3; + RegisterClassForArchive, SplineSeg<2>> regls2; + RegisterClassForArchive, SplineSeg<3>> regls3; + RegisterClassForArchive, SplineSeg<2>> regsss2; + RegisterClassForArchive, SplineSeg<3>> regsss3; } diff --git a/libsrc/gprim/spline.hpp b/libsrc/gprim/spline.hpp index a628d07d..1454d685 100644 --- a/libsrc/gprim/spline.hpp +++ b/libsrc/gprim/spline.hpp @@ -35,6 +35,11 @@ namespace netgen /// GeomPoint (const Point & ap, double aref = 1, double ahpref=0) : Point(ap), refatpoint(aref), hmax(1e99), hpref(ahpref) { ; } + void DoArchive(Archive& ar) + { + Point::DoArchive(ar); + ar & refatpoint & hmax & hpref; + } }; @@ -72,6 +77,7 @@ namespace netgen second = 1.0/sqr(eps) * ( (pr-point)+(pl-point)); } + virtual void DoArchive(Archive& ar) = 0; /// returns initial point on curve virtual const GeomPoint & StartPI () const = 0; @@ -122,6 +128,12 @@ namespace netgen /// LineSeg (const GeomPoint & ap1, const GeomPoint & ap2); /// + // default constructor for archive + LineSeg() {} + virtual void DoArchive(Archive& ar) + { + ar & p1 & p2; + } virtual double Length () const; /// inline virtual Point GetPoint (double t) const; @@ -172,7 +184,13 @@ namespace netgen SplineSeg3 (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3); + // default constructor for archive + SplineSeg3() {} /// + virtual void DoArchive(Archive& ar) + { + ar & p1 & p2 & p3 & weight & proj_latest_t; + } inline virtual Point GetPoint (double t) const; /// virtual Vec GetTangent (const double t) const; @@ -226,6 +244,12 @@ namespace netgen CircleSeg (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3); + // default constructor for archive + CircleSeg() {} + virtual void DoArchive(Archive& ar) + { + ar & p1 & p2 & p3 & pm & radius & w1 & w3; + } /// virtual Point GetPoint (double t) const; /// @@ -270,6 +294,12 @@ namespace netgen public: /// DiscretePointsSeg (const Array > & apts); + // default constructor for archive + DiscretePointsSeg() {} + virtual void DoArchive(Archive& ar) + { + ar & pts & p1n & p2n; + } /// virtual ~DiscretePointsSeg (); /// @@ -624,8 +654,14 @@ namespace netgen /// BSplineSeg (const Array > & apts); /// + //default constructor for archive + BSplineSeg() {} virtual ~BSplineSeg(); /// + virtual void DoArchive(Archive& ar) + { + ar & pts & p1n & p2n & ti; + } virtual Point GetPoint (double t) const; /// virtual const GeomPoint & StartPI () const { return p1n; }; diff --git a/libsrc/gprim/splinegeometry.hpp b/libsrc/gprim/splinegeometry.hpp index 16574516..8e01cc62 100644 --- a/libsrc/gprim/splinegeometry.hpp +++ b/libsrc/gprim/splinegeometry.hpp @@ -55,6 +55,10 @@ namespace netgen // void SetGrading (const double grading); DLL_HEADER void AppendPoint (const Point & p, const double reffac = 1., const bool hpref = false); + void DoArchive(Archive& ar) + { + ar & geompoints & splines; + } void AppendSegment(SplineSeg * spline) { diff --git a/libsrc/linalg/vector.hpp b/libsrc/linalg/vector.hpp index dec8b57d..97ad05ed 100644 --- a/libsrc/linalg/vector.hpp +++ b/libsrc/linalg/vector.hpp @@ -139,6 +139,14 @@ public: ~Vector () { if (ownmem) delete [] data; } + virtual void DoArchive(Archive& ar) + { + auto size = s; + ar & ownmem & size; + if(!ar.Output()) + SetSize(size); + ar.Do(data, size); + } Vector & operator= (const FlatVector & v) { memcpy (data, &v(0), s*sizeof(double)); return *this; } diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index f6fb4bc8..f5d38eb2 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -68,6 +68,21 @@ public: class NotRegisteredForArchive : public SharedPtrAndPtrHolder {}; +class ClassWithConstPtr +{ +private: + const int* ptr; +public: + ClassWithConstPtr(const int* aptr) : ptr(aptr) { } + // constructor only for archive + ClassWithConstPtr() {} + void DoArchive(Archive& ar) + { + ar & ptr; + } + const int* getPtr() { return ptr; } +}; + class OneMoreDerivedClass : public SharedPtrAndPtrHolder {}; static RegisterClassForArchive regb; @@ -110,18 +125,36 @@ void testSharedPointer(Archive& in, Archive& out) void testPointer(Archive& in, Archive& out) { - SECTION("Same pointer") + PtrHolder holder, holder2; + holder.numbers.push_back(new int(3)); + holder2.numbers = holder.numbers; // same shared ptr + out & holder & holder2; + out.FlushBuffer(); + PtrHolder inholder, inholder2; + in & inholder & inholder2; + CHECK(inholder.numbers.size() == 1); + CHECK(inholder.numbers[0] == inholder2.numbers[0]); + CHECK(*inholder.numbers[0] == 3); +} + +void testConstPointer(Archive& in, Archive& out) +{ + SECTION("Const pointer") { - PtrHolder holder, holder2; - holder.numbers.push_back(new int(3)); - holder2.numbers = holder.numbers; // same shared ptr - out & holder & holder2; + int* iptr = new int(4); + double d = 0.1; + ClassWithConstPtr cls(iptr); + out & cls & iptr & d; out.FlushBuffer(); - PtrHolder inholder, inholder2; - in & inholder & inholder2; - CHECK(inholder.numbers.size() == 1); - CHECK(inholder.numbers[0] == inholder2.numbers[0]); - CHECK(*inholder.numbers[0] == 3); + ClassWithConstPtr incls; + int* iniptr; + double ind; + in & incls & iniptr & ind; + CHECK(*incls.getPtr() == 4); + CHECK(incls.getPtr() == iniptr); + CHECK(ind == 0.1); + delete iptr; + delete iniptr; } } @@ -205,7 +238,7 @@ void testMultipleInheritance(Archive& in, Archive& out) void testLibraryVersion(Archive& in, Archive& out) { - GetLibraryVersions()["netgen"] = "v6.2.1812"; + SetLibraryVersion("netgen","v6.2.1812"); CHECK(in.getVersion("netgen") == "v6.2.1811"); CHECK(out.getVersion("netgen") == "v6.2.1812"); } @@ -214,12 +247,25 @@ void testArchive(Archive& in, Archive& out) { SECTION("Empty String") { - out << string("") << 1; + char* cstr = nullptr; + char* empty = new char[1]; + char* simple = new char[7] {'s','i','m','p','l','e','\0'}; + empty[0] = '\0'; + out << string("") << cstr << empty << simple << string("simple") << long(1); out.FlushBuffer(); - string str; int i; - in & str & i; + string str; long i; char* readempty; char* readsimple; + string simplestr; + in & str & cstr & readempty & readsimple & simplestr & i; CHECK(str == ""); + CHECK(cstr == nullptr); + CHECK(strcmp(readempty,"") == 0); + CHECK(strcmp(readsimple,"simple") == 0); CHECK(i == 1); + CHECK(simplestr == "simple"); + delete[] readempty; + delete[] empty; + delete[] simple; + delete[] readsimple; } SECTION("SharedPtr") { @@ -229,6 +275,10 @@ void testArchive(Archive& in, Archive& out) { testPointer(in, out); } + SECTION("Const Pointer") + { + testConstPointer(in, out); + } SECTION("Multiple inheritance") { testMultipleInheritance(in, out); @@ -250,7 +300,7 @@ void testArchive(Archive& in, Archive& out) TEST_CASE("BinaryArchive") { - GetLibraryVersions()["netgen"] = "v6.2.1811"; + SetLibraryVersion("netgen","v6.2.1811"); auto stream = make_shared(); BinaryOutArchive out(stream); BinaryInArchive in(stream); @@ -259,7 +309,7 @@ TEST_CASE("BinaryArchive") TEST_CASE("TextArchive") { - GetLibraryVersions()["netgen"] = "v6.2.1811"; + SetLibraryVersion("netgen","v6.2.1811"); auto stream = make_shared(); TextOutArchive out(stream); TextInArchive in(stream); diff --git a/tests/pytest/test_pickling.py b/tests/pytest/test_pickling.py new file mode 100644 index 00000000..7bbf1fa6 --- /dev/null +++ b/tests/pytest/test_pickling.py @@ -0,0 +1,40 @@ + +import netgen.csg as csg +import pickle, numpy +from ngsolve import Draw, Mesh + +def test_pickle_csg(): + geo = csg.CSGeometry() + geo.Add(csg.Sphere(csg.Pnt(0,0,0), 2).bc("sphere")) + brick = csg.OrthoBrick(csg.Pnt(-3,-3,-3), csg.Pnt(3,3,3)) + geo.Add(csg.Cylinder(csg.Pnt(0,0,0), csg.Pnt(1,0,0), 0.5) * brick) + geo.Add(csg.Ellipsoid(csg.Pnt(0,0,0), csg.Vec(1,0,0), csg.Vec(0,1,0), csg.Vec(0,0,0.5))) + geo.Add(csg.Cone(csg.Pnt(0,0,0), csg.Pnt(3,0,0), 1, 0.5) * brick) + geo.Add(csg.EllipticCone(csg.Pnt(0,0,0), csg.Vec(2,0,0), csg.Vec(0,1,0), 3, 0.5) * brick) + geo.Add(csg.Torus(csg.Pnt(0,0,0), csg.Vec(0,1,0), 0.3, 0.05)) + pts2d = [[1,1], [1,-1], [-1,-1], [-1,1]] + segs = [[0,1], [1,2], [2,3], [3,0]] + curve = csg.SplineCurve2d() + pnrs = [curve.AddPoint(*p) for p in pts2d] + for s in segs: + curve.AddSegment(pnrs[s[0]], pnrs[s[1]]) + geo.Add(csg.Revolution(csg.Pnt(0,0,0), csg.Pnt(1,0,0), curve)) + path = csg.SplineCurve3d() + pnts = [(0,0,0), (2,0,0), (2,2,0)] + segs = [(0,1,2)] + for pnt in pnts: + path.AddPoint (*pnt) + + for seg in segs: + path.AddSegment (*seg) + geo.Add(csg.Extrusion(path, curve, csg.Vec(0,0,1))) + + geo_dump = pickle.dumps(geo) + geo2 = pickle.loads(geo_dump) + vd1 = geo._visualizationData() + vd2 = geo2._visualizationData() + for val1, val2 in zip(vd1.values(), vd2.values()): + assert numpy.array_equal(val1, val2) + +if __name__ == "__main__": + test_pickle_csg()