Merge branch 'save_occ_to_mesh' into 'master'

Save OCCGeometry in mesh file using TextOutArchive

See merge request jschoeberl/netgen!450
This commit is contained in:
Joachim Schöberl 2021-11-12 13:15:50 +00:00
commit 9477fb0321
11 changed files with 185 additions and 50 deletions

View File

@ -9,6 +9,7 @@
#include <functional> // for function #include <functional> // for function
#include <map> // for map #include <map> // for map
#include <memory> // for shared_ptr #include <memory> // for shared_ptr
#include <optional> // for optional
#include <string> // for string #include <string> // for string
#include <type_traits> // for declval, enable_if_t, false_type, is_co... #include <type_traits> // for declval, enable_if_t, false_type, is_co...
#include <cstddef> // for std::byte #include <cstddef> // for std::byte
@ -290,6 +291,24 @@ namespace ngcore
} }
return (*this); return (*this);
} }
template<typename T>
Archive& operator& (std::optional<T>& opt)
{
bool has_value = opt.has_value();
(*this) & has_value;
if(has_value)
{
if(Output())
(*this) << *opt;
else
{
T value;
(*this) & value;
opt = value;
}
}
return (*this);
}
// Archive arrays ===================================================== // Archive arrays =====================================================
// this functions can be overloaded in Archive implementations for more efficiency // this functions can be overloaded in Archive implementations for more efficiency
template <typename T, typename = std::enable_if_t<is_archivable<T>>> template <typename T, typename = std::enable_if_t<is_archivable<T>>>

View File

@ -1620,7 +1620,7 @@ namespace netgen
{ {
public: public:
virtual NetgenGeometry * Load (string filename) const; virtual NetgenGeometry * Load (string filename) const;
virtual NetgenGeometry * LoadFromMeshFile (istream & ist) const; virtual NetgenGeometry * LoadFromMeshFile (istream & ist, string token) const;
// virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const; // virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;
}; };
@ -1659,23 +1659,15 @@ namespace netgen
return NULL; return NULL;
} }
NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist) const NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist, string token) const
{
string auxstring;
if (ist.good())
{
ist >> auxstring;
if (auxstring == "csgsurfaces")
{ {
if (token != "csgsurfaces")
return nullptr;
CSGeometry * geometry = new CSGeometry (""); CSGeometry * geometry = new CSGeometry ("");
geometry -> LoadSurfaces(ist); geometry -> LoadSurfaces(ist);
return geometry; return geometry;
} }
// else
// ist.putback (auxstring);
}
return NULL;
}
class CSGInit class CSGInit

View File

@ -269,6 +269,11 @@ namespace netgen
CalcInverse (*this, inv); CalcInverse (*this, inv);
sol = inv * rhs; sol = inv * rhs;
} }
void DoArchive(Archive & ar)
{
ar.Do(x, H*W);
}
}; };

View File

