From dae35f59ce16b95c897d8f17c7dd8c23697c2e3c Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 4 Aug 2019 11:27:10 +0200 Subject: [PATCH] Implement mapping of IfcExtrudedAreaSolid --- src/ifcgeom/schema/bind_convert_decl.i | 2 +- src/ifcgeom/schema/mapping.cpp | 56 +++++++++++++++++++++++++- src/ifcgeom/schema/mapping.i | 3 +- src/ifcgeom/taxonomy.h | 52 ++++++++++++++++++------ 4 files changed, 97 insertions(+), 16 deletions(-) diff --git a/src/ifcgeom/schema/bind_convert_decl.i b/src/ifcgeom/schema/bind_convert_decl.i index 3f2fc443d2..b612616039 100644 --- a/src/ifcgeom/schema/bind_convert_decl.i +++ b/src/ifcgeom/schema/bind_convert_decl.i @@ -2,6 +2,6 @@ #undef BIND #endif -#define BIND(T) ifcopenshell::geometry::taxonomy::item* convert(const IfcSchema::T*); +#define BIND(T) ifcopenshell::geometry::taxonomy::item* map(const IfcSchema::T*); #include "mapping.i" diff --git a/src/ifcgeom/schema/mapping.cpp b/src/ifcgeom/schema/mapping.cpp index f87fa8ef86..64b3dc81e9 100644 --- a/src/ifcgeom/schema/mapping.cpp +++ b/src/ifcgeom/schema/mapping.cpp @@ -22,9 +22,63 @@ #include "../../ifcparse/IfcLogger.h" using namespace IfcUtil; +using namespace ifcopenshell::geometry; -ifcopenshell::geometry::taxonomy::item* ifcopenshell::geometry::POSTFIX_SCHEMA(mapping)::map(const IfcBaseClass* l) { +#define mapping POSTFIX_SCHEMA(mapping) + +taxonomy::item* mapping::map(const IfcBaseClass* l) { #include "bind_convert_impl.i" Logger::Message(Logger::LOG_ERROR, "No operation defined for:", l); return nullptr; } + +namespace { + // A RAII-based mechanism to cast the conversion results + // from map() into the right type expected by the higher + // level typology items. An exception is thrown if the + // types do not match or the result was nullptr. A copy + // will be assigned to the higher level topology member + // and the original pointer will be deleted. + + // This class is also able to uplift some topology items + // to higher level types, such as a loop to a face, which + // is why the cast operator does not return a reference. + template + class as { + private: + taxonomy::item* item_; + + public: + as(taxonomy::item* item) : item_(item) {} + operator T() const { + if (!item_) { + throw taxonomy::topology_error; + } + T* t = dynamic_cast(item_); + if (t) { + return *t; + } else { + if constexpr (std::is_same::value) { + topology::loop* loop = dynamic_cast(item_); + if (loop) { + return topology::face(loop.id, loop.matrix, *loop); + } + } + throw taxonomy::topology_error; + } + } + ~as() { + delete item; + } + }; +}; + +taxonomy::item* mapping::map(const IfcSchema::IfcExtrudedAreaSolid* inst) { + return new taxonomy::extrusion( + inst->data().id(), + as(map(inst->Position())), + as(map(inst->SweptArea())), + as(map(inst->ExtrudedDirection())), + inst->Depth() + ); +} diff --git a/src/ifcgeom/schema/mapping.i b/src/ifcgeom/schema/mapping.i index 1dc894d273..b6a863d353 100644 --- a/src/ifcgeom/schema/mapping.i +++ b/src/ifcgeom/schema/mapping.i @@ -20,8 +20,7 @@ /******************************************************************************** * * * This file registers function prototypes for all supported IFC geometrical * - * entities. For entities of type CLASS an std::map is also created to cache * - * the output of the conversion functions * + * entities. * * * ********************************************************************************/ diff --git a/src/ifcgeom/taxonomy.h b/src/ifcgeom/taxonomy.h index 10eb3b8704..90ed25b764 100644 --- a/src/ifcgeom/taxonomy.h +++ b/src/ifcgeom/taxonomy.h @@ -1,5 +1,7 @@ #include +#include + namespace ifcopenshell { namespace geometry { @@ -9,6 +11,8 @@ namespace taxonomy { struct item { int instance_id; virtual item* clone() const = 0; + + item(int id) : instance_id(id) {} }; struct matrix4 : public item { @@ -25,61 +29,78 @@ struct matrix4 : public item { struct geom_item : public item { // geometry::style surface_style; matrix4 matrix; + + geom_item(int id) : item(id) {} + geom_item(int id, matrix4 m) : item(id), matrix(m) {} }; template -struct cartesian_base : public item { +struct cartesian_base : public geom_item { std::array components; + + cartesian_base(double x, double y, double z = 0.) : components{ {x, y, z} } {} }; struct point3 : public cartesian_base<3> { virtual item* clone() const { return new point3(*this); } + + point3(double x, double y, double z = 0.) : cartesian_base(x, y, z) {} }; struct direction3 : public cartesian_base<3> { virtual item* clone() const { return new direction3(*this); } + + direction3(double x, double y, double z = 0.) : cartesian_base(x, y, z) {} }; -struct line : public item { +struct line : public geom_item { virtual item* clone() const { return new line(*this); } }; -struct circle : public item { +struct circle : public geom_item { virtual item* clone() const { return new circle(*this); } }; -struct ellipse : public item { +struct ellipse : public geom_item { virtual item* clone() const { return new ellipse(*this); } }; -struct bspline : public item { +struct bspline : public geom_item { virtual item* clone() const { return new bspline(*this); } }; typedef boost::variant curve; -struct edge : public item { +struct edge : public geom_item { boost::variant start, end; boost::optional basis; virtual item* clone() const { return new edge(*this); } }; -struct boundary : public item { +struct loop : public geom_item { std::vector edges; - virtual item* clone() const { return new boundary(*this); } + virtual item* clone() const { return new loop(*this); } }; -struct face : public item { - boundary outer; - std::vector inner; +struct face : public geom_item { + loop outer; + std::vector inner; virtual item* clone() const { return new face(*this); } + + face(int id, loop o) : geom_item(id), outer(o) {} + face(int id, loop o, std::vector i) : geom_item(id), outer(o), inner(i) {} + face(int id, matrix4 m, loop o) : geom_item(id, m), outer(o) {} + face(int id, matrix4 m, loop o, std::vector i) : geom_item(id, m), outer(o), inner(i) {} }; -struct sweep : public item { +struct sweep : public geom_item { face basis; + + sweep(int id, face b) : geom_item(id), basis(b) {} + sweep(int id, matrix4 m, face b) : geom_item(id, m), basis(b) {} }; struct extrusion : public sweep { @@ -87,10 +108,17 @@ struct extrusion : public sweep { double depth; virtual item* clone() const { return new extrusion(*this); } + extrusion(int id, matrix4 m, face basis, direction3 dir, double d) : sweep(id, m, basis), direction(dir), depth(d) {} +}; + +class topology_error : public std::runtime_error { + }; } + + } }