Geometry caching

This commit is contained in:
Thomas Krijnen
2021-10-08 15:38:46 +02:00
parent 4cee76ddc3
commit 8dca84dd07
20 changed files with 867 additions and 207 deletions
+23 -2
View File
@@ -209,6 +209,7 @@ int main(int argc, char** argv) {
path_t filter_filename;
path_t default_material_filename;
path_t log_file;
path_t cache_file;
std::string log_format;
po::options_description generic_options("Command line options");
@@ -218,6 +219,9 @@ int main(int argc, char** argv) {
("version", "display version information")
("verbose,v", po::value(&vcounter)->zero_tokens(), "more verbose log messages")
("quiet,q", "less status and progress output")
#ifdef WITH_HDF5
("cache", "cache geometry creation. Use --cache-file to specify cache file path.")
#endif
("stderr-progress", "output progress to stderr stream")
("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)")
("no-progress", "suppress possible progress bar type of prints that use carriage return")
@@ -230,8 +234,12 @@ int main(int argc, char** argv) {
("mmap", "use memory-mapped file for input")
#endif
("input-file", new po::typed_value<path_t, char_t>(0), "input IFC file")
("output-file", new po::typed_value<path_t, char_t>(0), "output geometry file");
("output-file", new po::typed_value<path_t, char_t>(0), "output geometry file")
#ifdef WITH_HDF5
("cache-file", new po::typed_value<path_t, char_t>(&cache_file), "geometry cache file")
#endif
;
po::options_description ifc_options("IFC options");
ifc_options.add_options()
("calculate-quantities", "Calculate or fix the physical quantity definitions "
@@ -680,6 +688,7 @@ int main(int argc, char** argv) {
STP = IfcUtil::path::from_utf8(".stp"),
IGS = IfcUtil::path::from_utf8(".igs"),
SVG = IfcUtil::path::from_utf8(".svg"),
CACHE = IfcUtil::path::from_utf8(".cache"),
HDF = IfcUtil::path::from_utf8(".h5"),
XML = IfcUtil::path::from_utf8(".xml"),
IFC = IfcUtil::path::from_utf8(".ifc");
@@ -969,6 +978,18 @@ int main(int argc, char** argv) {
}
IfcGeom::Iterator context_iterator(settings, ifc_file, filter_funcs, num_threads);
#ifdef WITH_HDF5
std::unique_ptr<HdfSerializer> cache;
if (vmap.count("cache-file") || vmap.count("cache")) {
if (!vmap.count("cache-file")) {
cache_file = input_filename + CACHE + HDF;
}
cache.reset(new HdfSerializer(IfcUtil::path::to_utf8(cache_file), settings));
context_iterator.set_cache(cache.get());
}
#endif
if (!context_iterator.initialize()) {
/// @todo It would be nice to know and print separate error prints for a case where we found no entities
/// and for a case we found no entities that satisfy our filtering criteria.
+7 -7
View File
@@ -288,9 +288,9 @@ private:
MAKE_TYPE_NAME(Cache) cache;
#endif
std::map<int, SurfaceStyle> style_cache;
std::map<int, std::shared_ptr<const SurfaceStyle>> style_cache;
const SurfaceStyle* internalize_surface_style(const std::pair<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*>& shading_style);
std::shared_ptr<const SurfaceStyle> internalize_surface_style(const std::pair<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*>& shading_style);
public:
MAKE_TYPE_NAME(Kernel)()
@@ -364,9 +364,9 @@ public:
bool convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes);
void assert_closed_wire(TopoDS_Wire& wire);
bool convert_layerset(const IfcSchema::IfcProduct*, std::vector<Handle_Geom_Surface>&, std::vector<const SurfaceStyle*>&, std::vector<double>&);
bool apply_layerset(const IfcRepresentationShapeItems&, const std::vector<Handle_Geom_Surface>&, const std::vector<const SurfaceStyle*>&, IfcRepresentationShapeItems&);
bool apply_folded_layerset(const IfcRepresentationShapeItems&, const std::vector< std::vector<Handle_Geom_Surface> >&, const std::vector<const SurfaceStyle*>&, IfcRepresentationShapeItems&);
bool convert_layerset(const IfcSchema::IfcProduct*, std::vector<Handle_Geom_Surface>&, std::vector<std::shared_ptr<const SurfaceStyle>>&, std::vector<double>&);
bool apply_layerset(const IfcRepresentationShapeItems&, const std::vector<Handle_Geom_Surface>&, const std::vector<std::shared_ptr<const SurfaceStyle>>&, IfcRepresentationShapeItems&);
bool apply_folded_layerset(const IfcRepresentationShapeItems&, const std::vector< std::vector<Handle_Geom_Surface> >&, const std::vector<std::shared_ptr<const SurfaceStyle>>&, IfcRepresentationShapeItems&);
bool fold_layers(const IfcSchema::IfcWall*, const IfcRepresentationShapeItems&, const std::vector<Handle_Geom_Surface>&, const std::vector<double>&, std::vector< std::vector<Handle_Geom_Surface> >&);
bool split_solid_by_surface(const TopoDS_Shape&, const Handle_Geom_Surface&, TopoDS_Shape&, TopoDS_Shape&);
@@ -443,8 +443,8 @@ public:
const IfcSchema::IfcMaterial* get_single_material_association(const IfcSchema::IfcProduct*);
IfcSchema::IfcRepresentation* representation_mapped_to(const IfcSchema::IfcRepresentation* representation);
IfcSchema::IfcProduct::list::ptr products_represented_by(const IfcSchema::IfcRepresentation*);
const SurfaceStyle* get_style(const IfcSchema::IfcRepresentationItem*);
const SurfaceStyle* get_style(const IfcSchema::IfcMaterial*);
std::shared_ptr<const SurfaceStyle> get_style(const IfcSchema::IfcRepresentationItem*);
std::shared_ptr<const SurfaceStyle> get_style(const IfcSchema::IfcMaterial*);
template <typename T> std::pair<IfcSchema::IfcSurfaceStyle*, T*> _get_surface_style(const IfcSchema::IfcStyledItem* si) {
std::vector<IfcSchema::IfcPresentationStyle*> prs_styles;
+15 -15
View File
@@ -907,7 +907,7 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons
}
}
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), it3->Placement(), entity_shape, &it3->Style()));
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), it3->Placement(), entity_shape, it3->StylePtr()));
}
return true;
@@ -1123,7 +1123,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
continue;
}
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), result, &it3->Style()));
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), result, it3->StylePtr()));
// For manifold first operands we're not even going to try if processing
// as loose faces gives a better result.
@@ -1848,7 +1848,7 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and_produc
std::vector<double> thickness;
std::vector<Handle_Geom_Surface> layers;
std::vector< std::vector<Handle_Geom_Surface> > folded_layers;
std::vector<const SurfaceStyle*> styles;
std::vector<std::shared_ptr<const SurfaceStyle>> styles;
if (convert_layerset(product, layers, styles, thickness)) {
IfcSchema::IfcRelAssociates::list::ptr associations = product->HasAssociations();
@@ -1889,7 +1889,7 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and_produc
const IfcSchema::IfcMaterial* single_material = get_single_material_association(product);
if (single_material) {
const IfcGeom::SurfaceStyle* s = get_style(single_material);
auto s = get_style(single_material);
for (IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++it) {
if (!it->hasStyle() && s) {
it->setStyle(s);
@@ -1917,8 +1917,8 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and_produc
for (auto& s : shapes) {
if (s.hasStyle()) {
for (auto& p : style_cache) {
if (&p.second == &s.Style()) {
p.second.Transparency() = settings.force_space_transparency();
if (p.second == s.StylePtr()) {
std::const_pointer_cast<IfcGeom::SurfaceStyle>(p.second)->Transparency() = settings.force_space_transparency();
}
}
}
@@ -2303,7 +2303,7 @@ std::pair<std::string, double> IfcGeom::Kernel::initializeUnits(IfcSchema::IfcUn
return std::pair<std::string, double>(unit_name, unit_magnitude);
}
bool IfcGeom::Kernel::convert_layerset(const IfcSchema::IfcProduct* product, std::vector<Handle_Geom_Surface>& surfaces, std::vector<const SurfaceStyle*>& styles, std::vector<double>& thicknesses) {
bool IfcGeom::Kernel::convert_layerset(const IfcSchema::IfcProduct* product, std::vector<Handle_Geom_Surface>& surfaces, std::vector<std::shared_ptr<const SurfaceStyle>>& styles, std::vector<double>& thicknesses) {
IfcSchema::IfcMaterialLayerSetUsage* usage = 0;
Handle_Geom_Surface reference_surface;
@@ -3063,7 +3063,7 @@ namespace {
#endif
}
bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& items, const std::vector< std::vector<Handle_Geom_Surface> >& surfaces, const std::vector<const SurfaceStyle*>& styles, IfcRepresentationShapeItems& result) {
bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& items, const std::vector< std::vector<Handle_Geom_Surface> >& surfaces, const std::vector<std::shared_ptr<const SurfaceStyle>>& styles, IfcRepresentationShapeItems& result) {
Bnd_Box bb;
TopoDS_Shape input;
flatten_shape_list(items, input, false);
@@ -3148,8 +3148,8 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
TopoDS_Shape a,b;
if (split_solid_by_shell(it->Shape(), shells.First(), a, b)) {
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), b, styles[0] ? styles[0] : &it->Style()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, styles[1] ? styles[1] : &it->Style()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), b, !!styles[0] ? styles[0] : it->StylePtr()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, !!styles[1] ? styles[1] : it->StylePtr()));
} else {
continue;
}
@@ -3168,7 +3168,7 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i
std::vector<TopoDS_Shape> slices;
if (split(*this, it->Shape(), shells, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) {
for (size_t i = 0; i < slices.size(); ++i) {
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), slices[i], styles[i] ? styles[i] : &it->Style()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), slices[i], !!styles[i] ? styles[i] : it->StylePtr()));
}
} else {
return false;
@@ -3181,7 +3181,7 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i
}
bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, const std::vector<Handle_Geom_Surface>& surfaces, const std::vector<const SurfaceStyle*>& styles, IfcRepresentationShapeItems& result) {
bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, const std::vector<Handle_Geom_Surface>& surfaces, const std::vector<std::shared_ptr<const SurfaceStyle>>& styles, IfcRepresentationShapeItems& result) {
if (surfaces.size() < 3) {
return false;
@@ -3191,8 +3191,8 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
TopoDS_Shape a,b;
if (split_solid_by_surface(it->Shape(), surfaces[1], a, b)) {
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), b, styles[0] ? styles[0] : &it->Style()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, styles[1] ? styles[1] : &it->Style()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), b, !!styles[0] ? styles[0] : it->StylePtr()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, !!styles[1] ? styles[1] : it->StylePtr()));
} else {
continue;
}
@@ -3259,7 +3259,7 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c
std::vector<TopoDS_Shape> slices;
if (split(*this, it->Shape(), operands, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) {
for (size_t i = 0; i < slices.size(); ++i) {
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), slices[i], styles[i] ? styles[i] : &it->Style()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), slices[i], !!styles[i] ? styles[i] : it->StylePtr()));
}
} else {
return false;
+59 -11
View File
@@ -777,11 +777,25 @@ namespace IfcGeom {
Logger::SetProduct(product);
bool read_from_cache = false;
BRepElement* element;
if (ifcproduct_iterator == ifcproducts->begin() || !geometry_reuse_ok_for_current_representation_) {
element = kernel.create_brep_for_representation_and_product(settings, representation, product);
} else {
element = kernel.create_brep_for_processed_representation(settings, representation, product, current_shape_model);
#ifdef WITH_HDF5
if (cache_) {
auto from_cache = cache_->read(*ifc_file, product->GlobalId(), representation->data().id());
if (from_cache) {
read_from_cache = true;
element = (BRepElement*) from_cache;
}
}
#endif
if (!read_from_cache) {
if (ifcproduct_iterator == ifcproducts->begin() || !geometry_reuse_ok_for_current_representation_) {
element = kernel.create_brep_for_representation_and_product(settings, representation, product);
} else {
element = kernel.create_brep_for_processed_representation(settings, representation, product, current_shape_model);
}
}
Logger::SetProduct(boost::none);
@@ -791,6 +805,12 @@ namespace IfcGeom {
continue;
}
#ifdef WITH_HDF5
if (cache_ && !read_from_cache) {
cache_->write(element);
}
#endif
return element;
}
}
@@ -1003,14 +1023,42 @@ namespace IfcGeom {
Logger::Message(Logger::LOG_ERROR, "Getting a serialized element from model failed.");
}
} else if (!settings.get(IteratorSettings::DISABLE_TRIANGULATION)) {
try {
if (ifcproduct_iterator == ifcproducts->begin() || !geometry_reuse_ok_for_current_representation_) {
next_triangulation = new TriangulationElement(*next_shape_model);
} else {
next_triangulation = new TriangulationElement(*next_shape_model, current_triangulation->geometry_pointer());
bool read_from_cache = false;
#ifdef WITH_HDF5
if (cache_) {
// the part before the hyphen is the representation id
auto gid2 = next_shape_model->geometry().id();
auto hyphen = gid2.find("-");
if (hyphen != std::string::npos) {
gid2 = gid2.substr(0, hyphen);
}
auto from_cache = cache_->read(*ifc_file, next_shape_model->guid(), boost::lexical_cast<int>(gid2), HdfSerializer::READ_TRIANGULATION);
if (from_cache) {
read_from_cache = true;
next_triangulation = (TriangulationElement*)from_cache;
}
}
#endif
if (!read_from_cache) {
try {
if (ifcproduct_iterator == ifcproducts->begin() || !geometry_reuse_ok_for_current_representation_) {
next_triangulation = new TriangulationElement(*next_shape_model);
} else {
next_triangulation = new TriangulationElement(*next_shape_model, current_triangulation->geometry_pointer());
}
#ifdef WITH_HDF5
if (cache_) {
cache_->write(next_triangulation);
}
#endif
} catch (...) {
Logger::Message(Logger::LOG_ERROR, "Getting a triangulation element from model failed.");
}
} catch (...) {
Logger::Message(Logger::LOG_ERROR, "Getting a triangulation element from model failed.");
}
}
}
+18 -12
View File
@@ -56,25 +56,31 @@ namespace {
#define Kernel MAKE_TYPE_NAME(Kernel)
const IfcGeom::SurfaceStyle* IfcGeom::Kernel::internalize_surface_style(const std::pair<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*>& shading_styles) {
std::shared_ptr<const IfcGeom::SurfaceStyle> IfcGeom::Kernel::internalize_surface_style(const std::pair<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*>& shading_styles) {
if (shading_styles.second == 0) {
return 0;
}
int surface_style_id = shading_styles.first->data().id();
std::map<int,SurfaceStyle>::const_iterator it = style_cache.find(surface_style_id);
auto it = style_cache.find(surface_style_id);
if (it != style_cache.end()) {
return &(it->second);
return it->second;
}
SurfaceStyle surface_style;
IfcSchema::IfcSurfaceStyle* style = shading_styles.first->as<IfcSchema::IfcSurfaceStyle>();
IfcSchema::IfcSurfaceStyleShading* shading = shading_styles.second->as<IfcSchema::IfcSurfaceStyleShading>();
std::shared_ptr<SurfaceStyle> surface_style_ptr;
if (style->Name()) {
surface_style = SurfaceStyle(surface_style_id, *style->Name());
surface_style_ptr.reset(new SurfaceStyle(surface_style_id, *style->Name()));
} else {
surface_style = SurfaceStyle(surface_style_id);
surface_style_ptr.reset(new SurfaceStyle(surface_style_id));
}
std::shared_ptr<const SurfaceStyle> surface_style_ptr_const = std::const_pointer_cast<const SurfaceStyle>(surface_style_ptr);
SurfaceStyle& surface_style = *surface_style_ptr;
double rgb[3];
if (process_colour(shading->SurfaceColour(), rgb)) {
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
@@ -113,14 +119,14 @@ const IfcGeom::SurfaceStyle* IfcGeom::Kernel::internalize_surface_style(const st
surface_style.Transparency().reset(d);
}
}
return &(style_cache[surface_style_id] = surface_style);
return style_cache[surface_style_id] = surface_style_ptr_const;
}
const IfcGeom::SurfaceStyle* IfcGeom::Kernel::get_style(const IfcSchema::IfcRepresentationItem* item) {
std::shared_ptr<const IfcGeom::SurfaceStyle> IfcGeom::Kernel::get_style(const IfcSchema::IfcRepresentationItem* item) {
return internalize_surface_style(get_surface_style<IfcSchema::IfcSurfaceStyleShading>(item));
}
const IfcGeom::SurfaceStyle* IfcGeom::Kernel::get_style(const IfcSchema::IfcMaterial* material) {
std::shared_ptr<const IfcGeom::SurfaceStyle> IfcGeom::Kernel::get_style(const IfcSchema::IfcMaterial* material) {
IfcSchema::IfcMaterialDefinitionRepresentation::list::ptr defs = material->HasRepresentation();
for (IfcSchema::IfcMaterialDefinitionRepresentation::list::it jt = defs->begin(); jt != defs->end(); ++jt) {
IfcSchema::IfcRepresentation::list::ptr reps = (*jt)->Representations();
@@ -135,6 +141,6 @@ const IfcGeom::SurfaceStyle* IfcGeom::Kernel::get_style(const IfcSchema::IfcMate
}
}
}
IfcGeom::SurfaceStyle material_style = IfcGeom::SurfaceStyle(material->data().id(), material->Name());
return &(style_cache[material->data().id()] = material_style);
auto material_style = std::make_shared<IfcGeom::SurfaceStyle>(material->data().id(), material->Name());
return style_cache[material->data().id()] = material_style;
}
+32 -1
View File
@@ -121,6 +121,11 @@ namespace IfcGeom {
size_t weld_offset_;
VertexKeyMap welds;
// when read from serialization, the element needs to take ownership of the styles,
// the material vector is constructor off of this.
// @todo this can be improved
std::vector<std::shared_ptr<SurfaceStyle>> styles_;
public:
const std::string& id() const { return id_; }
const std::vector<double>& verts() const { return _verts; }
@@ -144,7 +149,7 @@ namespace IfcGeom {
int surface_style_id = -1;
if (iit->hasStyle()) {
Material adapter(&iit->Style());
Material adapter(iit->StylePtr());
std::vector<Material>::const_iterator jt = std::find(_materials.begin(), _materials.end(), adapter);
if (jt == _materials.end()) {
surface_style_id = (int)_materials.size();
@@ -349,6 +354,32 @@ namespace IfcGeom {
BRepTools::Clean(s);
}
}
Triangulation(
ElementSettings settings,
const std::string& id,
const std::vector<double>& verts,
const std::vector<int>& faces,
const std::vector<int>& edges,
const std::vector<double>& normals,
const std::vector<double>& uvs,
const std::vector<int>& material_ids,
const std::vector<std::shared_ptr<SurfaceStyle>>& styles)
: Representation(settings)
, id_(id)
, _verts(verts)
, _faces(faces)
, _edges(edges)
, _normals(normals)
, uvs_(uvs)
, _material_ids(material_ids)
, styles_(styles)
{
for (auto& s : styles_) {
_materials.push_back(IfcGeom::Material(s));
}
}
virtual ~Triangulation() {}
/// Generates UVs for a single mesh using box projection.
+9 -9
View File
@@ -434,9 +434,9 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_S
bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, IfcRepresentationShapeItems& shape) {
TopoDS_Shape s;
const SurfaceStyle* collective_style = get_style(l);
auto collective_style = get_style(l);
if (convert_shape(l->Outer(),s) ) {
const SurfaceStyle* indiv_style = get_style(l->Outer());
auto indiv_style = get_style(l->Outer());
IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list);
if (l->declaration().is(IfcSchema::IfcFacetedBrepWithVoids::Class())) {
@@ -466,10 +466,10 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, IfcRepre
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
bool part_success = false;
IfcSchema::IfcConnectedFaceSet::list::ptr facesets = l->FbsmFaces();
const SurfaceStyle* collective_style = get_style(l);
auto collective_style = get_style(l);
for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) {
TopoDS_Shape s;
const SurfaceStyle* shell_style = get_style(*it);
auto shell_style = get_style(*it);
if (convert_shape(*it,s)) {
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, shell_style ? shell_style : collective_style));
part_success |= true;
@@ -527,10 +527,10 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l,
bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
aggregate_of_instance::ptr shells = l->SbsmBoundary();
const SurfaceStyle* collective_style = get_style(l);
auto collective_style = get_style(l);
for( aggregate_of_instance::it it = shells->begin(); it != shells->end(); ++ it ) {
TopoDS_Shape s;
const SurfaceStyle* shell_style = 0;
decltype(collective_style) shell_style;
if ((*it)->declaration().is(IfcSchema::IfcRepresentationItem::Class())) {
shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it);
}
@@ -845,7 +845,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentati
}
gtrsf.Multiply(trsf);
const IfcGeom::SurfaceStyle* mapped_item_style = get_style(l);
auto mapped_item_style = get_style(l);
const size_t previous_size = shapes.size();
bool b = convert_shapes(map->MappedRepresentation(), shapes);
@@ -893,7 +893,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresenta
aggregate_of_instance::ptr elements = l->Elements();
if ( !elements->size() ) return false;
bool part_succes = false;
const IfcGeom::SurfaceStyle* parent_style = get_style(l);
auto parent_style = get_style(l);
for (aggregate_of_instance::it it = elements->begin(); it != elements->end(); ++it) {
auto element = *it;
TopoDS_Shape s;
@@ -917,7 +917,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresenta
}
part_succes = true;
const IfcGeom::SurfaceStyle* style = 0;
decltype(parent_style) style = 0;
if (element->declaration().is(IfcSchema::IfcPoint::Class())) {
style = get_style((IfcSchema::IfcPoint*) element);
}
+1 -1
View File
@@ -338,7 +338,7 @@ namespace IfcGeom {
for (; it.More(); it.Next(), ++git) {
std::unique_ptr<IfcGeom::Material> adaptor;
if (git->hasStyle()) {
adaptor.reset(new Material(&git->Style()));
adaptor.reset(new Material(git->StylePtr()));
} else {
adaptor.reset(new Material(IfcGeom::get_default_style(elem->type())));
}
+1 -1
View File
@@ -30,7 +30,7 @@ bool IfcGeom::Kernel::convert_shapes(const IfcBaseInterface* l, IfcRepresentatio
if (shape_type(l) != ST_SHAPELIST) {
TopoDS_Shape shp;
if (convert_shape(l, shp)) {
const IfcGeom::SurfaceStyle* style = nullptr;
std::shared_ptr<const IfcGeom::SurfaceStyle> style;
if (l->as<IfcSchema::IfcRepresentationItem>()) {
style = get_style(l->as<IfcSchema::IfcRepresentationItem>());
}
+6 -5
View File
@@ -31,13 +31,13 @@ namespace IfcGeom {
int id;
gp_GTrsf placement;
TopoDS_Shape shape;
const SurfaceStyle* style;
std::shared_ptr<const SurfaceStyle> style;
public:
IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape, const SurfaceStyle* style)
IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape, std::shared_ptr<const SurfaceStyle> style)
: id(id), placement(placement), shape(shape), style(style) {}
IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape)
: id(id), placement(placement), shape(shape), style(0) {}
IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape, const SurfaceStyle* style)
IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape, std::shared_ptr<const SurfaceStyle> style)
: id(id), shape(shape), style(style) {}
IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape)
: id(id), shape(shape), style(0) {}
@@ -45,9 +45,10 @@ namespace IfcGeom {
void prepend(const gp_GTrsf& trsf) { placement.PreMultiply(trsf); }
const TopoDS_Shape& Shape() const { return shape; }
const gp_GTrsf& Placement() const { return placement; }
bool hasStyle() const { return style != 0; }
bool hasStyle() const { return !!style; }
const SurfaceStyle& Style() const { return *style; }
void setStyle(const SurfaceStyle* newStyle) { style = newStyle; }
const std::shared_ptr<const SurfaceStyle> StylePtr() const { return style; }
void setStyle(std::shared_ptr<const SurfaceStyle> newStyle) { style = newStyle; }
int ItemId() const { return id; }
};
typedef std::vector<IfcRepresentationShapeItem> IfcRepresentationShapeItems;
@@ -137,6 +137,8 @@ namespace IfcGeom {
const Element* get_object(int id) { return implementation_->get_object(id); }
IfcUtil::IfcBaseClass* create() { return implementation_->create(); }
void set_cache(HdfSerializer* cache) { return implementation_->set_cache(cache); }
};
}
@@ -20,16 +20,23 @@
#include "IfcGeomMaterial.h"
static double black[3] = {0.,0.,0.};
static const std::string no_name = "";
IfcGeom::Material::Material(const IfcGeom::SurfaceStyle* style) : style(style) {}
bool IfcGeom::Material::hasDiffuse() const { return style->Diffuse() ? true : false; }
bool IfcGeom::Material::hasSpecular() const { return style->Specular() ? true : false; }
bool IfcGeom::Material::hasTransparency() const { return style->Transparency() ? true : false; }
bool IfcGeom::Material::hasSpecularity() const { return style->Specularity() ? true : false; }
IfcGeom::Material::Material() {}
IfcGeom::Material::Material(const std::shared_ptr<const IfcGeom::SurfaceStyle>& style) : style(style) {}
bool IfcGeom::Material::hasDiffuse() const { return style && style->Diffuse() ? true : false; }
bool IfcGeom::Material::hasSpecular() const { return style && style->Specular() ? true : false; }
bool IfcGeom::Material::hasTransparency() const { return style && style->Transparency() ? true : false; }
bool IfcGeom::Material::hasSpecularity() const { return style && style->Specularity() ? true : false; }
const double* IfcGeom::Material::diffuse() const { if (hasDiffuse()) return &((*style->Diffuse()).R()); else return black; }
const double* IfcGeom::Material::specular() const { if (hasSpecular()) return &((*style->Specular()).R()); else return black; }
double IfcGeom::Material::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; }
double IfcGeom::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); else return 0; }
const std::string &IfcGeom::Material::name() const { return style->Name(); }
const std::string &IfcGeom::Material::original_name() const { return style->original_name(); }
const std::string &IfcGeom::Material::name() const { return style ? style->Name() : no_name; }
const std::string &IfcGeom::Material::original_name() const { return style ? style->original_name() : no_name; }
bool IfcGeom::Material::operator==(const IfcGeom::Material& other) const { return style == other.style; }
const IfcGeom::SurfaceStyle& IfcGeom::Material::get_style() const {
return *style;
}
@@ -28,11 +28,11 @@ namespace IfcGeom {
class IFC_GEOM_API Material {
private:
const IfcGeom::SurfaceStyle* style;
std::shared_ptr<const IfcGeom::SurfaceStyle> style;
public:
explicit Material(const IfcGeom::SurfaceStyle* style = 0); // TODO default constructor for vector?
// Material(const Material& other);
// Material& operator=(const Material& other);
Material();
explicit Material(const std::shared_ptr<const IfcGeom::SurfaceStyle>&);
bool hasDiffuse() const;
bool hasSpecular() const;
bool hasTransparency() const;
@@ -44,6 +44,8 @@ namespace IfcGeom {
const std::string &name() const;
const std::string &original_name() const;
bool operator==(const Material& other) const;
const IfcGeom::SurfaceStyle& get_style() const;
};
}
@@ -99,7 +99,7 @@ namespace IfcGeom {
boost::optional<int>& Id() { return id; }
};
IFC_GEOM_API const SurfaceStyle* get_default_style(const std::string& ifc_type);
IFC_GEOM_API std::shared_ptr<const IfcGeom::SurfaceStyle> get_default_style(const std::string& ifc_type);
IFC_GEOM_API SurfaceStyle& update_default_style(const std::string& ifc_type);
@@ -4,6 +4,7 @@
#include "../ifcgeom_schema_agnostic/IfcGeomFilter.h"
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../serializers/HdfSerializer.h"
#include <gp_XYZ.hxx>
@@ -34,7 +35,11 @@ IteratorFactoryImplementation& iterator_implementations();
namespace IfcGeom {
class IteratorImplementation {
protected:
HdfSerializer* cache_ = nullptr;
public:
void set_cache(HdfSerializer* cache) { cache_ = cache; }
virtual bool initialize() = 0;
virtual void compute_bounds(bool with_geometry) = 0;
virtual const gp_XYZ& bounds_min() const = 0;
+41 -50
View File
@@ -8,48 +8,48 @@
namespace pt = boost::property_tree;
static std::map<std::string, IfcGeom::SurfaceStyle> default_materials;
static IfcGeom::SurfaceStyle default_material;
static std::map<std::string, std::shared_ptr<IfcGeom::SurfaceStyle>> default_materials;
static std::shared_ptr<IfcGeom::SurfaceStyle> default_material;
static bool default_materials_initialized = false;
void InitDefaultMaterials() {
default_materials.insert(std::make_pair("IfcSite", IfcGeom::SurfaceStyle("IfcSite")));
default_materials["IfcSite"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.65));
default_materials.insert(std::make_pair("IfcSite", std::make_shared<IfcGeom::SurfaceStyle>("IfcSite")));
default_materials["IfcSite"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.65));
default_materials.insert(std::make_pair("IfcSlab", IfcGeom::SurfaceStyle("IfcSlab")));
default_materials["IfcSlab"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.4, 0.4, 0.4));
default_materials.insert(std::make_pair("IfcSlab", std::make_shared<IfcGeom::SurfaceStyle>("IfcSlab")));
default_materials["IfcSlab"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.4, 0.4, 0.4));
default_materials.insert(std::make_pair("IfcWallStandardCase", IfcGeom::SurfaceStyle("IfcWallStandardCase")));
default_materials["IfcWallStandardCase"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9, 0.9, 0.9));
default_materials.insert(std::make_pair("IfcWallStandardCase", std::make_shared<IfcGeom::SurfaceStyle>("IfcWallStandardCase")));
default_materials["IfcWallStandardCase"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9, 0.9, 0.9));
default_materials.insert(std::make_pair("IfcWall", IfcGeom::SurfaceStyle("IfcWall")));
default_materials["IfcWall"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9, 0.9, 0.9));
default_materials.insert(std::make_pair("IfcWall", std::make_shared<IfcGeom::SurfaceStyle>("IfcWall")));
default_materials["IfcWall"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9, 0.9, 0.9));
default_materials.insert(std::make_pair("IfcWindow", IfcGeom::SurfaceStyle("IfcWindow")));
default_materials["IfcWindow"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.75));
default_materials["IfcWindow"].Transparency().reset(0.3);
default_materials.insert(std::make_pair("IfcWindow", std::make_shared<IfcGeom::SurfaceStyle>("IfcWindow")));
default_materials["IfcWindow"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.75));
default_materials["IfcWindow"]->Transparency().reset(0.3);
default_materials.insert(std::make_pair("IfcDoor", IfcGeom::SurfaceStyle("IfcDoor")));
default_materials["IfcDoor"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.55, 0.3, 0.15));
default_materials.insert(std::make_pair("IfcDoor", std::make_shared<IfcGeom::SurfaceStyle>("IfcDoor")));
default_materials["IfcDoor"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.55, 0.3, 0.15));
default_materials.insert(std::make_pair("IfcBeam", IfcGeom::SurfaceStyle("IfcBeam")));
default_materials["IfcBeam"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.7, 0.7));
default_materials.insert(std::make_pair("IfcBeam", std::make_shared<IfcGeom::SurfaceStyle>("IfcBeam")));
default_materials["IfcBeam"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.7, 0.7));
default_materials.insert(std::make_pair("IfcRailing", IfcGeom::SurfaceStyle("IfcRailing")));
default_materials["IfcRailing"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6));
default_materials.insert(std::make_pair("IfcRailing", std::make_shared<IfcGeom::SurfaceStyle>("IfcRailing")));
default_materials["IfcRailing"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6));
default_materials.insert(std::make_pair("IfcMember", IfcGeom::SurfaceStyle("IfcMember")));
default_materials["IfcMember"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6));
default_materials.insert(std::make_pair("IfcMember", std::make_shared<IfcGeom::SurfaceStyle>("IfcMember")));
default_materials["IfcMember"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6));
default_materials.insert(std::make_pair("IfcPlate", IfcGeom::SurfaceStyle("IfcPlate")));
default_materials["IfcPlate"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.8, 0.8, 0.8));
default_materials.insert(std::make_pair("IfcPlate", std::make_shared<IfcGeom::SurfaceStyle>("IfcPlate")));
default_materials["IfcPlate"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.8, 0.8, 0.8));
default_materials.insert(std::make_pair("IfcSpace", IfcGeom::SurfaceStyle("IfcSpace")));
default_materials["IfcWindow"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.75, 0.8));
default_materials["IfcWindow"].Transparency().reset(0.8);
default_materials.insert(std::make_pair("IfcSpace", std::make_shared<IfcGeom::SurfaceStyle>("IfcSpace")));
default_materials["IfcWindow"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.75, 0.8));
default_materials["IfcWindow"]->Transparency().reset(0.8);
default_material = IfcGeom::SurfaceStyle("DefaultMaterial");
default_material.Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.7, 0.7, 0.7));
default_material = std::make_shared<IfcGeom::SurfaceStyle>("DefaultMaterial");
default_material->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.7, 0.7, 0.7));
default_materials_initialized = true;
}
@@ -83,58 +83,49 @@ void IfcGeom::set_default_style_file(const std::string& json_file) {
for (pt::ptree::value_type &material_pair : root) {
std::string name = material_pair.first;
default_materials.insert(std::make_pair(name, IfcGeom::SurfaceStyle(name)));
default_materials.insert(std::make_pair(name, std::make_shared<IfcGeom::SurfaceStyle>(name)));
pt::ptree material = material_pair.second;
boost::optional<pt::ptree&> diffuse = material.get_child_optional("diffuse");
default_materials[name].Diffuse() = read_colour_component(diffuse);
default_materials[name]->Diffuse() = read_colour_component(diffuse);
boost::optional<pt::ptree&> specular = material.get_child_optional("specular");
default_materials[name].Specular() = read_colour_component(specular);
default_materials[name]->Specular() = read_colour_component(specular);
if (material.get_child_optional("specular-roughness")) {
default_materials[name].Specularity().reset(1.0 / material.get<double>("specular-roughness"));
default_materials[name]->Specularity().reset(1.0 / material.get<double>("specular-roughness"));
}
if (material.get_child_optional("transparency")) {
default_materials[name].Transparency() = material.get<double>("transparency");
default_materials[name]->Transparency() = material.get<double>("transparency");
}
}
// Is "*" present? If yes, remove it and make it the default style.
std::map<std::string, IfcGeom::SurfaceStyle>::const_iterator it = default_materials.find("*");
auto it = default_materials.find("*");
if (it != default_materials.end()) {
IfcGeom::SurfaceStyle star = it->second;
default_material.Diffuse() = star.Diffuse();
default_material.Specular() = star.Specular();
default_material.Specularity() = star.Specularity();
default_material.Transparency() = star.Transparency();
default_material = it->second;
default_materials.erase(it);
}
}
const IfcGeom::SurfaceStyle* IfcGeom::get_default_style(const std::string& s) {
std::shared_ptr<const IfcGeom::SurfaceStyle> IfcGeom::get_default_style(const std::string& s) {
static std::mutex m;
std::lock_guard<std::mutex> lk(m);
if (!default_materials_initialized) InitDefaultMaterials();
std::map<std::string, IfcGeom::SurfaceStyle>::const_iterator it = default_materials.find(s);
auto it = default_materials.find(s);
if (it == default_materials.end()) {
default_materials.insert(std::make_pair(s, IfcGeom::SurfaceStyle(s)));
default_materials[s].Diffuse() = default_material.Diffuse();
default_materials[s].Specular() = default_material.Specular();
default_materials[s].Specularity() = default_material.Specularity();
default_materials[s].Transparency() = default_material.Transparency();
default_materials.insert(std::make_pair(s, default_material));
it = default_materials.find(s);
}
const IfcGeom::SurfaceStyle& surface_style = it->second;
return &surface_style;
return it->second;
}
IfcGeom::SurfaceStyle& IfcGeom::update_default_style(const std::string& s) {
if (!default_materials_initialized) InitDefaultMaterials();
std::map<std::string, IfcGeom::SurfaceStyle>::iterator it = default_materials.find(s);
auto it = default_materials.find(s);
if (it == default_materials.end()) {
throw std::runtime_error("No style registered for " + s);
}
return it->second;
return *it->second;
}
-1
View File
@@ -21,7 +21,6 @@
#define GEOMETRYSERIALIZER_H
#include "../serializers/Serializer.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h"
#include "../ifcgeom/IfcGeomElement.h"
class SerializerSettings : public IfcGeom::IteratorSettings
+559 -71
View File
@@ -25,106 +25,594 @@
#include "../ifcparse/utils.h"
#include <BRepTools_ShapeSet.hxx>
#include <BinTools_ShapeSet.hxx>
#include <boost/lexical_cast.hpp>
#include <iomanip>
#include <numeric>
#include <functional>
#ifdef USE_BINARY
#define write_shape write_binary
#define read_shape read_binary
#else
#define write_shape write_text
#define read_shape read_text
#endif
herr_t print_stack(hid_t, void*) {
/*
// For debugging: when using IfcConvert on Windows with wcout,
// it's difficult to get console output of HDF5 stack traces.
auto f = fopen("temp.txt", "w");
H5Eprint(estack, f);
fclose(f);
*/
return 0;
}
HdfSerializer::HdfSerializer(const std::string& hdf_filename, const SerializerSettings& settings)
: GeometrySerializer(settings)
, hdf_filename(hdf_filename)
, DATASET_NAME_POSITIONS("Positions")
, DATASET_NAME_NORMALS("Normals")
, DATASET_NAME_INDICES("Indices")
, DATASET_NAME_OCCT("OCCT Text")
, settings_(settings)
{
guids = {};
H5E_auto2_t fn = &print_stack;
H5::Exception::setAutoPrint(fn, nullptr);
try {
file = H5::H5File(hdf_filename, H5F_ACC_RDWR | H5F_ACC_CREAT);
} catch (H5::Exception&) {
file = H5::H5File(hdf_filename, H5F_ACC_TRUNC);
}
str_type = H5::StrType(H5::PredType::C_S1, H5T_VARIABLE);
#ifdef USE_BINARY
auto uint_type = H5::PredType::NATIVE_UINT8;
shape_type = H5::VarLenType(&uint_type);
#else
shape_type = str_type;
#endif
hsize_t dims_3[1]{ 3 };
double3 = H5::ArrayType(H5::PredType::NATIVE_DOUBLE, 1, dims_3);
style_compound = H5::CompType(sizeof(surface_style_serialization));
style_compound.insertMember("name", HOFFSET(surface_style_serialization, name), str_type);
style_compound.insertMember("original_name", HOFFSET(surface_style_serialization, original_name), str_type);
style_compound.insertMember("id", HOFFSET(surface_style_serialization, id), H5::PredType::NATIVE_INT);
style_compound.insertMember("diffuse", HOFFSET(surface_style_serialization, diffuse), double3);
style_compound.insertMember("specular", HOFFSET(surface_style_serialization, specular), double3);
style_compound.insertMember("transparency", HOFFSET(surface_style_serialization, transparency), H5::PredType::NATIVE_DOUBLE);
style_compound.insertMember("specularity", HOFFSET(surface_style_serialization, specularity), H5::PredType::NATIVE_DOUBLE);
hsize_t dims_4x4[2]{ 4, 4 };
double4x4 = H5::ArrayType(H5::PredType::NATIVE_DOUBLE, 2, dims_4x4);
compound = H5::CompType(sizeof(brep_element));
compound.insertMember("id", HOFFSET(brep_element, id), H5::PredType::NATIVE_INT);
compound.insertMember("matrix", HOFFSET(brep_element, matrix), double4x4);
compound.insertMember("shape_serialization", HOFFSET(brep_element, shape_serialization), shape_type);
compound.insertMember("surface_style_id", HOFFSET(brep_element, surface_style), style_compound);
}
bool HdfSerializer::ready() {
//todo: check whether the file exists
return true;
}
void HdfSerializer::writeHeader() {
const H5std_string FILE_NAME(hdf_filename);
file = H5::H5File(FILE_NAME, H5F_ACC_TRUNC);
}
namespace {
template <typename T>
H5::DataType h5_datatype_for_cpp();
template <>
H5::DataType h5_datatype_for_cpp<int>() {
return H5::PredType::NATIVE_INT;
}
template <>
H5::DataType h5_datatype_for_cpp<double>() {
return H5::PredType::NATIVE_DOUBLE;
}
template <>
H5::DataType h5_datatype_for_cpp<std::string>() {
return H5::StrType(H5::PredType::C_S1, H5T_VARIABLE);
}
template <typename T>
void do_read(H5::Attribute& attr, T& val) {
attr.read(h5_datatype_for_cpp<T>(), &val);
}
template <>
void do_read(H5::Attribute& attr, std::string& val) {
attr.read(h5_datatype_for_cpp<std::string>(), val);
}
template <typename T>
T read_scalar_attribute(H5::H5Object& l, const std::string& name) {
auto attr = l.openAttribute(name);
auto space = attr.getSpace();
int rank = space.getSimpleExtentNdims();
// A scalar dataspace, H5S_SCALAR, has a single element, though that
// element may be of a complex datatype, such as a compound or array
// datatype. By convention, the rank of a scalar dataspace is always
// 0 (zero);
if (rank != 0) {
throw std::runtime_error("Invalid");
}
T val;
do_read<T>(attr, val);
return val;
}
}
#include <BinTools.hxx>
namespace {
// https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/TopoShape.cpp
TopoDS_Shape read_binary(const hvl_t& vlen) {
std::string s((char*)vlen.p, (size_t)vlen.len);
std::istringstream str(s);
BinTools_ShapeSet theShapeSet;
theShapeSet.Read(str);
Standard_Integer shapeId = 0, locId = 0, orient = 0;
BinTools::GetInteger(str, shapeId);
if (shapeId <= 0 || shapeId > theShapeSet.NbShapes()) {
throw std::runtime_error("");
}
BinTools::GetInteger(str, locId);
BinTools::GetInteger(str, orient);
TopAbs_Orientation anOrient = static_cast<TopAbs_Orientation>(orient);
TopoDS_Shape shp = theShapeSet.Shape(shapeId);
shp.Location(theShapeSet.Locations().Location(locId));
shp.Orientation(anOrient);
return shp;
}
// https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/TopoShape.cpp
void write_binary(TopoDS_Shape shp, std::string& s) {
std::ostringstream out;
BinTools_ShapeSet theShapeSet;
Standard_Integer shapeId = theShapeSet.Add(shp);
Standard_Integer locId = theShapeSet.Locations().Index(shp.Location());
Standard_Integer orient = static_cast<int>(shp.Orientation());
theShapeSet.Write(out);
BinTools::PutInteger(out, shapeId);
BinTools::PutInteger(out, locId);
BinTools::PutInteger(out, orient);
s = out.str();
}
TopoDS_Shape read_text(const std::string& s) {
std::stringstream stream(s);
BRep_Builder B;
TopoDS_Shape shp;
BRepTools::Read(shp, stream, B);
return shp;
}
void write_text(TopoDS_Shape shp, std::string& out) {
std::stringstream sstream;
BRepTools::Write(shp, sstream);
out = sstream.str();
}
}
namespace {
template <typename T>
std::vector<T> read_dataset(const H5::Group& group, const std::string& name) {
auto ds = group.openDataSet(name);
auto space = ds.getSpace();
int rank = space.getSimpleExtentNdims();
std::vector<hsize_t> dims(rank);
space.getSimpleExtentDims(dims.data(), NULL);
const hsize_t total = std::accumulate(dims.begin(), dims.end(), 1U, std::multiplies<hsize_t>());
std::vector<T> result(total);
ds.read(result.data(), h5_datatype_for_cpp<T>());
return result;
}
}
void HdfSerializer::read_surface_style(surface_style_serialization& s, std::shared_ptr<IfcGeom::SurfaceStyle>& style_ptr) {
if (strlen(s.name) || s.id) {
if (strlen(s.name) && s.id) {
style_ptr = std::make_shared<IfcGeom::SurfaceStyle>(s.id, s.name);
} else if (strlen(s.name)) {
style_ptr = std::make_shared<IfcGeom::SurfaceStyle>(s.name);
} else if (s.id) {
style_ptr = std::make_shared<IfcGeom::SurfaceStyle>(s.id);
}
auto& gss = *style_ptr;
if (s.diffuse[0] == s.diffuse[0]) {
gss.Diffuse().emplace(s.diffuse[0], s.diffuse[1], s.diffuse[2]);
}
if (s.specular[0] == s.specular[0]) {
gss.Specular().emplace(s.specular[0], s.specular[1], s.specular[2]);
}
if (s.transparency == s.transparency) {
gss.Transparency() = s.transparency;
}
if (s.specularity == s.specularity) {
gss.Specularity() = s.specularity;
}
}
}
const IfcGeom::Element* HdfSerializer::read(IfcParse::IfcFile& f, const std::string& guid, unsigned int representation_id, read_type rt) {
if (!H5Lexists(file.getId(), guid.c_str(), H5P_DEFAULT)) {
return nullptr;
}
auto representation_id_str = std::to_string(representation_id);
auto element_group = file.openGroup(guid);
if (!H5Lexists(element_group.getId(), representation_id_str.c_str(), H5P_DEFAULT)) {
return nullptr;
}
int id = read_scalar_attribute<int>(element_group, "id");
int parent_id = read_scalar_attribute<int>(element_group, "parent_id");
std::string type = read_scalar_attribute<std::string>(element_group, "type");
std::string name = read_scalar_attribute<std::string>(element_group, "name");
std::string context = read_scalar_attribute<std::string>(element_group, "context");
std::string unique_id = read_scalar_attribute<std::string>(element_group, "unique_id");
gp_Trsf trsf;
auto placeds = element_group.openDataSet(DATASET_NAME_PLACEMENT);
double m44[4][4];
placeds.read(m44, H5::PredType::NATIVE_DOUBLE);
trsf.SetValues(
m44[0][0], m44[0][1], m44[0][2], m44[0][3],
m44[1][0], m44[1][1], m44[1][2], m44[1][3],
m44[2][0], m44[2][1], m44[2][2], m44[2][3]
);
auto representation_group = element_group.openGroup(std::to_string(representation_id));
std::string geom_id = read_scalar_attribute<std::string>(representation_group, "geom_id");
IfcGeom::ElementSettings element_settings(settings_, f.getUnit("LENGTHUNIT").second, type);
auto inst = f.instance_by_id(id)->as<IfcUtil::IfcBaseEntity>();
if (rt == READ_BREP) {
auto brepDataset = representation_group.openDataSet(DATASET_NAME_OCCT);
std::vector<brep_element> parts;
{
auto space = brepDataset.getSpace();
int rank = space.getSimpleExtentNdims();
if (rank != 1) {
return nullptr;
}
std::vector<hsize_t> dims(rank);
space.getSimpleExtentDims(dims.data(), NULL);
parts.resize(dims[0]);
brepDataset.read(parts.data(), compound);
}
IfcGeom::IfcRepresentationShapeItems shapes;
for (auto& part : parts) {
TopoDS_Shape shp = read_shape(part.shape_serialization);
gp_GTrsf trsf(gp_Mat(
part.matrix[0][0], part.matrix[0][1], part.matrix[0][2],
part.matrix[1][0], part.matrix[1][1], part.matrix[1][2],
part.matrix[2][0], part.matrix[2][1], part.matrix[2][2]
), gp_XYZ(
part.matrix[3][0], part.matrix[3][1], part.matrix[3][2]
));
std::shared_ptr<IfcGeom::SurfaceStyle> style_ptr;
read_surface_style(part.surface_style, style_ptr);
shapes.push_back(IfcGeom::IfcRepresentationShapeItem(part.id, trsf, shp, style_ptr));
}
auto geometry = boost::shared_ptr<IfcGeom::Representation::BRep>(new IfcGeom::Representation::BRep(element_settings, geom_id, shapes));
return new IfcGeom::BRepElement(id, parent_id, name, type, guid, context, trsf, geometry, inst);
} else {
H5::Group meshGroup;
try {
meshGroup = representation_group.openGroup(GROUP_NAME_MESH);
} catch (H5::Exception&) {
return nullptr;
}
auto verts = read_dataset<double>(meshGroup, DATASET_NAME_POSITIONS);
auto faces = read_dataset<int>(meshGroup, DATASET_NAME_INDICES);
auto edges = read_dataset<int>(meshGroup, DATASET_NAME_EDGES);
auto normals = read_dataset<double>(meshGroup, DATASET_NAME_NORMALS);
auto uvcoords = read_dataset<double>(meshGroup, DATASET_NAME_UVCOORDS);
auto material_ids = read_dataset<int>(meshGroup, DATASET_NAME_MATERIAL_IDS);
std::vector<surface_style_serialization> surface_styles;
{
auto ds = meshGroup.openDataSet(DATASET_NAME_MATERIALS);
auto space = ds.getSpace();
int rank = space.getSimpleExtentNdims();
if (rank != 1) {
return nullptr;
}
std::vector<hsize_t> dims(rank);
space.getSimpleExtentDims(dims.data(), NULL);
surface_styles.resize(dims[0]);
ds.read(surface_styles.data(), style_compound);
}
std::vector<std::shared_ptr<IfcGeom::SurfaceStyle>> surface_style_ptrs(surface_styles.size());
for (size_t i = 0; i < surface_styles.size(); ++i) {
read_surface_style(surface_styles[i], surface_style_ptrs[i]);
}
auto rep = boost::shared_ptr<IfcGeom::Representation::Triangulation>(new IfcGeom::Representation::Triangulation(
element_settings,
geom_id,
verts,
faces,
edges,
normals,
uvcoords,
material_ids,
surface_style_ptrs
));
return new IfcGeom::TriangulationElement(
IfcGeom::Element(
element_settings,
id,
parent_id,
name,
type,
guid,
context,
trsf,
inst
),
rep
);
}
}
namespace {
std::array<std::array<double, 4>, 4> gtrsf_to_matrix(const gp_GTrsf& trsf) {
std::array<std::array<double, 4>, 4> arr;
for (int i = 1; i < 5; ++i) {
for (int j = 1; j < 4; ++j) {
arr[i-1][j-1] = trsf.Value(j, i);
}
arr[i - 1][3] = i == 4 ? 1.0 : 0.0;
}
return arr;
}
}
H5::Group HdfSerializer::write(const IfcGeom::Element* o) {
try {
return file.openGroup(o->guid());
} catch (H5::Exception&) {}
H5::Group element_group = file.createGroup(o->guid());
typedef std::string const & (IfcGeom::Element::*string_member_fun)(void) const;
typedef int (IfcGeom::Element::*int_member_fun)(void) const;
static const std::vector<std::pair<const char* const, string_member_fun>> data_pairs_string = {
{"type", &IfcGeom::Element::type},
{"name", &IfcGeom::Element::name },
{"guid", &IfcGeom::Element::guid },
{"context", &IfcGeom::Element::context },
{"unique_id", &IfcGeom::Element::unique_id }
};
static const std::vector<std::pair<const char* const, int_member_fun>> data_pairs_int = {
{"id", &IfcGeom::Element::id},
{"parent_id", &IfcGeom::Element::parent_id },
};
H5::DataSpace attrdspace(H5S_SCALAR);
for (auto& p : data_pairs_string) {
H5::Attribute att = element_group.createAttribute(p.first, str_type, attrdspace);
att.write(str_type, ((*o).*(p.second))());
}
for (auto& p : data_pairs_int) {
H5::Attribute att = element_group.createAttribute(p.first, H5::PredType::NATIVE_INT, attrdspace);
int value = ((*o).*(p.second))();
att.write(H5::PredType::NATIVE_INT, &value);
}
hsize_t dims_4x4[2]{ 4, 4 };
H5::DataSpace dataspace_4x4(2, dims_4x4);
auto placement_dataset = element_group.createDataSet(DATASET_NAME_PLACEMENT, H5::PredType::NATIVE_DOUBLE, dataspace_4x4);
const std::vector<double>& m43 = o->transformation().matrix().data();
double m44[4][4] = {
{ m43[0], m43[3], m43[6], m43[9] },
{ m43[1], m43[4], m43[7], m43[10] },
{ m43[2], m43[5], m43[8], m43[11] },
{ 0, 0, 0, 1 }
};
placement_dataset.write(m44, H5::PredType::NATIVE_DOUBLE);
return element_group;
}
H5::Group HdfSerializer::createRepresentationGroup(const H5::Group& element_group, const std::string& gid) {
// the part before the hyphen is the representation id
auto gid2 = gid;
auto hyphen = gid2.find("-");
if (hyphen != std::string::npos) {
gid2 = gid2.substr(0, hyphen);
}
H5::Group representation_group;
try {
representation_group = element_group.openGroup(gid2);
} catch (H5::Exception&) {
representation_group = element_group.createGroup(gid2);
H5::DataSpace attrdspace(H5S_SCALAR);
{
H5::Attribute att = representation_group.createAttribute("geom_id", str_type, attrdspace);
std::string value = gid;
att.write(str_type, value);
}
}
return representation_group;
}
void HdfSerializer::write_style(surface_style_serialization& data, const IfcGeom::SurfaceStyle& s) {
data.name = s.Name().c_str();
data.original_name = s.original_name().c_str();
data.id = s.Id().get_value_or(0);
if (s.Diffuse()) {
data.diffuse[0] = s.Diffuse()->R();
data.diffuse[1] = s.Diffuse()->G();
data.diffuse[2] = s.Diffuse()->B();
}
if (s.Specular()) {
data.specular[0] = s.Specular()->R();
data.specular[1] = s.Specular()->G();
data.specular[2] = s.Specular()->B();
}
if (s.Transparency()) {
data.transparency = *s.Transparency();
}
if (s.Specularity()) {
data.specularity = *s.Specularity();
}
}
void HdfSerializer::write(const IfcGeom::BRepElement* o) {
static auto nan = std::numeric_limits<double>::quiet_NaN();
std::string guid = o->guid();
auto element_group = write((const IfcGeom::Element*)o);
H5::Group elementGroup;
H5::Group representation_group = createRepresentationGroup(element_group, o->geometry().id());
H5::Group meshGroup;
H5::DataSet positionsDataset;
H5::DataSet normalsDataset;
H5::DataSet indicesDataset;
std::list<std::string> brep_strings;
size_t num_parts = std::distance(o->geometry().begin(), o->geometry().end());
brep_element* parts = new brep_element[num_parts];
size_t i = 0;
for (auto it = o->geometry().begin(); it != o->geometry().end(); ++it, ++i) {
parts[i].id = it->ItemId();
std::array<std::array<double, 4>, 4> arr = gtrsf_to_matrix(it->Placement());
for (int j = 0; j < 4; ++j) {
std::copy(arr[j].begin(), arr[j].end(), parts[i].matrix[j]);
}
H5::Group OCCTGroup;
H5::DataSet OCCTDataset;
const IfcGeom::Representation::BRep& brepmesh = o->geometry();
const IfcGeom::Representation::Serialization serialization(brepmesh);
std::string brep_data = serialization.brep_data();
const IfcGeom::TriangulationElement triangular_element(*o);
const IfcGeom::Representation::Triangulation& mesh = triangular_element.geometry();
const int vcount = (int)mesh.verts().size() / 3;
const int fcount = (int)mesh.faces().size() / 3;
const bool isyup = settings().get(SerializerSettings::USE_Y_UP);
std::string value = o->type();
if (fcount > 0) {
guids.insert(guid);
elementGroup = file.createGroup(guid);
meshGroup = elementGroup.createGroup("Triangle Mesh");
OCCTGroup = elementGroup.createGroup("OCCT Data");
H5::StrType str_type(0, H5T_VARIABLE);
H5:: DataSpace attrdspace(H5S_SCALAR);
H5::Attribute att = elementGroup.createAttribute("IFC entity type", str_type, attrdspace);
att.write(str_type, value);
const int RANK = 2;
hsize_t dimsf[2];
dimsf[0] = vcount;
dimsf[1] = 3;
H5::DataSpace dataspace(RANK, dimsf);
hsize_t dimsfaces[2];
dimsfaces[0] = fcount;
dimsfaces[1] = 3;
H5::DataSpace face_dataspace(RANK, dimsfaces);
const int RANK_OCCT = 1;
hsize_t dimsocct[2];
dimsocct[0] = 1;
dimsfaces[1] = 1;
H5::DataSpace occt_dataspace(RANK_OCCT, dimsocct);
OCCTDataset = OCCTGroup.createDataSet(DATASET_NAME_OCCT, str_type, occt_dataspace);
OCCTDataset.write(brep_data, str_type);
indicesDataset = meshGroup.createDataSet(DATASET_NAME_INDICES, H5::PredType::NATIVE_INT, face_dataspace);
positionsDataset = meshGroup.createDataSet(DATASET_NAME_POSITIONS, H5::PredType::NATIVE_DOUBLE, dataspace);
normalsDataset = meshGroup.createDataSet(DATASET_NAME_NORMALS, H5::PredType::NATIVE_DOUBLE, dataspace);
positionsDataset.write(mesh.verts().data(), H5::PredType::NATIVE_DOUBLE);
normalsDataset.write(mesh.normals().data(), H5::PredType::NATIVE_DOUBLE);
indicesDataset.write(mesh.faces().data(), H5::PredType::NATIVE_INT);
brep_strings.emplace_back();
write_shape(it->Shape(), brep_strings.back());
parts[i].surface_style = { "", "", 0, {nan,nan,nan}, {nan,nan,nan}, nan, nan };
if (it->hasStyle()) {
auto& s = it->Style();
write_style(parts[i].surface_style, s);
}
#ifdef USE_BINARY
const auto& s = brep_strings.back();
parts[i].shape_serialization.p = new char[s.size()];
memcpy(parts[i].shape_serialization.p, s.c_str(), s.size());
parts[i].shape_serialization.len = s.size();
#else
parts[i].shape_serialization = brep_strings.back().c_str();
#endif
}
hsize_t dimsp[1]{ num_parts };
H5::DataSpace dataspace_parts(1, dimsp);
auto brepDataset = representation_group.createDataSet(DATASET_NAME_OCCT, compound, dataspace_parts);
brepDataset.write(parts, compound);
}
namespace {
template <typename T>
void write_dataset(const H5::Group& group, const std::string& name, const std::vector<T>& ts, size_t stride) {
hsize_t d[2]{ ts.size() / stride, stride };
H5::DataSpace dataspace(stride == 1 ? 1 : 2, d);
auto dt = h5_datatype_for_cpp<T>();
auto ds = group.createDataSet(name, dt, dataspace);
ds.write(ts.data(), dt);
}
}
void HdfSerializer::write(const IfcGeom::TriangulationElement* o) {
auto element_group = write((const IfcGeom::Element*)o);
const auto& mesh = o->geometry();
H5::Group representation_group = createRepresentationGroup(element_group, o->geometry().id());
H5::Group meshGroup = representation_group.createGroup(GROUP_NAME_MESH);
write_dataset(meshGroup, DATASET_NAME_POSITIONS, mesh.verts(), 3);
write_dataset(meshGroup, DATASET_NAME_INDICES, mesh.faces(), 3);
write_dataset(meshGroup, DATASET_NAME_EDGES, mesh.edges(), 2);
write_dataset(meshGroup, DATASET_NAME_NORMALS, mesh.normals(), 2);
write_dataset(meshGroup, DATASET_NAME_UVCOORDS, mesh.uvs(), 2);
write_dataset(meshGroup, DATASET_NAME_MATERIAL_IDS, mesh.material_ids(), 1);
{
auto& ts = mesh.materials();
hsize_t d[2] { ts.size() };
H5::DataSpace dataspace(1, d);
const auto& dt = style_compound;
std::vector<surface_style_serialization> data;
data.reserve(ts.size());
for (auto& m : ts) {
data.emplace_back();
write_style(data.back(), m.get_style());
}
auto ds = meshGroup.createDataSet(DATASET_NAME_MATERIALS, dt, dataspace);
ds.write(data.data(), dt);
}
}
const H5std_string HdfSerializer::DATASET_NAME_POSITIONS = "positions";
const H5std_string HdfSerializer::DATASET_NAME_UVCOORDS = "uvcoords";
const H5std_string HdfSerializer::DATASET_NAME_NORMALS = "normals";
const H5std_string HdfSerializer::DATASET_NAME_INDICES = "indices";
const H5std_string HdfSerializer::DATASET_NAME_EDGES = "edges";
const H5std_string HdfSerializer::DATASET_NAME_MATERIAL_IDS = "material_ids";
const H5std_string HdfSerializer::DATASET_NAME_MATERIALS = "materials";
const H5std_string HdfSerializer::DATASET_NAME_OCCT = "brep";
const H5std_string HdfSerializer::DATASET_NAME_PLACEMENT = "placement";
const H5std_string HdfSerializer::GROUP_NAME_MESH = "mesh";
#endif
+66 -9
View File
@@ -17,8 +17,8 @@
* *
********************************************************************************/
#ifndef HdfSERIALIZER_H
#define HdfSERIALIZER_H
#ifndef HDFSERIALIZER_H
#define HDFSERIALIZER_H
#ifdef WITH_HDF5
@@ -30,32 +30,89 @@
#include "../serializers/GeometrySerializer.h"
#define USE_BINARY
class HdfSerializer : public GeometrySerializer {
public:
enum read_type { READ_BREP, READ_TRIANGULATION };
private:
const std::string hdf_filename;
unsigned int vcount_total;
H5::H5File file;
std::set<std::string> guids;
const H5std_string DATASET_NAME_POSITIONS;
const H5std_string DATASET_NAME_NORMALS;
const H5std_string DATASET_NAME_INDICES;
const H5std_string DATASET_NAME_OCCT;
SerializerSettings settings_;
static const H5std_string DATASET_NAME_POSITIONS;
static const H5std_string DATASET_NAME_UVCOORDS;
static const H5std_string DATASET_NAME_NORMALS;
static const H5std_string DATASET_NAME_INDICES;
static const H5std_string DATASET_NAME_EDGES;
static const H5std_string DATASET_NAME_MATERIAL_IDS;
static const H5std_string DATASET_NAME_MATERIALS;
static const H5std_string DATASET_NAME_OCCT;
static const H5std_string DATASET_NAME_PLACEMENT;
static const H5std_string GROUP_NAME_MESH;
struct surface_style_serialization {
const char* name;
const char* original_name;
// 0 if unset
unsigned int id;
// nan if unset
double diffuse[3];
double specular[3];
double transparency;
double specularity;
};
struct brep_element {
int id;
double matrix[4][4];
#ifdef USE_BINARY
hvl_t shape_serialization;
#else
const char* shape_serialization;
#endif
surface_style_serialization surface_style;
};
H5::CompType compound;
H5::CompType style_compound;
H5::StrType str_type;
H5::ArrayType double4x4, double3;
H5::DataType shape_type;
private:
H5::Group createRepresentationGroup(const H5::Group& element_group, const std::string& gid);
void read_surface_style(surface_style_serialization& sss, std::shared_ptr<IfcGeom::SurfaceStyle>& style_ptr);
void write_style(surface_style_serialization& data, const IfcGeom::SurfaceStyle& s);
public:
HdfSerializer(const std::string& hdf_filename, const SerializerSettings& settings);
virtual ~HdfSerializer() {}
bool ready();
void writeHeader();
H5::Group write(const IfcGeom::Element* o);
void write(const IfcGeom::BRepElement* o);
void write(const IfcGeom::TriangulationElement* /*o*/) {}
void write(const IfcGeom::TriangulationElement* o);
const IfcGeom::Element* read(IfcParse::IfcFile& f, const std::string& guid, unsigned int representation_id, read_type rt = READ_BREP);
void finalize() {}
bool isTesselated() const { return false; }
void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {}
void setFile(IfcParse::IfcFile*) {}
};
#else
// We just define something here so that the symbol exists and the Iterator class
// methods don't need to look so different
class HdfSerializer {};
#endif
#endif
+2
View File
@@ -19,6 +19,8 @@
* *
********************************************************************************/
#include "../ifcgeom_schema_agnostic/Kernel.h"
#include <string>
#include <fstream>
#include <cstdio>