diff --git a/src/ifcgeom/schema/mapping.cpp b/src/ifcgeom/schema/mapping.cpp index 748339388f..3218e4355b 100644 --- a/src/ifcgeom/schema/mapping.cpp +++ b/src/ifcgeom/schema/mapping.cpp @@ -70,7 +70,11 @@ namespace { loop_to_face_upgrade(taxonomy::item* item) { taxonomy::loop* loop = dynamic_cast(item); if (loop) { - face_ = taxonomy::face(loop->instance, loop->matrix, *loop); + face_ = taxonomy::face(); + face_->instance = loop->instance; + face_->matrix = loop->matrix; + // @todo make sure loop is not freed + face_->children = { loop }; } } @@ -121,6 +125,23 @@ namespace { delete item_; } }; + + template + U* map_to_collection(mapping* m, const T& ts) { + auto c = new U; + if (ts->size()) { + for (auto it = ts->begin(); it != ts->end(); ++it) { + if (auto r = m->map(*it)) { + c->children.push_back(r); + } + } + } + if (c->children.empty()) { + delete c; + return nullptr; + } + return c; + } }; taxonomy::item* mapping::map(const IfcSchema::IfcExtrudedAreaSolid* inst) { @@ -134,20 +155,82 @@ taxonomy::item* mapping::map(const IfcSchema::IfcExtrudedAreaSolid* inst) { } taxonomy::item* mapping::map(const IfcSchema::IfcRepresentation* inst) { - auto c = new taxonomy::collection(); - IfcSchema::IfcRepresentationItem::list::ptr items = inst->Items(); - if (items->size()) { - for (IfcSchema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) { - if (auto r = map(*it)) { - c->children.push_back(r); + return map_to_collection(this, inst->Items()); +} + +taxonomy::item* mapping::map(const IfcSchema::IfcFaceBasedSurfaceModel* inst) { + return map_to_collection(this, inst->FbsmFaces()); +} + +taxonomy::item* mapping::map(const IfcSchema::IfcConnectedFaceSet* inst) { + return map_to_collection(this, inst->CfsFaces()); +} + +taxonomy::item* mapping::map(const IfcSchema::IfcFace* inst) { + taxonomy::face* face = new taxonomy::face; + auto bounds = inst->Bounds(); + for (auto& bound : *bounds) { + if (auto r = map(bound->Bound())) { + if (!bound->Orientation()) { + r->reverse(); } - } + face->children.push_back(r); + } } - if (c->children.empty()) { - delete c; + if (face->children.empty()) { + delete face; return nullptr; } - return c; + return face; +} + +taxonomy::item* mapping::map(const IfcSchema::IfcPolyLoop* inst) { + taxonomy::loop* loop = new taxonomy::loop; + + taxonomy::point3 first, previous; + bool is_first = true; + + auto points = inst->Polygon(); + for (auto& point : *points) { + auto p = as(map(point)); + if (is_first) { + previous = first = p; + is_first = false; + } else { + auto edge = new taxonomy::edge; + edge->start = previous; + edge->end = p; + loop->children.push_back(edge); + previous = p; + } + } + + auto edge = new taxonomy::edge; + edge->start = previous; + edge->end = first; + loop->children.push_back(edge); + + if (loop->children.size() < 3) { + Logger::Warning("Not enough edges for", inst); + delete loop; + return nullptr; + } + return loop; +} + +taxonomy::item* mapping::map(const IfcSchema::IfcCartesianPoint* inst) { + auto coords = inst->Coordinates(); + return new taxonomy::point3( + coords.size() >= 1 ? coords[0] : 0., + coords.size() >= 2 ? coords[1] : 0., + coords.size() >= 3 ? coords[2] : 0. + ); +} + +taxonomy::item* mapping::map(const IfcSchema::IfcProduct* inst) { + auto n = new taxonomy::node; + n->matrix = as(map(inst->ObjectPlacement())); + return n; } taxonomy::item* mapping::map(const IfcSchema::IfcAxis2Placement3D* inst) { @@ -175,6 +258,11 @@ taxonomy::item* mapping::map(const IfcSchema::IfcCartesianTransformationOperator return new taxonomy::matrix4(); } +taxonomy::item* mapping::map(const IfcSchema::IfcLocalPlacement* inst) { + // @todo length unit + return new taxonomy::matrix4(); +} + IfcSchema::IfcProduct::list::ptr mapping::products_represented_by(const IfcSchema::IfcRepresentation* representation) { IfcSchema::IfcProduct::list::ptr products(new IfcSchema::IfcProduct::list); diff --git a/src/ifcgeom/schema/mapping.i b/src/ifcgeom/schema/mapping.i index eb6bf0b4f0..c794c6f447 100644 --- a/src/ifcgeom/schema/mapping.i +++ b/src/ifcgeom/schema/mapping.i @@ -24,8 +24,10 @@ * * ********************************************************************************/ +BIND(IfcProduct); + // BIND(IfcShellBasedSurfaceModel); -// BIND(IfcFaceBasedSurfaceModel); +BIND(IfcFaceBasedSurfaceModel); BIND(IfcRepresentation); // BIND(IfcMappedItem); // IfcFacetedBrep included @@ -53,7 +55,7 @@ BIND(IfcRepresentation); #endif BIND(IfcExtrudedAreaSolid); // BIND(IfcRevolvedAreaSolid); -// BIND(IfcConnectedFaceSet); +BIND(IfcConnectedFaceSet); // BIND(IfcBooleanResult); // BIND(IfcPolygonalBoundedHalfSpace); // BIND(IfcHalfSpaceSolid); @@ -91,7 +93,7 @@ BIND(IfcExtrudedAreaSolid); // BIND(IfcDerivedProfileDef); // IfcFaceSurface included // IfcAdvancedFace included in case of IFC4 -// BIND(IfcFace); +BIND(IfcFace); // BIND(IfcEdgeCurve); // BIND(IfcSubedge); @@ -99,7 +101,7 @@ BIND(IfcExtrudedAreaSolid); // BIND(IfcEdge); // BIND(IfcEdgeLoop); // BIND(IfcPolyline); -// BIND(IfcPolyLoop); +BIND(IfcPolyLoop); // BIND(IfcCompositeCurve); // BIND(IfcTrimmedCurve); // BIND(IfcArbitraryOpenProfileDef); @@ -115,7 +117,7 @@ BIND(IfcExtrudedAreaSolid); // BIND(IfcBSplineCurveWithKnots); #endif -// BIND(IfcCartesianPoint); +BIND(IfcCartesianPoint); // BIND(IfcDirection); // BIND(IfcAxis2Placement2D); BIND(IfcAxis2Placement3D); @@ -124,7 +126,7 @@ BIND(IfcCartesianTransformationOperator2DnonUniform); BIND(IfcCartesianTransformationOperator3DnonUniform); BIND(IfcCartesianTransformationOperator2D); BIND(IfcCartesianTransformationOperator3D); -// BIND(IfcObjectPlacement); +BIND(IfcLocalPlacement); // BIND(IfcVector); // BIND(IfcPlane); diff --git a/src/ifcgeom/taxonomy.h b/src/ifcgeom/taxonomy.h index 65bc958071..21a187fc4b 100644 --- a/src/ifcgeom/taxonomy.h +++ b/src/ifcgeom/taxonomy.h @@ -19,12 +19,18 @@ namespace geometry { namespace taxonomy { -enum kinds { MATRIX4, POINT3, DIRECTION3, LINE, CIRCLE, ELLIPSE, BSPLINE, EDGE, LOOP, FACE, EXTRUSION, NODE, COLOUR, STYLE, COLLECTION }; +class topology_error : public std::runtime_error { +public: + topology_error() : std::runtime_error("Generic topology error") {} +}; + +enum kinds { MATRIX4, POINT3, DIRECTION3, LINE, CIRCLE, ELLIPSE, BSPLINE, EDGE, LOOP, FACE, SHELL, EXTRUSION, NODE, COLOUR, STYLE, COLLECTION }; struct item { const IfcUtil::IfcBaseClass* instance; virtual item* clone() const = 0; virtual kinds kind() const = 0; + virtual void reverse() { throw taxonomy::topology_error(); } item(const IfcUtil::IfcBaseClass* instance = nullptr) : instance(instance) {} @@ -98,14 +104,14 @@ struct point3 : public cartesian_base<3> { virtual item* clone() const { return new point3(*this); } virtual kinds kind() const { return POINT3; } - point3(double x, double y, double z = 0.) : cartesian_base(x, y, z) {} + point3(double x = 0., double y = 0., double z = 0.) : cartesian_base(x, y, z) {} }; struct direction3 : public cartesian_base<3> { virtual item* clone() const { return new direction3(*this); } virtual kinds kind() const { return DIRECTION3; } - direction3(double x, double y, double z = 0.) : cartesian_base(x, y, z) {} + direction3(double x = 0., double y = 0., double z = 0.) : cartesian_base(x, y, z) {} }; struct line : public geom_item { @@ -133,46 +139,16 @@ typedef boost::variant curve; struct edge : public geom_item { boost::variant start, end; boost::optional basis; + bool orientation; + edge() : orientation(true) {} virtual item* clone() const { return new edge(*this); } virtual kinds kind() const { return EDGE; } -}; -struct loop : public geom_item { - std::vector edges; - - virtual item* clone() const { return new loop(*this); } - virtual kinds kind() const { return LOOP; } -}; - -struct face : public geom_item { - loop outer; - std::vector inner; - - virtual item* clone() const { return new face(*this); } - virtual kinds kind() const { return FACE; } - - face(const IfcUtil::IfcBaseClass* instance, loop o) : geom_item(instance), outer(o) {} - face(const IfcUtil::IfcBaseClass* instance, loop o, std::vector i) : geom_item(instance), outer(o), inner(i) {} - face(const IfcUtil::IfcBaseClass* instance, matrix4 m, loop o) : geom_item(instance, m), outer(o) {} - face(const IfcUtil::IfcBaseClass* instance, matrix4 m, loop o, std::vector i) : geom_item(instance, m), outer(o), inner(i) {} -}; - -struct sweep : public geom_item { - face basis; - - sweep(face b) : basis(b) {} - sweep(matrix4 m, face b) : geom_item(m), basis(b) {} -}; - -struct extrusion : public sweep { - direction3 direction; - double depth; - - virtual item* clone() const { return new extrusion(*this); } - virtual kinds kind() const { return EXTRUSION; } - - extrusion(matrix4 m, face basis, direction3 dir, double d) : sweep(m, basis), direction(dir), depth(d) {} + virtual void reverse() { + std::swap(start, end); + orientation = !orientation; + } }; struct collection : public geom_item { @@ -180,6 +156,44 @@ struct collection : public geom_item { virtual item* clone() const { return new collection(*this); } virtual kinds kind() const { return COLLECTION; } + virtual void reverse() { + std::reverse(children.begin(), children.end()); + for (auto& child : children) { + child->reverse(); + } + } +}; + +struct shell : public collection { + virtual item* clone() const { return new shell(*this); } + virtual kinds kind() const { return SHELL; } +}; + +struct face : public collection { + virtual item* clone() const { return new face(*this); } + virtual kinds kind() const { return FACE; } +}; + +struct loop : public collection { + virtual item* clone() const { return new loop(*this); } + virtual kinds kind() const { return LOOP; } +}; + +struct sweep : public geom_item { + face basis; + + sweep(face b) : basis(b) {} + sweep(matrix4 m, face b) : geom_item(m), basis(b) {} +}; + +struct extrusion : public sweep { + direction3 direction; + double depth; + + virtual item* clone() const { return new extrusion(*this); } + virtual kinds kind() const { return EXTRUSION; } + + extrusion(matrix4 m, face basis, direction3 dir, double d) : sweep(m, basis), direction(dir), depth(d) {} }; struct node : public geom_item { @@ -188,12 +202,10 @@ struct node : public geom_item { virtual item* clone() const { return new node(*this); } virtual kinds kind() const { return NODE; } - - node(const IfcUtil::IfcBaseClass* instance, matrix4 m, const std::map& representations, const std::vector& children) : geom_item(instance, m), representations(representations), children(children) {} }; namespace impl { - typedef std::tuple KindsTuple; + typedef std::tuple KindsTuple; } struct type_by_kind { @@ -203,11 +215,6 @@ struct type_by_kind { static const size_t max = std::tuple_size< impl::KindsTuple>::value; }; -class topology_error : public std::runtime_error { -public: - topology_error() : std::runtime_error("Generic topology error") {} -}; - }