From 3bdf429c307c3156964b599f03aa399d1c93f69f Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 12 Jan 2018 12:39:39 +0100 Subject: [PATCH] Correct bounding boxes on LOD case --- src/hdf5_usecases/lod.cpp | 76 ++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/src/hdf5_usecases/lod.cpp b/src/hdf5_usecases/lod.cpp index b72ead68dc..26fcb6fcd0 100644 --- a/src/hdf5_usecases/lod.cpp +++ b/src/hdf5_usecases/lod.cpp @@ -23,6 +23,10 @@ #include #include +#include +#include +#include +#include #include @@ -32,6 +36,11 @@ void generate_bounding_boxes(IfcParse::IfcFile& f, const std::string& fn) { IfcGeom::Kernel kernel; auto unit_factor = kernel.initializeUnits(*f.entitiesByType()->begin()); + IfcGeom::IteratorSettings settings; + settings.convert_back_units() = true; + settings.disable_triangulation() = true; + settings.disable_opening_subtractions() = true; + IfcSchema::IfcProductDefinitionShape::list::ptr defs_ = f.entitiesByType(); std::vector defs(defs_->begin(), defs_->end()); // Make sure to sort by id to have new definitions lining up in the same order @@ -45,21 +54,60 @@ void generate_bounding_boxes(IfcParse::IfcFile& f, const std::string& fn) { std::cerr << "boxes:" << std::endl; - std::for_each(defs.begin(), defs.end(), [&kernel, &str, N, &n, &unit_factor](IfcSchema::IfcProductDefinitionShape* def) { - Bnd_Box box; - auto reps = def->Representations(); - IfcSchema::IfcRepresentationContext* context; + // In newer versions of IfcOpenShell this is a method Kernel::apply_transformation() + auto apply_transformation = [](const TopoDS_Shape& s, const gp_GTrsf& gt) { + if (gt.Form() == gp_Other) { + return BRepBuilderAPI_GTransform(s, gt, true).Shape(); + } + gp_Trsf t = gt.Trsf(); + if (t.Form() == gp_Identity) { + return s; + } else { + /// @todo set to 1. and exactly 1. or use epsilon? + if (t.ScaleFactor() != 1.) { + return BRepBuilderAPI_Transform(s, t, true).Shape(); + } else { + return s.Moved(t); + } + } + }; - std::for_each(reps->begin(), reps->end(), [&kernel, &box, &context](auto rep) { - IfcGeom::IfcRepresentationShapeItems items; + // In newer versions of IfcOpenShell this is a method BRep::as_compound() + auto brep_as_compound = [&apply_transformation](const IfcGeom::Representation::BRep& brep) { + TopoDS_Compound compound; + BRep_Builder builder; + builder.MakeCompound(compound); + for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++it) { + const TopoDS_Shape& s = it->Shape(); + gp_GTrsf trsf = it->Placement(); - if (rep->RepresentationIdentifier() == "Body") { - kernel.convert(rep, items); - context = rep->ContextOfItems(); + if (brep.settings().convert_back_units()) { + gp_Trsf scale; + scale.SetScaleFactor(1.0 / brep.settings().unit_magnitude()); + trsf.PreMultiply(scale); } - for (auto& i : items) { - BRepBndLib::AddClose(i.Shape(), box); + const TopoDS_Shape moved_shape = apply_transformation(s, trsf); + builder.Add(compound, moved_shape); + } + return compound; + }; + + std::for_each(defs.begin(), defs.end(), [&kernel, &brep_as_compound, &str, N, &n, &settings](IfcSchema::IfcProductDefinitionShape* def) { + Bnd_Box box; + + auto prods = def->data().getInverse(IfcSchema::Type::IfcProduct, -1)->as(); + if (prods->size() != 1) return; + + IfcSchema::IfcProduct* prod = *prods->begin(); + + auto reps = def->Representations(); + + std::for_each(reps->begin(), reps->end(), [&kernel, &brep_as_compound, &settings, &box, prod](auto rep) { + if (rep->RepresentationIdentifier() == "Body") { + IfcGeom::BRepElement* elem = kernel.create_brep_for_representation_and_product(settings, rep, prod); + BRepBndLib::AddClose(brep_as_compound(elem->geometry()), box); + delete elem; } }); @@ -68,10 +116,6 @@ void generate_bounding_boxes(IfcParse::IfcFile& f, const std::string& fn) { double xyz[6]; box.Get(xyz[0], xyz[1], xyz[2], xyz[3], xyz[4], xyz[5]); - for (int i = 0; i < 6; ++i) { - xyz[i] *= unit_factor.second; - } - str.write((char*)&name, sizeof(size_t)); str.write((char*)xyz, sizeof(double) * 6); @@ -304,7 +348,7 @@ int main(int argc, char** argv) { double xyz[6]; str.read((char*)&name, sizeof(size_t)); - str.read((char*)xyz, sizeof(size_t)); + str.read((char*)xyz, sizeof(double) * 6); IfcSchema::IfcCartesianPoint* corner = new IfcSchema::IfcCartesianPoint(std::vector{xyz[0], xyz[1], xyz[2]});; IfcSchema::IfcBoundingBox* bbox = new IfcSchema::IfcBoundingBox(corner, xyz[3] - xyz[0], xyz[4] - xyz[1], xyz[5] - xyz[2]);