mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 08:12:30 +00:00
Correct bounding boxes on LOD case
This commit is contained in:
+60
-16
@@ -23,6 +23,10 @@
|
|||||||
|
|
||||||
#include <Bnd_Box.hxx>
|
#include <Bnd_Box.hxx>
|
||||||
#include <BRepBndLib.hxx>
|
#include <BRepBndLib.hxx>
|
||||||
|
#include <BRep_Builder.hxx>
|
||||||
|
#include <TopoDS_Compound.hxx>
|
||||||
|
#include <BRepBuilderAPI_Transform.hxx>
|
||||||
|
#include <BRepBuilderAPI_GTransform.hxx>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -32,6 +36,11 @@ void generate_bounding_boxes(IfcParse::IfcFile& f, const std::string& fn) {
|
|||||||
IfcGeom::Kernel kernel;
|
IfcGeom::Kernel kernel;
|
||||||
auto unit_factor = kernel.initializeUnits(*f.entitiesByType<IfcSchema::IfcUnitAssignment>()->begin());
|
auto unit_factor = kernel.initializeUnits(*f.entitiesByType<IfcSchema::IfcUnitAssignment>()->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<IfcSchema::IfcProductDefinitionShape>();
|
IfcSchema::IfcProductDefinitionShape::list::ptr defs_ = f.entitiesByType<IfcSchema::IfcProductDefinitionShape>();
|
||||||
std::vector<IfcSchema::IfcProductDefinitionShape*> defs(defs_->begin(), defs_->end());
|
std::vector<IfcSchema::IfcProductDefinitionShape*> defs(defs_->begin(), defs_->end());
|
||||||
// Make sure to sort by id to have new definitions lining up in the same order
|
// 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::cerr << "boxes:" << std::endl;
|
||||||
|
|
||||||
std::for_each(defs.begin(), defs.end(), [&kernel, &str, N, &n, &unit_factor](IfcSchema::IfcProductDefinitionShape* def) {
|
// In newer versions of IfcOpenShell this is a method Kernel::apply_transformation()
|
||||||
Bnd_Box box;
|
auto apply_transformation = [](const TopoDS_Shape& s, const gp_GTrsf& gt) {
|
||||||
auto reps = def->Representations();
|
if (gt.Form() == gp_Other) {
|
||||||
IfcSchema::IfcRepresentationContext* context;
|
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) {
|
// In newer versions of IfcOpenShell this is a method BRep::as_compound()
|
||||||
IfcGeom::IfcRepresentationShapeItems items;
|
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") {
|
if (brep.settings().convert_back_units()) {
|
||||||
kernel.convert(rep, items);
|
gp_Trsf scale;
|
||||||
context = rep->ContextOfItems();
|
scale.SetScaleFactor(1.0 / brep.settings().unit_magnitude());
|
||||||
|
trsf.PreMultiply(scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& i : items) {
|
const TopoDS_Shape moved_shape = apply_transformation(s, trsf);
|
||||||
BRepBndLib::AddClose(i.Shape(), box);
|
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<IfcSchema::IfcProduct>();
|
||||||
|
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<double>* elem = kernel.create_brep_for_representation_and_product<double>(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];
|
double xyz[6];
|
||||||
box.Get(xyz[0], xyz[1], xyz[2], xyz[3], xyz[4], xyz[5]);
|
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*)&name, sizeof(size_t));
|
||||||
str.write((char*)xyz, sizeof(double) * 6);
|
str.write((char*)xyz, sizeof(double) * 6);
|
||||||
|
|
||||||
@@ -304,7 +348,7 @@ int main(int argc, char** argv) {
|
|||||||
double xyz[6];
|
double xyz[6];
|
||||||
|
|
||||||
str.read((char*)&name, sizeof(size_t));
|
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<double>{xyz[0], xyz[1], xyz[2]});;
|
IfcSchema::IfcCartesianPoint* corner = new IfcSchema::IfcCartesianPoint(std::vector<double>{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]);
|
IfcSchema::IfcBoundingBox* bbox = new IfcSchema::IfcBoundingBox(corner, xyz[3] - xyz[0], xyz[4] - xyz[1], xyz[5] - xyz[2]);
|
||||||
|
|||||||
Reference in New Issue
Block a user