From ad61353fb51111b541f5860dc36d897f6aec4ed9 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 24 Oct 2023 20:54:25 +0200 Subject: [PATCH] Implement ObjectPlacement using native recursion --- src/ifcgeom/mapping/IfcLinearPlacement.cpp | 101 --------------------- src/ifcgeom/mapping/IfcLocalPlacement.cpp | 68 -------------- src/ifcgeom/mapping/IfcObjectPlacement.cpp | 73 +++++++++++++++ src/ifcgeom/mapping/mapping.i | 6 +- 4 files changed, 74 insertions(+), 174 deletions(-) delete mode 100644 src/ifcgeom/mapping/IfcLinearPlacement.cpp delete mode 100644 src/ifcgeom/mapping/IfcLocalPlacement.cpp create mode 100644 src/ifcgeom/mapping/IfcObjectPlacement.cpp diff --git a/src/ifcgeom/mapping/IfcLinearPlacement.cpp b/src/ifcgeom/mapping/IfcLinearPlacement.cpp deleted file mode 100644 index 6e205bc3d3..0000000000 --- a/src/ifcgeom/mapping/IfcLinearPlacement.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************** - * * - * 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 . * - * * - ********************************************************************************/ - -#include "mapping.h" -#define mapping POSTFIX_SCHEMA(mapping) -using namespace ifcopenshell::geometry; - -#if defined SCHEMA_HAS_IfcLinearPlacement - -taxonomy::ptr mapping::map_impl(const IfcSchema::IfcLinearPlacement* inst) { - - // IfcLinearPlacement was added in IFC 4.1 but it had an Orientation attribute of type IfcOrientationExpression, which when combined with other - // attributes was similar to IfcAxis2PlacementLinear. IFC 4.1 and IFC 4.2 have been withdrawn so I'm not going to try to implement linear placement for them. - // For this reason the preprocessor skips this code if SCHEMA_HAS_IfcAxis2PlacementLinear is not defined -#if defined SCHEMA_HAS_IfcAxis2PlacementLinear - // the following is taken from IfcLocalPlacement and tweaked a little - // assumes that PlacementRelTo is relative to another IfcLinearPlacement - IfcSchema::IfcLinearPlacement* current = (IfcSchema::IfcLinearPlacement*)inst; - auto m4 = taxonomy::make(); - - - for (;;) { - IfcSchema::IfcAxis2PlacementLinear* relplacement = current->RelativePlacement(); - m4->components() = taxonomy::cast(map(relplacement))->ccomponents() * m4->ccomponents(); - - if (current->PlacementRelTo()) { - IfcSchema::IfcObjectPlacement* parent = current->PlacementRelTo(); - - bool parent_placement_ignored = false; - if (placement_rel_to_type_ || placement_rel_to_instance_) { - IfcSchema::IfcProduct::list::ptr parent_places = parent->PlacesObject(); - for (auto iter = parent_places->begin(); iter != parent_places->end(); ++iter) { - if ((placement_rel_to_type_ && (*iter)->declaration().is(*placement_rel_to_type_)) || - (placement_rel_to_instance_ && (*iter)->as() == placement_rel_to_instance_)) { - parent_placement_ignored = true; - } - } - } - - if (parent_placement_ignored) { - // The parent placement of the current is a placement for a type that is - // being ignored (Site or Building) or it is the host element of an opening. - break; - } else if (parent->declaration().is(IfcSchema::IfcLinearPlacement::Class())) { - // Keep processing parent placements - current = current->PlacementRelTo()->as(); - } else { - // This is the root placement (typically Site). - break; - } - } else { - break; - } - } - - // The IFC specification does not provided a description of the optional - // CartesianPosition attribute. It is assumed to be a pre-computed IfcAxis2Placement3D - // to be used by software that don't support IfcLinearPlacement. Check that the - // provided cartesian position is the same as the one determined by linear placement - if (inst->CartesianPosition()) { - auto m_fallback = taxonomy::cast(map(inst->CartesianPosition())); - if (m4 != m_fallback) { - Logger::Warning("IfcLinearPlacement.CartesianPosition is different than the computed placement", inst); - } - } - - // @todo: rb - not sure what this means... it came from IfcLocalPlacement - // m4->components() = offset_and_rotation_ * m4->components(); - - return m4; - -#else - // The IFC specification does not provided a description of the optional - // CartesianPosition attribute. It is assumed to be a pre-computed IfcAxis2Placement3D - // to be used by software that don't support IfcLinearPlacement. In this case, - // we will simply use the intended CartesianPosition provided by the IFC model - if (inst->CartesianPosition()) { - return map(inst->CartesianPosition()); - } else { - Logger::Error("Unsupported"); - } -#endif // SCHEMA_HAS_IfcAxis2PlacementLinear -} - -#endif diff --git a/src/ifcgeom/mapping/IfcLocalPlacement.cpp b/src/ifcgeom/mapping/IfcLocalPlacement.cpp deleted file mode 100644 index ac275c8201..0000000000 --- a/src/ifcgeom/mapping/IfcLocalPlacement.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************** - * * - * 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 . * - * * - ********************************************************************************/ - -#include "mapping.h" -#define mapping POSTFIX_SCHEMA(mapping) -using namespace ifcopenshell::geometry; - -taxonomy::ptr mapping::map_impl(const IfcSchema::IfcLocalPlacement* inst) { - IfcSchema::IfcLocalPlacement* current = (IfcSchema::IfcLocalPlacement*)inst; - auto m4 = taxonomy::make(); - for (;;) { - IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement(); - // @todo this type check is wrong and unnecessary? - if (relplacement->as()) { - // @todo check - m4->components() = taxonomy::cast(map(relplacement))->ccomponents() * m4->ccomponents(); - } - if (current->PlacementRelTo()) { - IfcSchema::IfcObjectPlacement* parent = current->PlacementRelTo(); - - bool parent_placement_ignored = false; - if (placement_rel_to_type_ || placement_rel_to_instance_) { - IfcSchema::IfcProduct::list::ptr parent_places = parent->PlacesObject(); - for (auto iter = parent_places->begin(); iter != parent_places->end(); ++iter) { - if ((placement_rel_to_type_ && (*iter)->declaration().is(*placement_rel_to_type_)) || - (placement_rel_to_instance_ && (*iter)->as() == placement_rel_to_instance_)) { - parent_placement_ignored = true; - } - } - } - - if (parent_placement_ignored) { - // The parent placement of the current is a placement for a type that is - // being ignored (Site or Building) or it is the host element of an opening. - break; - } else if (parent->declaration().is(IfcSchema::IfcLocalPlacement::Class())) { - // Keep processing parent placements - current = current->PlacementRelTo()->as(); - } else { - // This is the root placement (typically Site). - break; - } - } else { - break; - } - } - - // @todo - // m4->components() = offset_and_rotation_ * m4->components(); - - return m4; -} diff --git a/src/ifcgeom/mapping/IfcObjectPlacement.cpp b/src/ifcgeom/mapping/IfcObjectPlacement.cpp new file mode 100644 index 0000000000..34ef7bee61 --- /dev/null +++ b/src/ifcgeom/mapping/IfcObjectPlacement.cpp @@ -0,0 +1,73 @@ +/******************************************************************************** + * * + * 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 . * + * * + ********************************************************************************/ + +#include "mapping.h" +#define mapping POSTFIX_SCHEMA(mapping) +using namespace ifcopenshell::geometry; + +taxonomy::ptr mapping::map_impl(const IfcSchema::IfcObjectPlacement* inst) { + const IfcSchema::IfcObjectPlacement* relative_to = nullptr; + const IfcUtil::IfcBaseInterface* transform; + +#ifdef SCHEMA_HAS_IfcLinearPlacement + if (inst->as()) { + transform = inst->as()->RelativePlacement(); + } +#endif + if (inst->as()) { + transform = inst->as()->RelativePlacement(); + } + if (inst->as()) { + // @todo a bit harder to map without kernel + return nullptr; + } + +#ifdef SCHEMA_IfcObjectPlacement_HAS_PlacementRelTo + relative_to = inst->PlacementRelTo(); +#else + if (inst->as()) { + relative_to = inst->as()->PlacementRelTo(); + } +#endif + + bool parent_placement_ignored = false; + if (relative_to && (placement_rel_to_type_ || placement_rel_to_instance_)) { + IfcSchema::IfcProduct::list::ptr parent_places = relative_to->PlacesObject(); + for (auto iter = parent_places->begin(); iter != parent_places->end(); ++iter) { + if ((placement_rel_to_type_ && (*iter)->declaration().is(*placement_rel_to_type_)) || + (placement_rel_to_instance_ && (*iter)->as() == placement_rel_to_instance_)) { + parent_placement_ignored = true; + } + } + } + + if (!parent_placement_ignored && relative_to) { + // The parent placement of the current is a placement for a type that is + // being ignored (Site or Building) or it is the host element of an opening. + return taxonomy::make( + taxonomy::cast(map(relative_to))->ccomponents() * + taxonomy::cast(map(transform))->ccomponents() + ); + } else { + return map(transform); + } + + // @todo + // m4->components() = offset_and_rotation_ * m4->components(); +} diff --git a/src/ifcgeom/mapping/mapping.i b/src/ifcgeom/mapping/mapping.i index 7f1d425350..ffb5f6ec6a 100644 --- a/src/ifcgeom/mapping/mapping.i +++ b/src/ifcgeom/mapping/mapping.i @@ -149,11 +149,7 @@ BIND(IfcAxis1Placement); BIND(IfcCartesianTransformationOperator2D); // IfcCartesianTransformationOperator3DnonUniform included BIND(IfcCartesianTransformationOperator3D); -// BIND(IfcObjectPlacement); -BIND(IfcLocalPlacement); // -> matrix4 -#if defined SCHEMA_HAS_IfcLinearPlacement -BIND(IfcLinearPlacement); // -> matrix4 -#endif +BIND(IfcObjectPlacement); // -> matrix4 BIND(IfcVector); // BIND(IfcColourRgb);