mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-24 21:10:33 +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 <map> // for map
|
||||
#include <memory> // for shared_ptr
|
||||
#include <optional> // for optional
|
||||
#include <string> // for string
|
||||
#include <type_traits> // for declval, enable_if_t, false_type, is_co...
|
||||
#include <cstddef> // for std::byte
|
||||
@ -290,6 +291,24 @@ namespace ngcore
|
||||
}
|
||||
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 =====================================================
|
||||
// this functions can be overloaded in Archive implementations for more efficiency
|
||||
template <typename T, typename = std::enable_if_t<is_archivable<T>>>
|
||||
|
@ -1620,7 +1620,7 @@ namespace netgen
|
||||
{
|
||||
public:
|
||||
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;
|
||||
};
|
||||
|
||||
@ -1659,22 +1659,14 @@ namespace netgen
|
||||
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")
|
||||
{
|
||||
CSGeometry * geometry = new CSGeometry ("");
|
||||
geometry -> LoadSurfaces(ist);
|
||||
return geometry;
|
||||
}
|
||||
// else
|
||||
// ist.putback (auxstring);
|
||||
}
|
||||
return NULL;
|
||||
if (token != "csgsurfaces")
|
||||
return nullptr;
|
||||
|
||||
CSGeometry * geometry = new CSGeometry ("");
|
||||
geometry -> LoadSurfaces(ist);
|
||||
return geometry;
|
||||
}
|
||||
|
||||
|
||||
|
@ -269,6 +269,11 @@ namespace netgen
|
||||
CalcInverse (*this, inv);
|
||||
sol = inv * rhs;
|
||||
}
|
||||
|
||||
void DoArchive(Archive & ar)
|
||||
{
|
||||
ar.Do(x, H*W);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -133,6 +133,11 @@ public:
|
||||
Mat<D> & GetMatrix() { return m; }
|
||||
Vec<D> & GetVector() { return v; }
|
||||
|
||||
void DoArchive(Archive& ar)
|
||||
{
|
||||
ar & m & v;
|
||||
}
|
||||
|
||||
///
|
||||
Transformation CalcInverse () const
|
||||
{
|
||||
|
@ -104,15 +104,8 @@ void Ng_LoadMeshFromStream ( istream & input )
|
||||
mesh -> Load(input);
|
||||
|
||||
SetGlobalMesh (mesh);
|
||||
for (int i = 0; i < geometryregister.Size(); i++)
|
||||
{
|
||||
NetgenGeometry * hgeom = geometryregister[i]->LoadFromMeshFile (input);
|
||||
if (hgeom)
|
||||
{
|
||||
ng_geometry.reset (hgeom);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ng_geometry = geometryregister.LoadFromMeshFile (input);
|
||||
|
||||
if (!ng_geometry)
|
||||
ng_geometry = make_shared<NetgenGeometry>();
|
||||
mesh->SetGeometry (ng_geometry);
|
||||
|
@ -507,9 +507,27 @@ namespace netgen
|
||||
|
||||
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++)
|
||||
{
|
||||
NetgenGeometry * hgeom = (*this)[i]->LoadFromMeshFile (ist);
|
||||
NetgenGeometry * hgeom = (*this)[i]->LoadFromMeshFile (ist, token);
|
||||
if (hgeom)
|
||||
return shared_ptr<NetgenGeometry>(hgeom);
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ namespace netgen
|
||||
public:
|
||||
virtual ~GeometryRegister();
|
||||
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
|
||||
{ return NULL; }
|
||||
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)
|
||||
{
|
||||
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())
|
||||
{
|
||||
std::stringstream ss;
|
||||
STEPControl_Writer writer;
|
||||
writer.Transfer(shape, STEPControl_AsIs);
|
||||
auto filename = GetTempFilename();
|
||||
writer.Write(filename.c_str());
|
||||
std::ifstream is(filename.c_str());
|
||||
ss << is.rdbuf();
|
||||
BRepTools::Write(shape, ss);
|
||||
ar << ss.str();
|
||||
std::remove(filename.c_str());
|
||||
}
|
||||
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;
|
||||
ar & str;
|
||||
stringstream ss(str);
|
||||
BRep_Builder builder;
|
||||
BRepTools::Read(shape, ss, builder);
|
||||
}
|
||||
|
||||
auto filename = GetTempFilename();
|
||||
auto tmpfile = std::fopen(filename.c_str(), "w");
|
||||
std::fputs(str.c_str(), tmpfile);
|
||||
std::fclose(tmpfile);
|
||||
LoadOCCInto(this, filename.c_str());
|
||||
std::remove(filename.c_str());
|
||||
// enumerate shapes and archive only integers
|
||||
auto my_hash = [](const TopoDS_Shape & key) {
|
||||
auto occ_hash = key.HashCode(1<<31UL);
|
||||
return std::hash<decltype(occ_hash)>()(occ_hash);
|
||||
};
|
||||
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;
|
||||
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 Save (string filename) const override;
|
||||
void SaveToMeshFile (ostream & /* ost */) const override;
|
||||
|
||||
void DoArchive(Archive& ar) override;
|
||||
|
||||
|
14
ng/ngpkg.cpp
14
ng/ngpkg.cpp
@ -233,16 +233,10 @@ namespace netgen
|
||||
MyMPI_SendCmd ("mesh");
|
||||
mesh -> Distribute();
|
||||
#endif
|
||||
for (int i = 0; i < geometryregister.Size(); i++)
|
||||
{
|
||||
NetgenGeometry * hgeom = geometryregister[i]->LoadFromMeshFile (*infile);
|
||||
if (hgeom)
|
||||
{
|
||||
ng_geometry = shared_ptr<NetgenGeometry>(hgeom);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete infile;
|
||||
auto geo = geometryregister.LoadFromMeshFile (*infile);
|
||||
if(geo)
|
||||
ng_geometry = geo;
|
||||
delete infile;
|
||||
|
||||
/*
|
||||
string auxstring;
|
||||
|
@ -265,6 +265,28 @@ void testEnum(Archive& in, Archive& out)
|
||||
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)
|
||||
{
|
||||
SECTION("Empty String")
|
||||
@ -322,6 +344,10 @@ void testArchive(Archive& in, Archive& out)
|
||||
{
|
||||
testEnum(in, out);
|
||||
}
|
||||
SECTION("optional")
|
||||
{
|
||||
testOptional(in, out);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("BinaryArchive")
|
||||
|
Loading…
Reference in New Issue
Block a user