mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Geometry caching
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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())));
|
||||
}
|
||||
|
||||
@@ -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>());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "../ifcgeom_schema_agnostic/Kernel.h"
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
|
||||
Reference in New Issue
Block a user