2017-11-24 15:20:21 +01:00
|
|
|
/********************************************************************************
|
|
|
|
|
* *
|
|
|
|
|
* This file is part of IfcOpenShell. *
|
|
|
|
|
* *
|
|
|
|
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
|
|
|
|
* it under the terms of the Lesser GNU General Public License as published by *
|
|
|
|
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
|
|
|
|
* (at your option) any later version. *
|
|
|
|
|
* *
|
|
|
|
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
|
* Lesser GNU General Public License for more details. *
|
|
|
|
|
* *
|
|
|
|
|
* You should have received a copy of the Lesser GNU General Public License *
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
|
|
|
* *
|
|
|
|
|
********************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "../../../src/ifcparse/IfcHdf5File.h"
|
|
|
|
|
#include "../../../src/ifcgeom/IfcGeom.h"
|
2017-11-25 09:47:42 +01:00
|
|
|
#include "../../../src/ifcparse/IfcWritableEntity.h"
|
2017-11-24 15:20:21 +01:00
|
|
|
|
|
|
|
|
#include <Bnd_Box.hxx>
|
|
|
|
|
#include <BRepBndLib.hxx>
|
|
|
|
|
|
2017-11-25 09:47:42 +01:00
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
#include "multifile_instance_locator.h"
|
|
|
|
|
|
2017-11-24 15:20:21 +01:00
|
|
|
int main(int, char** argv) {
|
|
|
|
|
IfcParse::IfcFile f;
|
|
|
|
|
f.Init(argv[1]);
|
|
|
|
|
|
2017-11-25 09:47:42 +01:00
|
|
|
IfcSchema::IfcProductDefinitionShape::list::ptr defs_ = f.entitiesByType<IfcSchema::IfcProductDefinitionShape>();
|
|
|
|
|
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
|
|
|
|
|
std::sort(defs.begin(), defs.end(), [](IfcSchema::IfcProductDefinitionShape* a, IfcSchema::IfcProductDefinitionShape* b) {
|
|
|
|
|
return a->data().id() < b->data().id();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
IfcSchema::IfcStyledItem::list::ptr styles = f.entitiesByType<IfcSchema::IfcStyledItem>();
|
2017-11-24 15:20:21 +01:00
|
|
|
|
|
|
|
|
IfcGeom::Kernel kernel;
|
|
|
|
|
kernel.initializeUnits(*f.entitiesByType<IfcSchema::IfcUnitAssignment>()->begin());
|
|
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
/*
|
|
|
|
|
|
2017-11-25 09:47:42 +01:00
|
|
|
std::set<IfcSchema::Type::Enum> geometric_types{ IfcSchema::Type::IfcStyledItem };
|
|
|
|
|
std::set<IfcSchema::Type::Enum> other_types;
|
|
|
|
|
|
|
|
|
|
std::set<IfcUtil::IfcBaseClass*> geometric_instances;
|
|
|
|
|
|
|
|
|
|
std::for_each(styles->begin(), styles->end(), [&geometric_instances](IfcSchema::IfcStyledItem* style) {
|
|
|
|
|
geometric_instances.insert(style);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
int N = defs.size();
|
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
|
|
std::for_each(defs.begin(), defs.end(), [&f, &geometric_types, &geometric_instances, N, &n](IfcSchema::IfcProductDefinitionShape* def) {
|
|
|
|
|
auto refs = f.traverse(def);
|
|
|
|
|
geometric_instances.insert(refs->begin(), refs->end());
|
|
|
|
|
std::for_each(refs->begin(), refs->end(), [&geometric_types](IfcUtil::IfcBaseClass* inst) {
|
|
|
|
|
geometric_types.insert(inst->declaration().type());
|
|
|
|
|
});
|
|
|
|
|
if (n++ % 1000 == 0) {
|
|
|
|
|
std::cerr << "\r" << n * 100 / N << std::flush;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
std::function<void(IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*)> fn;
|
|
|
|
|
fn = [&f, &geometric_instances, &other_types, &fn](IfcUtil::IfcBaseClass* root, IfcUtil::IfcBaseClass* inst) {
|
|
|
|
|
if (geometric_instances.find(inst) == geometric_instances.end()) {
|
|
|
|
|
if (inst->declaration().type() == IfcSchema::Type::IfcCircle) {
|
|
|
|
|
std::cerr << "circle reached by " << root->data().toString() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
other_types.insert(inst->declaration().type());
|
|
|
|
|
auto refs = f.traverse(inst, 1);
|
|
|
|
|
std::for_each(refs->begin() + 1, refs->end(), [&fn, root](IfcUtil::IfcBaseClass* inst) {
|
|
|
|
|
fn(root, inst);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
N = std::distance(f.begin(), f.end());
|
|
|
|
|
n = 0;
|
|
|
|
|
|
|
|
|
|
std::for_each(f.begin(), f.end(), [&fn, N, &n](const auto& pair) {
|
|
|
|
|
fn(pair.second, pair.second);
|
|
|
|
|
if (n++ % 1000 == 0) {
|
|
|
|
|
std::cerr << "\r" << n * 100 / N << std::flush;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
std::set<IfcSchema::Type::Enum> only_geometric;
|
|
|
|
|
std::set_difference(geometric_types.begin(), geometric_types.end(),
|
|
|
|
|
other_types.begin(), other_types.end(),
|
|
|
|
|
std::inserter(only_geometric, only_geometric.begin()));
|
|
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
std::cerr << "\nOnly geometric:" << std::endl;
|
|
|
|
|
|
2017-11-25 09:47:42 +01:00
|
|
|
for (auto ty : only_geometric) {
|
|
|
|
|
std::cerr << IfcSchema::Type::ToString(ty) << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
std::set<IfcSchema::Type::Enum> only_geometric{
|
|
|
|
|
IfcSchema::Type::IfcAxis2Placement2D ,
|
|
|
|
|
IfcSchema::Type::IfcCartesianTransformationOperator3D,
|
|
|
|
|
IfcSchema::Type::IfcCircleProfileDef ,
|
|
|
|
|
IfcSchema::Type::IfcClosedShell ,
|
|
|
|
|
IfcSchema::Type::IfcConnectedFaceSet ,
|
|
|
|
|
IfcSchema::Type::IfcExtrudedAreaSolid ,
|
|
|
|
|
IfcSchema::Type::IfcFace ,
|
|
|
|
|
IfcSchema::Type::IfcFaceBasedSurfaceModel ,
|
|
|
|
|
IfcSchema::Type::IfcFaceBound ,
|
|
|
|
|
IfcSchema::Type::IfcFaceOuterBound ,
|
|
|
|
|
IfcSchema::Type::IfcFacetedBrep ,
|
|
|
|
|
//IfcSchema::Type::IfcGeometricRepresentationContext ,
|
|
|
|
|
IfcSchema::Type::IfcMappedItem ,
|
|
|
|
|
IfcSchema::Type::IfcPolyLoop ,
|
|
|
|
|
IfcSchema::Type::IfcProductDefinitionShape ,
|
|
|
|
|
IfcSchema::Type::IfcRepresentationMap ,
|
|
|
|
|
IfcSchema::Type::IfcShapeRepresentation ,
|
|
|
|
|
IfcSchema::Type::IfcStyledItem
|
|
|
|
|
};
|
2017-11-25 09:47:42 +01:00
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
std::vector<IfcUtil::IfcBaseClass*> new_defs, old_defs, old_geom_defs, all_old_defs, all_defs;
|
2017-11-25 09:47:42 +01:00
|
|
|
|
|
|
|
|
std::for_each(only_geometric.begin(), only_geometric.end(), [&f, &old_geom_defs](IfcSchema::Type::Enum t) {
|
|
|
|
|
auto insts = f.entitiesByType(t);
|
|
|
|
|
std::for_each(insts->begin(), insts->end(), [t, &old_geom_defs](IfcUtil::IfcBaseClass* inst) {
|
|
|
|
|
if (inst->declaration().type() == t) {
|
|
|
|
|
old_geom_defs.push_back(inst);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
std::for_each(f.begin(), f.end(), [&only_geometric, &old_defs](const auto& pair) {
|
2017-11-25 09:47:42 +01:00
|
|
|
IfcUtil::IfcBaseClass* inst = pair.second;
|
|
|
|
|
auto ty = inst->declaration().type();
|
|
|
|
|
if (only_geometric.find(ty) == only_geometric.end()) {
|
|
|
|
|
old_defs.push_back(inst);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
auto id = f.FreshId();
|
|
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
int num_points_added = 0;
|
|
|
|
|
|
|
|
|
|
std::for_each(defs.begin(), defs.end(), [&kernel, &id, &old_defs, &new_defs, &num_points_added](IfcSchema::IfcProductDefinitionShape* def) {
|
2017-11-24 15:20:21 +01:00
|
|
|
Bnd_Box box;
|
|
|
|
|
auto reps = def->Representations();
|
|
|
|
|
IfcSchema::IfcRepresentationContext* context;
|
|
|
|
|
|
|
|
|
|
std::for_each(reps->begin(), reps->end(), [&kernel, &box, &context](auto rep) {
|
|
|
|
|
IfcGeom::IfcRepresentationShapeItems items;
|
|
|
|
|
|
|
|
|
|
if (rep->RepresentationIdentifier() == "Body") {
|
2017-12-01 15:38:28 +01:00
|
|
|
// kernel.convert(rep, items);
|
2017-11-24 15:20:21 +01:00
|
|
|
context = rep->ContextOfItems();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& i : items) {
|
|
|
|
|
BRepBndLib::AddClose(i.Shape(), box);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
box.Add(gp_Pnt(0, 0, 0));
|
|
|
|
|
|
2017-11-24 15:20:21 +01:00
|
|
|
double x1, y1, z1, x2, y2, z2;
|
|
|
|
|
box.Get(x1, y1, z1, x2, y2, z2);
|
|
|
|
|
|
|
|
|
|
IfcSchema::IfcCartesianPoint* corner = new IfcSchema::IfcCartesianPoint(std::vector<double>{x1, y1, z1});;
|
|
|
|
|
IfcSchema::IfcBoundingBox* bbox = new IfcSchema::IfcBoundingBox(corner, x2-x1, y2-y1, z2-z1);
|
|
|
|
|
IfcSchema::IfcRepresentationItem::list::ptr items(new IfcSchema::IfcRepresentationItem::list);
|
|
|
|
|
items->push(bbox);
|
|
|
|
|
|
|
|
|
|
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(context, std::string("Body"), std::string("BoundingBox"), items);
|
|
|
|
|
IfcSchema::IfcRepresentation::list::ptr new_reps(new IfcSchema::IfcRepresentation::list);
|
|
|
|
|
new_reps->push(rep);
|
|
|
|
|
|
|
|
|
|
IfcSchema::IfcProductDefinitionShape* new_def = new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, new_reps);
|
2017-11-25 09:47:42 +01:00
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
corner->data().isWritable()->setId(id++);
|
2017-11-25 09:47:42 +01:00
|
|
|
|
|
|
|
|
// NB: Corner is added to existing definitions
|
2017-12-01 15:38:28 +01:00
|
|
|
old_defs.push_back(corner); ++num_points_added;
|
2017-11-25 09:47:42 +01:00
|
|
|
new_defs.push_back(bbox);
|
|
|
|
|
new_defs.push_back(rep);
|
|
|
|
|
new_defs.push_back(new_def);
|
|
|
|
|
|
2017-11-24 15:20:21 +01:00
|
|
|
return new_def;
|
|
|
|
|
});
|
2017-11-25 09:47:42 +01:00
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
std::for_each(new_defs.begin(), new_defs.end(), [&id](auto new_def) {
|
|
|
|
|
new_def->data().isWritable()->setId(id++);
|
|
|
|
|
});
|
|
|
|
|
|
2017-11-25 09:47:42 +01:00
|
|
|
auto iden = [](IfcUtil::IfcBaseClass* inst) { return inst; };
|
|
|
|
|
|
|
|
|
|
std::set<IfcSchema::Type::Enum> old_new_geom_types;
|
|
|
|
|
|
|
|
|
|
std::vector<std::vector<IfcUtil::IfcBaseClass*>*> all_vectors = std::vector<std::vector<IfcUtil::IfcBaseClass*>*>{ &new_defs, &old_defs, &old_geom_defs };
|
|
|
|
|
for (auto vec_ : all_vectors) {
|
|
|
|
|
auto& vec = *vec_;
|
|
|
|
|
for (auto& inst : vec) {
|
|
|
|
|
old_new_geom_types.insert(inst->declaration().type());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
all_old_defs.insert(all_old_defs.end(), old_defs.begin(), old_defs.end());
|
|
|
|
|
all_old_defs.insert(all_old_defs.end(), old_geom_defs.begin(), old_geom_defs.end());
|
2017-12-01 15:38:28 +01:00
|
|
|
all_defs.insert(all_defs.end(), all_old_defs.begin(), all_old_defs.end());
|
|
|
|
|
all_defs.insert(all_defs.end(), new_defs.begin(), new_defs.end());
|
2017-11-25 09:47:42 +01:00
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
{
|
|
|
|
|
int num_insts1 = std::distance(all_old_defs.begin(), all_old_defs.end());
|
|
|
|
|
int num_insts2 = std::distance(f.begin(), f.end());
|
|
|
|
|
if ((num_insts1 - num_points_added) != num_insts2) {
|
|
|
|
|
std::cerr << "Missign instances " << num_insts1 << " - " << num_points_added << " != " << num_insts2 << std::endl;
|
|
|
|
|
abort();
|
|
|
|
|
}
|
2017-11-25 09:47:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
multifile_instance_locator* locator = new multifile_instance_locator(
|
|
|
|
|
old_new_geom_types.begin(), old_new_geom_types.end(),
|
|
|
|
|
all_old_defs.begin(), all_old_defs.end());
|
|
|
|
|
|
|
|
|
|
IfcParse::Hdf5Settings settings;
|
2017-12-01 15:38:28 +01:00
|
|
|
settings.profile() = IfcParse::Hdf5Settings::padded;
|
|
|
|
|
settings.compress() = true;
|
|
|
|
|
|
|
|
|
|
H5::H5File hdf(argv[1] + std::string(".hdf"), H5F_ACC_TRUNC);
|
|
|
|
|
H5::H5File geom_hdf(argv[1] + std::string("-geometry.hdf"), H5F_ACC_TRUNC);
|
|
|
|
|
H5::H5File box_hdf(argv[1] + std::string("-bounding-boxes.hdf"), H5F_ACC_TRUNC);
|
|
|
|
|
|
|
|
|
|
hdf.createGroup("geometry").close();
|
|
|
|
|
hdf.createGroup("bounding-boxes").close();
|
|
|
|
|
|
|
|
|
|
hdf.mount("geometry", geom_hdf, H5::PropList::DEFAULT);
|
|
|
|
|
hdf.mount("bounding-boxes", box_hdf, H5::PropList::DEFAULT);
|
2017-11-25 09:47:42 +01:00
|
|
|
|
2017-12-01 15:38:28 +01:00
|
|
|
H5::Group main_population = hdf.createGroup("population");
|
|
|
|
|
H5::Group geom_population = hdf.createGroup("geometry/population");
|
|
|
|
|
H5::Group box_population = hdf.createGroup("bounding-boxes/population");
|
2017-11-25 09:47:42 +01:00
|
|
|
|
|
|
|
|
{
|
2017-12-01 15:38:28 +01:00
|
|
|
IfcParse::IfcHdf5File ifc_hdf5(hdf, get_schema(), settings);
|
|
|
|
|
IfcParse::instance_categorizer categorizer(all_defs.begin(), all_defs.end());
|
|
|
|
|
ifc_hdf5.write_schema(&categorizer);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
IfcParse::instance_enumerator enumerator(&f.header(), old_defs.begin(), old_defs.end());
|
|
|
|
|
ifc_hdf5.write_population(main_population, enumerator, locator);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
IfcParse::instance_enumerator enumerator(&f.header(), old_geom_defs.begin(), old_geom_defs.end());
|
|
|
|
|
ifc_hdf5.write_population(geom_population, enumerator, locator);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-24 15:20:21 +01:00
|
|
|
}
|