mirror of
https://github.com/NGSolve/netgen.git
synced 2024-11-12 00:59:16 +05:00
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:
commit
9477fb0321
@ -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>>>
|
||||||
|
@ -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,22 +1659,14 @@ namespace netgen
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist) const
|
NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist, string token) const
|
||||||
{
|
{
|
||||||
string auxstring;
|
if (token != "csgsurfaces")
|
||||||
if (ist.good())
|
return nullptr;
|
||||||
{
|
|
||||||
ist >> auxstring;
|
CSGeometry * geometry = new CSGeometry ("");
|
||||||
if (auxstring == "csgsurfaces")
|
geometry -> LoadSurfaces(ist);
|
||||||
{
|
return geometry;
|
||||||
CSGeometry * geometry = new CSGeometry ("");
|
|
||||||
geometry -> LoadSurfaces(ist);
|
|
||||||
return geometry;
|
|
||||||
}
|
|
||||||
// else
|
|
||||||
// ist.putback (auxstring);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 */) { ; }
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
14
ng/ngpkg.cpp
14
ng/ngpkg.cpp
@ -233,16 +233,10 @@ 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)
|
delete infile;
|
||||||
{
|
|
||||||
ng_geometry = shared_ptr<NetgenGeometry>(hgeom);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete infile;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
string auxstring;
|
string auxstring;
|
||||||
|
@ -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")
|
||||||
|
Loading…
Reference in New Issue
Block a user