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 filter_filename;
path_t default_material_filename; path_t default_material_filename;
path_t log_file; path_t log_file;
path_t cache_file;
std::string log_format; std::string log_format;
po::options_description generic_options("Command line options"); po::options_description generic_options("Command line options");
@@ -218,6 +219,9 @@ int main(int argc, char** argv) {
("version", "display version information") ("version", "display version information")
("verbose,v", po::value(&vcounter)->zero_tokens(), "more verbose log messages") ("verbose,v", po::value(&vcounter)->zero_tokens(), "more verbose log messages")
("quiet,q", "less status and progress output") ("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") ("stderr-progress", "output progress to stderr stream")
("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)") ("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") ("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") ("mmap", "use memory-mapped file for input")
#endif #endif
("input-file", new po::typed_value<path_t, char_t>(0), "input IFC file") ("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"); po::options_description ifc_options("IFC options");
ifc_options.add_options() ifc_options.add_options()
("calculate-quantities", "Calculate or fix the physical quantity definitions " ("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"), STP = IfcUtil::path::from_utf8(".stp"),
IGS = IfcUtil::path::from_utf8(".igs"), IGS = IfcUtil::path::from_utf8(".igs"),
SVG = IfcUtil::path::from_utf8(".svg"), SVG = IfcUtil::path::from_utf8(".svg"),
CACHE = IfcUtil::path::from_utf8(".cache"),
HDF = IfcUtil::path::from_utf8(".h5"), HDF = IfcUtil::path::from_utf8(".h5"),
XML = IfcUtil::path::from_utf8(".xml"), XML = IfcUtil::path::from_utf8(".xml"),
IFC = IfcUtil::path::from_utf8(".ifc"); 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); 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()) { if (!context_iterator.initialize()) {
/// @todo It would be nice to know and print separate error prints for a case where we found no entities /// @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. /// 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; MAKE_TYPE_NAME(Cache) cache;
#endif #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: public:
MAKE_TYPE_NAME(Kernel)() 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); 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); 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 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<const SurfaceStyle*>&, IfcRepresentationShapeItems&); 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<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 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&); 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*); const IfcSchema::IfcMaterial* get_single_material_association(const IfcSchema::IfcProduct*);
IfcSchema::IfcRepresentation* representation_mapped_to(const IfcSchema::IfcRepresentation* representation); IfcSchema::IfcRepresentation* representation_mapped_to(const IfcSchema::IfcRepresentation* representation);
IfcSchema::IfcProduct::list::ptr products_represented_by(const IfcSchema::IfcRepresentation*); IfcSchema::IfcProduct::list::ptr products_represented_by(const IfcSchema::IfcRepresentation*);
const SurfaceStyle* get_style(const IfcSchema::IfcRepresentationItem*); std::shared_ptr<const SurfaceStyle> get_style(const IfcSchema::IfcRepresentationItem*);
const SurfaceStyle* get_style(const IfcSchema::IfcMaterial*); 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) { template <typename T> std::pair<IfcSchema::IfcSurfaceStyle*, T*> _get_surface_style(const IfcSchema::IfcStyledItem* si) {
std::vector<IfcSchema::IfcPresentationStyle*> prs_styles; 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; return true;
@@ -1123,7 +1123,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
continue; 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 // For manifold first operands we're not even going to try if processing
// as loose faces gives a better result. // 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<double> thickness;
std::vector<Handle_Geom_Surface> layers; std::vector<Handle_Geom_Surface> layers;
std::vector< std::vector<Handle_Geom_Surface> > folded_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)) { if (convert_layerset(product, layers, styles, thickness)) {
IfcSchema::IfcRelAssociates::list::ptr associations = product->HasAssociations(); 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); const IfcSchema::IfcMaterial* single_material = get_single_material_association(product);
if (single_material) { 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) { for (IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++it) {
if (!it->hasStyle() && s) { if (!it->hasStyle() && s) {
it->setStyle(s); it->setStyle(s);
@@ -1917,8 +1917,8 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and_produc
for (auto& s : shapes) { for (auto& s : shapes) {
if (s.hasStyle()) { if (s.hasStyle()) {
for (auto& p : style_cache) { for (auto& p : style_cache) {
if (&p.second == &s.Style()) { if (p.second == s.StylePtr()) {
p.second.Transparency() = settings.force_space_transparency(); 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); 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; IfcSchema::IfcMaterialLayerSetUsage* usage = 0;
Handle_Geom_Surface reference_surface; Handle_Geom_Surface reference_surface;
@@ -3063,7 +3063,7 @@ namespace {
#endif #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; Bnd_Box bb;
TopoDS_Shape input; TopoDS_Shape input;
flatten_shape_list(items, input, false); 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) { for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
TopoDS_Shape a,b; TopoDS_Shape a,b;
if (split_solid_by_shell(it->Shape(), shells.First(), 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(), b, !!styles[0] ? styles[0] : it->StylePtr()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, styles[1] ? styles[1] : &it->Style())); result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, !!styles[1] ? styles[1] : it->StylePtr()));
} else { } else {
continue; continue;
} }
@@ -3168,7 +3168,7 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i
std::vector<TopoDS_Shape> slices; std::vector<TopoDS_Shape> slices;
if (split(*this, it->Shape(), shells, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) { if (split(*this, it->Shape(), shells, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) {
for (size_t i = 0; i < slices.size(); ++i) { 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 { } else {
return false; 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) { if (surfaces.size() < 3) {
return false; 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) { for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
TopoDS_Shape a,b; TopoDS_Shape a,b;
if (split_solid_by_surface(it->Shape(), surfaces[1], 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(), b, !!styles[0] ? styles[0] : it->StylePtr()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, styles[1] ? styles[1] : &it->Style())); result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, !!styles[1] ? styles[1] : it->StylePtr()));
} else { } else {
continue; continue;
} }
@@ -3259,7 +3259,7 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c
std::vector<TopoDS_Shape> slices; std::vector<TopoDS_Shape> slices;
if (split(*this, it->Shape(), operands, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) { if (split(*this, it->Shape(), operands, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) {
for (size_t i = 0; i < slices.size(); ++i) { 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 { } else {
return false; return false;
+59 -11
View File
@@ -777,11 +777,25 @@ namespace IfcGeom {
Logger::SetProduct(product); Logger::SetProduct(product);
bool read_from_cache = false;
BRepElement* element; BRepElement* element;
if (ifcproduct_iterator == ifcproducts->begin() || !geometry_reuse_ok_for_current_representation_) {
element = kernel.create_brep_for_representation_and_product(settings, representation, product); #ifdef WITH_HDF5
} else { if (cache_) {
element = kernel.create_brep_for_processed_representation(settings, representation, product, current_shape_model); 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); Logger::SetProduct(boost::none);
@@ -791,6 +805,12 @@ namespace IfcGeom {
continue; continue;
} }
#ifdef WITH_HDF5
if (cache_ && !read_from_cache) {
cache_->write(element);
}
#endif
return element; return element;
} }
} }
@@ -1003,14 +1023,42 @@ namespace IfcGeom {
Logger::Message(Logger::LOG_ERROR, "Getting a serialized element from model failed."); Logger::Message(Logger::LOG_ERROR, "Getting a serialized element from model failed.");
} }
} else if (!settings.get(IteratorSettings::DISABLE_TRIANGULATION)) { } else if (!settings.get(IteratorSettings::DISABLE_TRIANGULATION)) {
try {
if (ifcproduct_iterator == ifcproducts->begin() || !geometry_reuse_ok_for_current_representation_) { bool read_from_cache = false;
next_triangulation = new TriangulationElement(*next_shape_model);
} else { #ifdef WITH_HDF5
next_triangulation = new TriangulationElement(*next_shape_model, current_triangulation->geometry_pointer()); 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) #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) { if (shading_styles.second == 0) {
return 0; return 0;
} }
int surface_style_id = shading_styles.first->data().id(); 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()) { if (it != style_cache.end()) {
return &(it->second); return it->second;
} }
SurfaceStyle surface_style;
IfcSchema::IfcSurfaceStyle* style = shading_styles.first->as<IfcSchema::IfcSurfaceStyle>(); IfcSchema::IfcSurfaceStyle* style = shading_styles.first->as<IfcSchema::IfcSurfaceStyle>();
IfcSchema::IfcSurfaceStyleShading* shading = shading_styles.second->as<IfcSchema::IfcSurfaceStyleShading>(); IfcSchema::IfcSurfaceStyleShading* shading = shading_styles.second->as<IfcSchema::IfcSurfaceStyleShading>();
std::shared_ptr<SurfaceStyle> surface_style_ptr;
if (style->Name()) { if (style->Name()) {
surface_style = SurfaceStyle(surface_style_id, *style->Name()); surface_style_ptr.reset(new SurfaceStyle(surface_style_id, *style->Name()));
} else { } 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]; double rgb[3];
if (process_colour(shading->SurfaceColour(), rgb)) { if (process_colour(shading->SurfaceColour(), rgb)) {
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2])); 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); 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)); 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(); IfcSchema::IfcMaterialDefinitionRepresentation::list::ptr defs = material->HasRepresentation();
for (IfcSchema::IfcMaterialDefinitionRepresentation::list::it jt = defs->begin(); jt != defs->end(); ++jt) { for (IfcSchema::IfcMaterialDefinitionRepresentation::list::it jt = defs->begin(); jt != defs->end(); ++jt) {
IfcSchema::IfcRepresentation::list::ptr reps = (*jt)->Representations(); 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()); auto material_style = std::make_shared<IfcGeom::SurfaceStyle>(material->data().id(), material->Name());
return &(style_cache[material->data().id()] = material_style); return style_cache[material->data().id()] = material_style;
} }
+32 -1
View File
@@ -121,6 +121,11 @@ namespace IfcGeom {
size_t weld_offset_; size_t weld_offset_;
VertexKeyMap welds; 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: public:
const std::string& id() const { return id_; } const std::string& id() const { return id_; }
const std::vector<double>& verts() const { return _verts; } const std::vector<double>& verts() const { return _verts; }
@@ -144,7 +149,7 @@ namespace IfcGeom {
int surface_style_id = -1; int surface_style_id = -1;
if (iit->hasStyle()) { if (iit->hasStyle()) {
Material adapter(&iit->Style()); Material adapter(iit->StylePtr());
std::vector<Material>::const_iterator jt = std::find(_materials.begin(), _materials.end(), adapter); std::vector<Material>::const_iterator jt = std::find(_materials.begin(), _materials.end(), adapter);
if (jt == _materials.end()) { if (jt == _materials.end()) {
surface_style_id = (int)_materials.size(); surface_style_id = (int)_materials.size();
@@ -349,6 +354,32 @@ namespace IfcGeom {
BRepTools::Clean(s); 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() {} virtual ~Triangulation() {}
/// Generates UVs for a single mesh using box projection. /// 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) { bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, IfcRepresentationShapeItems& shape) {
TopoDS_Shape s; TopoDS_Shape s;
const SurfaceStyle* collective_style = get_style(l); auto collective_style = get_style(l);
if (convert_shape(l->Outer(),s) ) { 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); IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list);
if (l->declaration().is(IfcSchema::IfcFacetedBrepWithVoids::Class())) { 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 IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
bool part_success = false; bool part_success = false;
IfcSchema::IfcConnectedFaceSet::list::ptr facesets = l->FbsmFaces(); 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 ) { for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) {
TopoDS_Shape s; TopoDS_Shape s;
const SurfaceStyle* shell_style = get_style(*it); auto shell_style = get_style(*it);
if (convert_shape(*it,s)) { if (convert_shape(*it,s)) {
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, shell_style ? shell_style : collective_style)); shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, shell_style ? shell_style : collective_style));
part_success |= true; 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) { bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
aggregate_of_instance::ptr shells = l->SbsmBoundary(); 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 ) { for( aggregate_of_instance::it it = shells->begin(); it != shells->end(); ++ it ) {
TopoDS_Shape s; TopoDS_Shape s;
const SurfaceStyle* shell_style = 0; decltype(collective_style) shell_style;
if ((*it)->declaration().is(IfcSchema::IfcRepresentationItem::Class())) { if ((*it)->declaration().is(IfcSchema::IfcRepresentationItem::Class())) {
shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it); shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it);
} }
@@ -845,7 +845,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentati
} }
gtrsf.Multiply(trsf); 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(); const size_t previous_size = shapes.size();
bool b = convert_shapes(map->MappedRepresentation(), shapes); 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(); aggregate_of_instance::ptr elements = l->Elements();
if ( !elements->size() ) return false; if ( !elements->size() ) return false;
bool part_succes = 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) { for (aggregate_of_instance::it it = elements->begin(); it != elements->end(); ++it) {
auto element = *it; auto element = *it;
TopoDS_Shape s; TopoDS_Shape s;
@@ -917,7 +917,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresenta
} }
part_succes = true; part_succes = true;
const IfcGeom::SurfaceStyle* style = 0; decltype(parent_style) style = 0;
if (element->declaration().is(IfcSchema::IfcPoint::Class())) { if (element->declaration().is(IfcSchema::IfcPoint::Class())) {
style = get_style((IfcSchema::IfcPoint*) element); style = get_style((IfcSchema::IfcPoint*) element);
} }
+1 -1
View File
@@ -338,7 +338,7 @@ namespace IfcGeom {
for (; it.More(); it.Next(), ++git) { for (; it.More(); it.Next(), ++git) {
std::unique_ptr<IfcGeom::Material> adaptor; std::unique_ptr<IfcGeom::Material> adaptor;
if (git->hasStyle()) { if (git->hasStyle()) {
adaptor.reset(new Material(&git->Style())); adaptor.reset(new Material(git->StylePtr()));
} else { } else {
adaptor.reset(new Material(IfcGeom::get_default_style(elem->type()))); 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) { if (shape_type(l) != ST_SHAPELIST) {
TopoDS_Shape shp; TopoDS_Shape shp;
if (convert_shape(l, shp)) { if (convert_shape(l, shp)) {
const IfcGeom::SurfaceStyle* style = nullptr; std::shared_ptr<const IfcGeom::SurfaceStyle> style;
if (l->as<IfcSchema::IfcRepresentationItem>()) { if (l->as<IfcSchema::IfcRepresentationItem>()) {
style = get_style(l->as<IfcSchema::IfcRepresentationItem>()); style = get_style(l->as<IfcSchema::IfcRepresentationItem>());
} }
+6 -5
View File
@@ -31,13 +31,13 @@ namespace IfcGeom {
int id; int id;
gp_GTrsf placement; gp_GTrsf placement;
TopoDS_Shape shape; TopoDS_Shape shape;
const SurfaceStyle* style; std::shared_ptr<const SurfaceStyle> style;
public: 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) {} : id(id), placement(placement), shape(shape), style(style) {}
IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape) IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape)
: id(id), placement(placement), shape(shape), style(0) {} : 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) {} : id(id), shape(shape), style(style) {}
IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape) IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape)
: id(id), shape(shape), style(0) {} : id(id), shape(shape), style(0) {}
@@ -45,9 +45,10 @@ namespace IfcGeom {
void prepend(const gp_GTrsf& trsf) { placement.PreMultiply(trsf); } void prepend(const gp_GTrsf& trsf) { placement.PreMultiply(trsf); }
const TopoDS_Shape& Shape() const { return shape; } const TopoDS_Shape& Shape() const { return shape; }
const gp_GTrsf& Placement() const { return placement; } const gp_GTrsf& Placement() const { return placement; }
bool hasStyle() const { return style != 0; } bool hasStyle() const { return !!style; }
const SurfaceStyle& Style() 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; } int ItemId() const { return id; }
}; };
typedef std::vector<IfcRepresentationShapeItem> IfcRepresentationShapeItems; typedef std::vector<IfcRepresentationShapeItem> IfcRepresentationShapeItems;
@@ -137,6 +137,8 @@ namespace IfcGeom {
const Element* get_object(int id) { return implementation_->get_object(id); } const Element* get_object(int id) { return implementation_->get_object(id); }
IfcUtil::IfcBaseClass* create() { return implementation_->create(); } IfcUtil::IfcBaseClass* create() { return implementation_->create(); }
void set_cache(HdfSerializer* cache) { return implementation_->set_cache(cache); }
}; };
} }
@@ -20,16 +20,23 @@
#include "IfcGeomMaterial.h" #include "IfcGeomMaterial.h"
static double black[3] = {0.,0.,0.}; static double black[3] = {0.,0.,0.};
static const std::string no_name = "";
IfcGeom::Material::Material(const IfcGeom::SurfaceStyle* style) : style(style) {} IfcGeom::Material::Material() {}
bool IfcGeom::Material::hasDiffuse() const { return style->Diffuse() ? true : false; } IfcGeom::Material::Material(const std::shared_ptr<const IfcGeom::SurfaceStyle>& style) : style(style) {}
bool IfcGeom::Material::hasSpecular() const { return style->Specular() ? true : false; }
bool IfcGeom::Material::hasTransparency() const { return style->Transparency() ? true : false; } bool IfcGeom::Material::hasDiffuse() const { return style && style->Diffuse() ? true : false; }
bool IfcGeom::Material::hasSpecularity() const { return style->Specularity() ? 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::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; } 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::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; }
double IfcGeom::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); 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::name() const { return style ? style->Name() : no_name; }
const std::string &IfcGeom::Material::original_name() const { return style->original_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; } 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 { class IFC_GEOM_API Material {
private: private:
const IfcGeom::SurfaceStyle* style; std::shared_ptr<const IfcGeom::SurfaceStyle> style;
public: public:
explicit Material(const IfcGeom::SurfaceStyle* style = 0); // TODO default constructor for vector? Material();
// Material(const Material& other); explicit Material(const std::shared_ptr<const IfcGeom::SurfaceStyle>&);
// Material& operator=(const Material& other);
bool hasDiffuse() const; bool hasDiffuse() const;
bool hasSpecular() const; bool hasSpecular() const;
bool hasTransparency() const; bool hasTransparency() const;
@@ -44,6 +44,8 @@ namespace IfcGeom {
const std::string &name() const; const std::string &name() const;
const std::string &original_name() const; const std::string &original_name() const;
bool operator==(const Material& other) 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; } 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); IFC_GEOM_API SurfaceStyle& update_default_style(const std::string& ifc_type);
@@ -4,6 +4,7 @@
#include "../ifcgeom_schema_agnostic/IfcGeomFilter.h" #include "../ifcgeom_schema_agnostic/IfcGeomFilter.h"
#include "../ifcparse/IfcFile.h" #include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h" #include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../serializers/HdfSerializer.h"
#include <gp_XYZ.hxx> #include <gp_XYZ.hxx>
@@ -34,7 +35,11 @@ IteratorFactoryImplementation& iterator_implementations();
namespace IfcGeom { namespace IfcGeom {
class IteratorImplementation { class IteratorImplementation {
protected:
HdfSerializer* cache_ = nullptr;
public: public:
void set_cache(HdfSerializer* cache) { cache_ = cache; }
virtual bool initialize() = 0; virtual bool initialize() = 0;
virtual void compute_bounds(bool with_geometry) = 0; virtual void compute_bounds(bool with_geometry) = 0;
virtual const gp_XYZ& bounds_min() const = 0; virtual const gp_XYZ& bounds_min() const = 0;
+41 -50
View File
@@ -8,48 +8,48 @@
namespace pt = boost::property_tree; namespace pt = boost::property_tree;
static std::map<std::string, IfcGeom::SurfaceStyle> default_materials; static std::map<std::string, std::shared_ptr<IfcGeom::SurfaceStyle>> default_materials;
static IfcGeom::SurfaceStyle default_material; static std::shared_ptr<IfcGeom::SurfaceStyle> default_material;
static bool default_materials_initialized = false; static bool default_materials_initialized = false;
void InitDefaultMaterials() { void InitDefaultMaterials() {
default_materials.insert(std::make_pair("IfcSite", IfcGeom::SurfaceStyle("IfcSite"))); 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["IfcSite"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.65));
default_materials.insert(std::make_pair("IfcSlab", IfcGeom::SurfaceStyle("IfcSlab"))); 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["IfcSlab"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.4, 0.4, 0.4));
default_materials.insert(std::make_pair("IfcWallStandardCase", IfcGeom::SurfaceStyle("IfcWallStandardCase"))); 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["IfcWallStandardCase"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9, 0.9, 0.9));
default_materials.insert(std::make_pair("IfcWall", IfcGeom::SurfaceStyle("IfcWall"))); 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["IfcWall"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9, 0.9, 0.9));
default_materials.insert(std::make_pair("IfcWindow", IfcGeom::SurfaceStyle("IfcWindow"))); 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"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.75));
default_materials["IfcWindow"].Transparency().reset(0.3); default_materials["IfcWindow"]->Transparency().reset(0.3);
default_materials.insert(std::make_pair("IfcDoor", IfcGeom::SurfaceStyle("IfcDoor"))); 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["IfcDoor"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.55, 0.3, 0.15));
default_materials.insert(std::make_pair("IfcBeam", IfcGeom::SurfaceStyle("IfcBeam"))); 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["IfcBeam"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.7, 0.7));
default_materials.insert(std::make_pair("IfcRailing", IfcGeom::SurfaceStyle("IfcRailing"))); 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["IfcRailing"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6));
default_materials.insert(std::make_pair("IfcMember", IfcGeom::SurfaceStyle("IfcMember"))); 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["IfcMember"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6));
default_materials.insert(std::make_pair("IfcPlate", IfcGeom::SurfaceStyle("IfcPlate"))); 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["IfcPlate"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.8, 0.8, 0.8));
default_materials.insert(std::make_pair("IfcSpace", IfcGeom::SurfaceStyle("IfcSpace"))); 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"]->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.75, 0.8));
default_materials["IfcWindow"].Transparency().reset(0.8); default_materials["IfcWindow"]->Transparency().reset(0.8);
default_material = IfcGeom::SurfaceStyle("DefaultMaterial"); default_material = std::make_shared<IfcGeom::SurfaceStyle>("DefaultMaterial");
default_material.Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.7, 0.7, 0.7)); default_material->Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.7, 0.7, 0.7));
default_materials_initialized = true; 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) { for (pt::ptree::value_type &material_pair : root) {
std::string name = material_pair.first; 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; pt::ptree material = material_pair.second;
boost::optional<pt::ptree&> diffuse = material.get_child_optional("diffuse"); 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"); 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")) { 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")) { 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. // 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()) { if (it != default_materials.end()) {
IfcGeom::SurfaceStyle star = it->second; default_material = it->second;
default_material.Diffuse() = star.Diffuse();
default_material.Specular() = star.Specular();
default_material.Specularity() = star.Specularity();
default_material.Transparency() = star.Transparency();
default_materials.erase(it); 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; static std::mutex m;
std::lock_guard<std::mutex> lk(m); std::lock_guard<std::mutex> lk(m);
if (!default_materials_initialized) InitDefaultMaterials(); 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()) { if (it == default_materials.end()) {
default_materials.insert(std::make_pair(s, IfcGeom::SurfaceStyle(s))); default_materials.insert(std::make_pair(s, default_material));
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();
it = default_materials.find(s); it = default_materials.find(s);
} }
const IfcGeom::SurfaceStyle& surface_style = it->second; return it->second;
return &surface_style;
} }
IfcGeom::SurfaceStyle& IfcGeom::update_default_style(const std::string& s) { IfcGeom::SurfaceStyle& IfcGeom::update_default_style(const std::string& s) {
if (!default_materials_initialized) InitDefaultMaterials(); 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()) { if (it == default_materials.end()) {
throw std::runtime_error("No style registered for " + s); 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 #define GEOMETRYSERIALIZER_H
#include "../serializers/Serializer.h" #include "../serializers/Serializer.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h"
#include "../ifcgeom/IfcGeomElement.h" #include "../ifcgeom/IfcGeomElement.h"
class SerializerSettings : public IfcGeom::IteratorSettings class SerializerSettings : public IfcGeom::IteratorSettings
+559 -71
View File
@@ -25,106 +25,594 @@
#include "../ifcparse/utils.h" #include "../ifcparse/utils.h"
#include <BRepTools_ShapeSet.hxx>
#include <BinTools_ShapeSet.hxx>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <iomanip> #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) HdfSerializer::HdfSerializer(const std::string& hdf_filename, const SerializerSettings& settings)
: GeometrySerializer(settings) : GeometrySerializer(settings)
, hdf_filename(hdf_filename) , hdf_filename(hdf_filename)
, DATASET_NAME_POSITIONS("Positions") , settings_(settings)
, DATASET_NAME_NORMALS("Normals")
, DATASET_NAME_INDICES("Indices")
, DATASET_NAME_OCCT("OCCT Text")
{ {
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() { bool HdfSerializer::ready() {
//todo: check whether the file exists
return true; return true;
} }
void HdfSerializer::writeHeader() { 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) { 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; std::list<std::string> brep_strings;
H5::DataSet positionsDataset; size_t num_parts = std::distance(o->geometry().begin(), o->geometry().end());
H5::DataSet normalsDataset; brep_element* parts = new brep_element[num_parts];
H5::DataSet indicesDataset; 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; brep_strings.emplace_back();
H5::DataSet OCCTDataset; write_shape(it->Shape(), brep_strings.back());
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);
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 #endif
+66 -9
View File
@@ -17,8 +17,8 @@
* * * *
********************************************************************************/ ********************************************************************************/
#ifndef HdfSERIALIZER_H #ifndef HDFSERIALIZER_H
#define HdfSERIALIZER_H #define HDFSERIALIZER_H
#ifdef WITH_HDF5 #ifdef WITH_HDF5
@@ -30,32 +30,89 @@
#include "../serializers/GeometrySerializer.h" #include "../serializers/GeometrySerializer.h"
#define USE_BINARY
class HdfSerializer : public GeometrySerializer { class HdfSerializer : public GeometrySerializer {
public:
enum read_type { READ_BREP, READ_TRIANGULATION };
private: private:
const std::string hdf_filename; const std::string hdf_filename;
unsigned int vcount_total; unsigned int vcount_total;
H5::H5File file; H5::H5File file;
std::set<std::string> guids; SerializerSettings settings_;
const H5std_string DATASET_NAME_POSITIONS;
const H5std_string DATASET_NAME_NORMALS; static const H5std_string DATASET_NAME_POSITIONS;
const H5std_string DATASET_NAME_INDICES; static const H5std_string DATASET_NAME_UVCOORDS;
const H5std_string DATASET_NAME_OCCT; 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: public:
HdfSerializer(const std::string& hdf_filename, const SerializerSettings& settings); HdfSerializer(const std::string& hdf_filename, const SerializerSettings& settings);
virtual ~HdfSerializer() {} virtual ~HdfSerializer() {}
bool ready(); bool ready();
void writeHeader(); void writeHeader();
H5::Group write(const IfcGeom::Element* o);
void write(const IfcGeom::BRepElement* 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() {} void finalize() {}
bool isTesselated() const { return false; } bool isTesselated() const { return false; }
void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {} void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {}
void setFile(IfcParse::IfcFile*) {} 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
#endif #endif
+2
View File
@@ -19,6 +19,8 @@
* * * *
********************************************************************************/ ********************************************************************************/
#include "../ifcgeom_schema_agnostic/Kernel.h"
#include <string> #include <string>
#include <fstream> #include <fstream>
#include <cstdio> #include <cstdio>