@ -133,6 +133,11 @@ public:
Mat<D> & GetMatrix() { return m; } Mat<D> & GetMatrix() { return m; }
Vec<D> & GetVector() { return v; } Vec<D> & GetVector() { return v; }
void DoArchive(Archive& ar)
{
ar & m & v;
}
/// ///
Transformation CalcInverse () const Transformation CalcInverse () const
{ {

View File

@ -104,15 +104,8 @@ void Ng_LoadMeshFromStream ( istream & input )
mesh -> Load(input); mesh -> Load(input);
SetGlobalMesh (mesh); SetGlobalMesh (mesh);
for (int i = 0; i < geometryregister.Size(); i++) ng_geometry = geometryregister.LoadFromMeshFile (input);
{
NetgenGeometry * hgeom = geometryregister[i]->LoadFromMeshFile (input);
if (hgeom)
{
ng_geometry.reset (hgeom);
break;
}
}
if (!ng_geometry) if (!ng_geometry)
ng_geometry = make_shared<NetgenGeometry>(); ng_geometry = make_shared<NetgenGeometry>();
mesh->SetGeometry (ng_geometry); mesh->SetGeometry (ng_geometry);

View File

@ -507,9 +507,27 @@ namespace netgen
shared_ptr<NetgenGeometry> GeometryRegisterArray :: LoadFromMeshFile (istream & ist) const shared_ptr<NetgenGeometry> GeometryRegisterArray :: LoadFromMeshFile (istream & ist) const
{ {
if (!ist.good())
return nullptr;
string token;
ist >> token;
if(token == "TextOutArchive")
{
NetgenGeometry *geo = nullptr;
size_t string_length;
ist >> string_length;
string buffer(string_length+1, '\0');
ist.read(&buffer[0], string_length);
auto ss = make_shared<stringstream>(buffer);
TextInArchive in(ss);
in & geo;
return shared_ptr<NetgenGeometry>(geo);
}
for (int i = 0; i < Size(); i++) for (int i = 0; i < Size(); i++)
{ {
NetgenGeometry * hgeom = (*this)[i]->LoadFromMeshFile (ist); NetgenGeometry * hgeom = (*this)[i]->LoadFromMeshFile (ist, token);
if (hgeom) if (hgeom)
return shared_ptr<NetgenGeometry>(hgeom); return shared_ptr<NetgenGeometry>(hgeom);
} }

View File

@ -224,7 +224,7 @@ namespace netgen
public: public:
virtual ~GeometryRegister(); virtual ~GeometryRegister();
virtual NetgenGeometry * Load (string filename) const = 0; virtual NetgenGeometry * Load (string filename) const = 0;
virtual NetgenGeometry * LoadFromMeshFile (istream & /* ist */) const { return NULL; } virtual NetgenGeometry * LoadFromMeshFile (istream & /* ist */, string) const { return NULL; }
virtual class VisualScene * GetVisualScene (const NetgenGeometry * /* geom */) const virtual class VisualScene * GetVisualScene (const NetgenGeometry * /* geom */) const
{ return NULL; } { return NULL; }
virtual void SetParameters (Tcl_Interp * /* interp */) { ; } virtual void SetParameters (Tcl_Interp * /* interp */) { ; }

View File

@ -1654,31 +1654,108 @@ namespace netgen
} }
} }
void OCCGeometry :: SaveToMeshFile (ostream & ost) const
{
auto ss = make_shared<stringstream>();
TextOutArchive out(ss);
NetgenGeometry *geo = const_cast<OCCGeometry*>(this);
out & geo;
ost << "TextOutArchive" << endl;
ost << ss->str().size() << endl;
ost << ss->str();
}
void OCCGeometry :: DoArchive(Archive& ar) void OCCGeometry :: DoArchive(Archive& ar)
{ {
constexpr int current_format_version = 0;
int format_version = current_format_version;
auto netgen_version = GetLibraryVersion("netgen");
ar & netgen_version & format_version;
if(ar.Output()) if(ar.Output())
{ {
std::stringstream ss; std::stringstream ss;
STEPControl_Writer writer; BRepTools::Write(shape, ss);
writer.Transfer(shape, STEPControl_AsIs);
auto filename = GetTempFilename();
writer.Write(filename.c_str());
std::ifstream is(filename.c_str());
ss << is.rdbuf();
ar << ss.str(); ar << ss.str();
std::remove(filename.c_str());
} }
else else
{ {
if(format_version>current_format_version)
throw Exception("Loading OCCGeometry from archive: unkown format version "
+ ToString(format_version)
+ ", written by netgen version "
+ ToString(netgen_version));
std::string str; std::string str;
ar & str; ar & str;
stringstream ss(str);
BRep_Builder builder;
BRepTools::Read(shape, ss, builder);
}
auto filename = GetTempFilename(); // enumerate shapes and archive only integers
auto tmpfile = std::fopen(filename.c_str(), "w"); auto my_hash = [](const TopoDS_Shape & key) {
std::fputs(str.c_str(), tmpfile); auto occ_hash = key.HashCode(1<<31UL);
std::fclose(tmpfile); return std::hash<decltype(occ_hash)>()(occ_hash);
LoadOCCInto(this, filename.c_str()); };
std::remove(filename.c_str()); std::unordered_map<TopoDS_Shape, int, decltype(my_hash)> shape_map(10, my_hash);
Array<TopoDS_Shape> shape_list;
std::map<Handle(TopoDS_TShape), int> tshape_map;
Array<Handle(TopoDS_TShape)> tshape_list;
ar & occdim;
for (auto typ : { TopAbs_SOLID, TopAbs_FACE, TopAbs_EDGE })
for (TopExp_Explorer e(shape, typ); e.More(); e.Next())
{
auto ds = e.Current();
auto ts = ds.TShape();
if(shape_map.count(ds)==0)
{
shape_map[ds] = shape_list.Size();
shape_list.Append(ds);
}
if(tshape_map.count(ts)==0)
{
tshape_map[ts] = shape_list.Size();
tshape_list.Append(ts);
}
}
for (auto ts : tshape_list)
{
bool has_properties = global_shape_properties.count(ts);
ar & has_properties;
if(has_properties)
ar & global_shape_properties[ts];
bool has_identifications = identifications.count(ts);
ar & has_identifications;
if(has_identifications)
{
auto & idents = identifications[ts];
auto n_idents = idents.size();
ar & n_idents;
idents.resize(n_idents);
for(auto i : Range(n_idents))
{
auto & id = idents[i];
int shape_id;
if(ar.Output())
shape_id = shape_map[id.other];
ar & shape_id & id.trafo & id.inverse & id.name;
if(ar.Input())
id.other = shape_list[shape_id];
}
}
}
if(ar.Input())
{
changed = 1;
BuildFMap();
CalcBoundingBox();
} }
} }

