2017-12-22 13:51:11 +01:00
|
|
|
#include "Kernel.h"
|
|
|
|
|
|
2018-11-02 16:10:06 +01:00
|
|
|
#include <TopExp.hxx>
|
2018-11-03 09:59:37 +01:00
|
|
|
#include <TopTools_ListOfShape.hxx>
|
2018-12-10 12:12:23 +01:00
|
|
|
#include <TopTools_IndexedMapOfShape.hxx>
|
2018-11-02 17:01:15 +01:00
|
|
|
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
2018-11-02 16:10:06 +01:00
|
|
|
|
2022-08-30 13:31:26 +02:00
|
|
|
#include <TopoDS.hxx>
|
|
|
|
|
#include <TopoDS_Vertex.hxx>
|
|
|
|
|
#include <TopoDS_Edge.hxx>
|
|
|
|
|
|
2022-07-17 21:13:46 +02:00
|
|
|
#include <boost/preprocessor/stringize.hpp>
|
|
|
|
|
#include <boost/preprocessor/seq/for_each.hpp>
|
|
|
|
|
|
2017-12-22 13:51:11 +01:00
|
|
|
IfcGeom::Kernel::Kernel(IfcParse::IfcFile* file) {
|
|
|
|
|
if (file != 0) {
|
|
|
|
|
if (file->schema() == 0) {
|
|
|
|
|
throw IfcParse::IfcException("No schema associated with file");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string& schema_name = file->schema()->name();
|
2018-01-01 11:22:12 +01:00
|
|
|
implementation_ = impl::kernel_implementations().construct(schema_name, file);
|
2017-12-22 13:51:11 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IfcGeom::impl::KernelFactoryImplementation& IfcGeom::impl::kernel_implementations() {
|
|
|
|
|
static KernelFactoryImplementation impl;
|
|
|
|
|
return impl;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-17 21:13:46 +02:00
|
|
|
// Declares the schema-based external kernel initialization routines:
|
|
|
|
|
// - extern void init_KernelImplementation_Ifc2x3(IfcGeom::impl::KernelFactoryImplementation*);
|
|
|
|
|
// - ...
|
|
|
|
|
#define EXTERNAL_DEFS(r, data, elem) \
|
2022-07-18 10:08:46 +02:00
|
|
|
extern void BOOST_PP_CAT(init_KernelImplementation_Ifc, elem)(IfcGeom::impl::KernelFactoryImplementation*);
|
2022-07-17 21:13:46 +02:00
|
|
|
|
|
|
|
|
// Declares the schema-based external iterator initialization routines:
|
|
|
|
|
// - init_IteratorImplementation_Ifc2x3(this);
|
|
|
|
|
// - ...
|
|
|
|
|
#define CALL_DEFS(r, data, elem) \
|
2022-07-18 10:08:46 +02:00
|
|
|
BOOST_PP_CAT(init_KernelImplementation_Ifc, elem)(this);
|
2022-07-17 21:13:46 +02:00
|
|
|
|
|
|
|
|
BOOST_PP_SEQ_FOR_EACH(EXTERNAL_DEFS, , SCHEMA_SEQ)
|
2017-12-22 13:51:11 +01:00
|
|
|
|
|
|
|
|
IfcGeom::impl::KernelFactoryImplementation::KernelFactoryImplementation() {
|
2022-07-17 21:13:46 +02:00
|
|
|
BOOST_PP_SEQ_FOR_EACH(CALL_DEFS, , SCHEMA_SEQ)
|
2017-12-22 13:51:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IfcGeom::impl::KernelFactoryImplementation::bind(const std::string& schema_name, IfcGeom::impl::kernel_fn fn) {
|
|
|
|
|
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
|
|
|
|
|
this->insert(std::make_pair(schema_name_lower, fn));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IfcGeom::Kernel* IfcGeom::impl::KernelFactoryImplementation::construct(const std::string& schema_name, IfcParse::IfcFile* file) {
|
|
|
|
|
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
|
|
|
|
|
std::map<std::string, IfcGeom::impl::kernel_fn>::const_iterator it;
|
|
|
|
|
it = this->find(schema_name_lower);
|
|
|
|
|
if (it == end()) {
|
|
|
|
|
throw IfcParse::IfcException("No geometry kernel registered for " + schema_name);
|
|
|
|
|
}
|
|
|
|
|
return it->second(file);
|
|
|
|
|
}
|
2018-09-07 14:08:56 +02:00
|
|
|
|
|
|
|
|
#define CREATE_GET_DECOMPOSING_ENTITY(IfcSchema) \
|
|
|
|
|
\
|
2019-03-24 14:26:14 +01:00
|
|
|
IfcSchema::IfcObjectDefinition* get_decomposing_entity_impl(IfcSchema::IfcProduct* product, bool include_openings) {\
|
2018-09-07 14:08:56 +02:00
|
|
|
IfcSchema::IfcObjectDefinition* parent = 0; \
|
|
|
|
|
\
|
|
|
|
|
/* In case of an opening element, parent to the RelatingBuildingElement */ \
|
2019-03-24 14:26:14 +01:00
|
|
|
if (include_openings && product->declaration().is(IfcSchema::IfcOpeningElement::Class())) { \
|
2018-09-07 14:08:56 +02:00
|
|
|
IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)product; \
|
|
|
|
|
IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements(); \
|
|
|
|
|
if (voids->size()) { \
|
|
|
|
|
IfcSchema::IfcRelVoidsElement* ifc_void = *voids->begin(); \
|
|
|
|
|
parent = ifc_void->RelatingBuildingElement(); \
|
|
|
|
|
} \
|
|
|
|
|
} else if (product->declaration().is(IfcSchema::IfcElement::Class())) { \
|
|
|
|
|
IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product; \
|
|
|
|
|
IfcSchema::IfcRelFillsElement::list::ptr fills = element->FillsVoids(); \
|
|
|
|
|
/* In case of a RelatedBuildingElement parent to the opening element */ \
|
2019-03-24 14:26:14 +01:00
|
|
|
if (fills->size() && include_openings) { \
|
2018-09-07 14:08:56 +02:00
|
|
|
for (IfcSchema::IfcRelFillsElement::list::it it = fills->begin(); it != fills->end(); ++it) { \
|
|
|
|
|
IfcSchema::IfcRelFillsElement* fill = *it; \
|
|
|
|
|
IfcSchema::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement(); \
|
|
|
|
|
if (product == ifc_objectdef) continue; \
|
|
|
|
|
parent = ifc_objectdef; \
|
|
|
|
|
} \
|
|
|
|
|
} \
|
|
|
|
|
/* Else simply parent to the containing structure */ \
|
|
|
|
|
if (!parent) { \
|
|
|
|
|
IfcSchema::IfcRelContainedInSpatialStructure::list::ptr parents = element->ContainedInStructure(); \
|
|
|
|
|
if (parents->size()) { \
|
|
|
|
|
IfcSchema::IfcRelContainedInSpatialStructure* container = *parents->begin(); \
|
|
|
|
|
parent = container->RelatingStructure(); \
|
|
|
|
|
} \
|
|
|
|
|
} \
|
|
|
|
|
} \
|
|
|
|
|
\
|
|
|
|
|
/* Parent decompositions to the RelatingObject */ \
|
|
|
|
|
if (!parent) { \
|
2021-07-29 14:54:51 +02:00
|
|
|
aggregate_of_instance::ptr parents = product->data().getInverse((&IfcSchema::IfcRelAggregates::Class()), -1); \
|
2018-09-07 14:08:56 +02:00
|
|
|
parents->push(product->data().getInverse((&IfcSchema::IfcRelNests::Class()), -1)); \
|
2021-11-26 14:15:51 +01:00
|
|
|
for (aggregate_of_instance::it it = parents->begin(); it != parents->end(); ++it) { \
|
|
|
|
|
IfcSchema::IfcRelDecomposes* decompose = (*it)->as<IfcSchema::IfcRelDecomposes>(); \
|
2018-09-07 14:08:56 +02:00
|
|
|
IfcUtil::IfcBaseEntity* ifc_objectdef; \
|
|
|
|
|
\
|
|
|
|
|
ifc_objectdef = get_RelatingObject(decompose); \
|
|
|
|
|
\
|
2021-11-26 14:15:51 +01:00
|
|
|
if (!ifc_objectdef || product == ifc_objectdef) continue; \
|
2018-09-07 14:08:56 +02:00
|
|
|
parent = ifc_objectdef->as<IfcSchema::IfcObjectDefinition>(); \
|
|
|
|
|
} \
|
|
|
|
|
} \
|
|
|
|
|
return parent; \
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-17 21:13:46 +02:00
|
|
|
#define GET_RELATINGOBJECT_IFC4_VARIANT(IfcSchema) \
|
|
|
|
|
\
|
|
|
|
|
IfcUtil::IfcBaseEntity* get_RelatingObject(IfcSchema::IfcRelDecomposes* decompose) { \
|
|
|
|
|
IfcSchema::IfcRelAggregates* aggr = decompose->as<IfcSchema::IfcRelAggregates>(); \
|
|
|
|
|
if (aggr != nullptr) { \
|
|
|
|
|
return aggr->RelatingObject(); \
|
|
|
|
|
} \
|
|
|
|
|
IfcSchema::IfcRelNests* nest = decompose->as<IfcSchema::IfcRelNests>(); \
|
|
|
|
|
if (nest != nullptr) { \
|
|
|
|
|
return nest->RelatingObject(); \
|
|
|
|
|
} \
|
|
|
|
|
return nullptr; \
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-07 14:08:56 +02:00
|
|
|
namespace {
|
2021-05-11 22:29:16 +02:00
|
|
|
|
|
|
|
|
#ifdef HAS_SCHEMA_2x3
|
|
|
|
|
IfcUtil::IfcBaseEntity* get_RelatingObject(Ifc2x3::IfcRelDecomposes* decompose) {
|
|
|
|
|
return decompose->RelatingObject();
|
|
|
|
|
}
|
|
|
|
|
CREATE_GET_DECOMPOSING_ENTITY(Ifc2x3);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAS_SCHEMA_4
|
2022-07-17 21:13:46 +02:00
|
|
|
GET_RELATINGOBJECT_IFC4_VARIANT(Ifc4);
|
2021-05-11 22:29:16 +02:00
|
|
|
CREATE_GET_DECOMPOSING_ENTITY(Ifc4);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAS_SCHEMA_4x1
|
2022-07-17 21:13:46 +02:00
|
|
|
GET_RELATINGOBJECT_IFC4_VARIANT(Ifc4x1);
|
2021-05-11 22:29:16 +02:00
|
|
|
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x1);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAS_SCHEMA_4x2
|
2022-07-17 21:13:46 +02:00
|
|
|
GET_RELATINGOBJECT_IFC4_VARIANT(Ifc4x2);
|
2021-05-11 22:29:16 +02:00
|
|
|
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x2);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAS_SCHEMA_4x3_rc1
|
2022-07-17 21:13:46 +02:00
|
|
|
GET_RELATINGOBJECT_IFC4_VARIANT(Ifc4x3_rc1);
|
2021-05-11 22:29:16 +02:00
|
|
|
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x3_rc1);
|
|
|
|
|
#endif
|
2018-09-07 14:08:56 +02:00
|
|
|
|
2021-05-11 22:29:16 +02:00
|
|
|
#ifdef HAS_SCHEMA_4x3_rc2
|
2022-07-17 21:13:46 +02:00
|
|
|
GET_RELATINGOBJECT_IFC4_VARIANT(Ifc4x3_rc2);
|
2021-02-14 12:43:27 +01:00
|
|
|
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x3_rc2);
|
2021-05-11 22:29:16 +02:00
|
|
|
#endif
|
|
|
|
|
|
2022-07-17 21:13:46 +02:00
|
|
|
#ifdef HAS_SCHEMA_4x3_rc3
|
|
|
|
|
GET_RELATINGOBJECT_IFC4_VARIANT(Ifc4x3_rc3);
|
|
|
|
|
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x3_rc3);
|
2021-05-11 22:29:16 +02:00
|
|
|
#endif
|
2022-07-17 21:13:46 +02:00
|
|
|
|
|
|
|
|
#ifdef HAS_SCHEMA_4x3_rc4
|
|
|
|
|
GET_RELATINGOBJECT_IFC4_VARIANT(Ifc4x3_rc4);
|
|
|
|
|
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x3_rc4);
|
2021-05-11 22:29:16 +02:00
|
|
|
#endif
|
2022-07-17 21:13:46 +02:00
|
|
|
|
|
|
|
|
#ifdef HAS_SCHEMA_4x3
|
|
|
|
|
GET_RELATINGOBJECT_IFC4_VARIANT(Ifc4x3);
|
|
|
|
|
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x3);
|
2021-05-11 22:29:16 +02:00
|
|
|
#endif
|
2022-07-17 21:13:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Declares the schema-based IfcProduct check:
|
|
|
|
|
// - if (inst->as<Ifc2x3::IfcProduct>()) { ... }
|
|
|
|
|
// - ...
|
|
|
|
|
#define IFCPROCUCT_CHECK(r, data, elem) \
|
|
|
|
|
if (inst->as<BOOST_PP_CAT(Ifc, elem)::IfcProduct>()) { return get_decomposing_entity_impl(inst->as<BOOST_PP_CAT(Ifc, elem)::IfcProduct>(), include_openings); }
|
|
|
|
|
|
|
|
|
|
#define GET_LAYERS(r, data, elem) \
|
|
|
|
|
if (inst->as<BOOST_PP_CAT(Ifc, elem)::IfcProduct>()) { return get_layers_impl<BOOST_PP_CAT(Ifc, elem)>(inst->as<BOOST_PP_CAT(Ifc, elem)::IfcProduct>()); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IfcUtil::IfcBaseEntity* IfcGeom::Kernel::get_decomposing_entity(IfcUtil::IfcBaseEntity* inst, bool include_openings) {
|
|
|
|
|
BOOST_PP_SEQ_FOR_EACH(IFCPROCUCT_CHECK, , SCHEMA_SEQ)
|
|
|
|
|
|
2021-05-11 22:29:16 +02:00
|
|
|
if (inst->declaration().name() == "IfcProject") {
|
2019-07-12 10:43:35 +02:00
|
|
|
return nullptr;
|
2018-09-07 14:08:56 +02:00
|
|
|
}
|
2021-05-11 22:29:16 +02:00
|
|
|
|
|
|
|
|
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
|
2018-09-07 14:08:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
template <typename Schema>
|
|
|
|
|
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_layers_impl(typename Schema::IfcProduct* prod) {
|
|
|
|
|
std::map<std::string, IfcUtil::IfcBaseEntity*> layers;
|
2021-07-29 14:54:51 +02:00
|
|
|
if (prod->Representation()) {
|
|
|
|
|
aggregate_of_instance::ptr r = IfcParse::traverse(prod->Representation());
|
2018-09-07 14:08:56 +02:00
|
|
|
typename Schema::IfcRepresentation::list::ptr representations = r->as<typename Schema::IfcRepresentation>();
|
|
|
|
|
for (typename Schema::IfcRepresentation::list::it it = representations->begin(); it != representations->end(); ++it) {
|
|
|
|
|
typename Schema::IfcPresentationLayerAssignment::list::ptr a = (*it)->LayerAssignments();
|
|
|
|
|
for (typename Schema::IfcPresentationLayerAssignment::list::it jt = a->begin(); jt != a->end(); ++jt) {
|
|
|
|
|
layers[(*jt)->Name()] = *jt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return layers;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::map<std::string, IfcUtil::IfcBaseEntity*> IfcGeom::Kernel::get_layers(IfcUtil::IfcBaseEntity* inst) {
|
2022-07-17 21:13:46 +02:00
|
|
|
BOOST_PP_SEQ_FOR_EACH(GET_LAYERS, , SCHEMA_SEQ)
|
2021-05-11 22:29:16 +02:00
|
|
|
|
|
|
|
|
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
|
2018-09-07 14:08:56 +02:00
|
|
|
}
|