View File

@ -232,6 +232,11 @@ namespace netgen
if (prop2.col) col = prop2.col; if (prop2.col) col = prop2.col;
maxh = min2(maxh, prop2.maxh); maxh = min2(maxh, prop2.maxh);
} }
void DoArchive(Archive& ar)
{
ar & name & col & maxh & hpref;
}
}; };
@ -375,6 +380,7 @@ namespace netgen
void FinalizeMesh(Mesh& mesh) const override; void FinalizeMesh(Mesh& mesh) const override;
void Save (string filename) const override; void Save (string filename) const override;
void SaveToMeshFile (ostream & /* ost */) const override;
void DoArchive(Archive& ar) override; void DoArchive(Archive& ar) override;

View File

@ -233,15 +233,9 @@ namespace netgen
MyMPI_SendCmd ("mesh"); MyMPI_SendCmd ("mesh");
mesh -> Distribute(); mesh -> Distribute();
#endif #endif
for (int i = 0; i < geometryregister.Size(); i++) auto geo = geometryregister.LoadFromMeshFile (*infile);
{ if(geo)
NetgenGeometry * hgeom = geometryregister[i]->LoadFromMeshFile (*infile); ng_geometry = geo;
if (hgeom)
{
ng_geometry = shared_ptr<NetgenGeometry>(hgeom);
break;
}
}
delete infile; delete infile;
/* /*

View File

@ -265,6 +265,28 @@ void testEnum(Archive& in, Archive& out)
CHECK(enin == CASE2); CHECK(enin == CASE2);
} }
void testOptional(Archive& in, Archive& out)
{
{
std::optional<int> no_value;
std::optional<int> myint = 42;
std::optional<string> mystr = "have an optional string";
out & no_value & myint & mystr;
out.FlushBuffer();
}
{
std::optional<int> no_value_;
std::optional<int> myint_;
std::optional<string> mystr_;
in & no_value_ & myint_ & mystr_;
CHECK(no_value_.has_value() == false);
CHECK(myint_.has_value() == true);
CHECK(*myint_ == 42);
CHECK(mystr_.has_value() == true);
CHECK(*mystr_ == "have an optional string");
}
}
void testArchive(Archive& in, Archive& out) void testArchive(Archive& in, Archive& out)
{ {
SECTION("Empty String") SECTION("Empty String")
@ -322,6 +344,10 @@ void testArchive(Archive& in, Archive& out)
{ {
testEnum(in, out); testEnum(in, out);
} }
SECTION("optional")
{
testOptional(in, out);
}
} }
TEST_CASE("BinaryArchive") TEST_CASE("BinaryArchive")