diff --git a/src/ifcconvert/ColladaSerializer.cpp b/src/ifcconvert/ColladaSerializer.cpp index 8d8f0d3433..0e8b3d83a6 100644 --- a/src/ifcconvert/ColladaSerializer.cpp +++ b/src/ifcconvert/ColladaSerializer.cpp @@ -335,7 +335,7 @@ void ColladaSerializer::ColladaExporter::startDocument(const std::string& unit_n asset.add(); } -void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationElement* o, const IfcGeom::Element* parent) +void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationElement* o) { const IfcGeom::Representation::Triangulation& mesh = o->geometry(); const std::string name = serializer->settings().get(SerializerSettings::USE_ELEMENT_GUIDS) ? @@ -355,7 +355,7 @@ void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationEleme DeferredObject defered = (serializer->settings().get(SerializerSettings::USE_ELEMENT_HIERARCHY) ? DeferredObject(name, representation_id, o->type(), o->transformation().matrix().data(), mesh.verts(), mesh.normals(), - mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials(), material_references, mesh.uvs(), *parent) : + mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials(), material_references, mesh.uvs(), *(o->storey())) : DeferredObject(name, representation_id, o->type(), o->transformation().matrix().data(), mesh.verts(), mesh.normals(), mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials(), material_references, mesh.uvs())); deferreds.push_back(defered); @@ -409,12 +409,7 @@ void ColladaSerializer::writeHeader() { } void ColladaSerializer::write(const IfcGeom::TriangulationElement* o) { - exporter.write(o, NULL); -} - -void ColladaSerializer::write(const IfcGeom::TriangulationElement* o, const IfcGeom::Element* parent) -{ - exporter.write(o, parent); + exporter.write(o); } diff --git a/src/ifcconvert/ColladaSerializer.h b/src/ifcconvert/ColladaSerializer.h index 96a5f32ab2..82473ec4d6 100644 --- a/src/ifcconvert/ColladaSerializer.h +++ b/src/ifcconvert/ColladaSerializer.h @@ -129,18 +129,15 @@ private: { const IfcGeom::Element* parent1 = def_obj1.parent; const IfcGeom::Element* parent2 = def_obj2.parent; - std::cout << "comparing..\n"; if (parent1 == NULL || parent2 == NULL) { bool res = (def_obj1.unique_id < def_obj2.unique_id ? true : false); - std::cout << "done\n"; return res; } else { bool res = parent1->name() < parent2->name() ? true : false; - std::cout << "done\n"; return res; } } @@ -219,8 +216,7 @@ private: std::vector deferreds; virtual ~ColladaExporter() {} void startDocument(const std::string& unit_name, float unit_magnitude); - void write(const IfcGeom::TriangulationElement* o) {}; - void write(const IfcGeom::TriangulationElement* o, const IfcGeom::Element* parent); + void write(const IfcGeom::TriangulationElement* o); void endDocument(); }; ColladaExporter exporter; @@ -239,7 +235,6 @@ public: bool ready(); void writeHeader(); void write(const IfcGeom::TriangulationElement* o); - void write(const IfcGeom::TriangulationElement* o, const IfcGeom::Element* parent); void write(const IfcGeom::BRepElement* /*o*/) {} void finalize(); bool isTesselated() const { return true; } diff --git a/src/ifcconvert/GeometrySerializer.h b/src/ifcconvert/GeometrySerializer.h index 4a84a50322..8543c468cb 100644 --- a/src/ifcconvert/GeometrySerializer.h +++ b/src/ifcconvert/GeometrySerializer.h @@ -76,7 +76,6 @@ public: virtual bool isTesselated() const = 0; virtual void write(const IfcGeom::TriangulationElement* o) = 0; - virtual void write(const IfcGeom::TriangulationElement* o, const IfcGeom::Element* element) = 0; virtual void write(const IfcGeom::BRepElement* o) = 0; virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) = 0; diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 5ceb200d30..f6f45bb143 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -467,6 +467,7 @@ int main(int argc, char** argv) settings.set(IfcGeom::IteratorSettings::APPLY_LAYERSETS, enable_layerset_slicing); settings.set(IfcGeom::IteratorSettings::NO_NORMALS, no_normals); settings.set(IfcGeom::IteratorSettings::GENERATE_UVS, generate_uvs); + settings.set(IfcGeom::IteratorSettings::SEARCH_FLOOR, use_element_hierarchy); settings.set(SerializerSettings::USE_ELEMENT_NAMES, use_element_names); settings.set(SerializerSettings::USE_ELEMENT_GUIDS, use_element_guids); @@ -588,43 +589,13 @@ int main(int argc, char** argv) do { IfcGeom::Element *geom_object = context_iterator.get(); - // if the target is a .dae file, get the parent of the object - if (serializer->settings().get(SerializerSettings::USE_ELEMENT_HIERARCHY) && output_extension == ".dae" && geom_object->parent_id() != -1) + if (is_tesselated) { - const IfcGeom::Element *parent_object = NULL; - - bool hasParent = true; - try { parent_object = context_iterator.getObject(geom_object->parent_id()); } - catch (std::exception e) - { - hasParent = false; - } - - while (parent_object != NULL && parent_object->type() != "IfcBuildingStorey" && hasParent) - { - try { parent_object = context_iterator.getObject(parent_object->parent_id()); } - catch (std::exception e) - { - hasParent = false; - } - - hasParent = hasParent && parent_object->parent_id() != 1; - } - - serializer->write(static_cast*>(geom_object), parent_object); - //delete parent_object; - //parent_object = NULL; + serializer->write(static_cast*>(geom_object)); } else { - if (is_tesselated) - { - serializer->write(static_cast*>(geom_object)); - } - else - { - serializer->write(static_cast*>(geom_object)); - } + serializer->write(static_cast*>(geom_object)); } const int progress = context_iterator.progress() / 2; diff --git a/src/ifcconvert/OpenCascadeBasedSerializer.h b/src/ifcconvert/OpenCascadeBasedSerializer.h index 2dce8ef63f..01c088594d 100644 --- a/src/ifcconvert/OpenCascadeBasedSerializer.h +++ b/src/ifcconvert/OpenCascadeBasedSerializer.h @@ -40,7 +40,6 @@ public: bool ready(); virtual void writeShape(const TopoDS_Shape& shape) = 0; void write(const IfcGeom::TriangulationElement* /*o*/) {} - void write(const IfcGeom::TriangulationElement* o, const IfcGeom::Element* parent) {} void write(const IfcGeom::BRepElement* o); bool isTesselated() const { return false; } void setFile(IfcParse::IfcFile*) {} diff --git a/src/ifcconvert/SvgSerializer.h b/src/ifcconvert/SvgSerializer.h index fe12cfbeb6..542541f9d0 100644 --- a/src/ifcconvert/SvgSerializer.h +++ b/src/ifcconvert/SvgSerializer.h @@ -60,7 +60,6 @@ public: void writeHeader(); bool ready(); void write(const IfcGeom::TriangulationElement* /*o*/) {} - void write(const IfcGeom::TriangulationElement* o, const IfcGeom::Element* parent) {} void write(const IfcGeom::BRepElement* o); void write(path_object& p, const TopoDS_Wire& wire); path_object& start_path(IfcSchema::IfcBuildingStorey* storey, const std::string& id); diff --git a/src/ifcgeom/IfcGeomElement.h b/src/ifcgeom/IfcGeomElement.h index 820727533a..c2c65891c8 100644 --- a/src/ifcgeom/IfcGeomElement.h +++ b/src/ifcgeom/IfcGeomElement.h @@ -81,6 +81,7 @@ namespace IfcGeom { std::string _unique_id; Transformation

_transformation; IfcSchema::IfcProduct* product_; + const Element

* _storey; public: int id() const { return _id; } int parent_id() const { return _parent_id; } @@ -91,6 +92,8 @@ namespace IfcGeom { const std::string& unique_id() const { return _unique_id; } const Transformation

& transformation() const { return _transformation; } IfcSchema::IfcProduct* product() const { return product_; } + const Element

* storey() const { return _storey; } + void SetFloor(const Element

* floor) { _storey = floor; } Element(const ElementSettings& settings, int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const std::string& context, const gp_Trsf& trsf, IfcSchema::IfcProduct *product) @@ -106,6 +109,7 @@ namespace IfcGeom { oss << "-" << ctx; } _unique_id = oss.str(); + } virtual ~Element() {} }; diff --git a/src/ifcgeom/IfcGeomElement.h~RF5ff49ef.TMP b/src/ifcgeom/IfcGeomElement.h~RF5ff49ef.TMP new file mode 100644 index 0000000000..3a38905ea1 --- /dev/null +++ b/src/ifcgeom/IfcGeomElement.h~RF5ff49ef.TMP @@ -0,0 +1,198 @@ +/******************************************************************************** + * * + * 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 . * + * * + ********************************************************************************/ + +#ifndef IFCGEOMELEMENT_H +#define IFCGEOMELEMENT_H + +#include +#include + +#include "../ifcparse/IfcGlobalId.h" + +#include "../ifcgeom/IfcGeomRepresentation.h" +#include "../ifcgeom/IfcGeomIteratorSettings.h" +#include "ifc_geom_api.h" + +namespace IfcGeom { + + template + class Matrix { + private: + std::vector

_data; + public: + Matrix(const ElementSettings& settings, const gp_Trsf& trsf) { + // Convert the gp_Trsf into a 4x3 Matrix + // Note that in case the CONVERT_BACK_UNITS setting is enabled + // the translation component of the matrix needs to be divided + // by the magnitude of the IFC model length unit because + // internally in IfcOpenShell everything is measured in meters. + for(int i = 1; i < 5; ++i) { + for (int j = 1; j < 4; ++j) { + const double trsf_value = trsf.Value(j,i); + const double matrix_value = i == 4 && settings.get(IteratorSettings::CONVERT_BACK_UNITS) + ? trsf_value / settings.unit_magnitude() + : trsf_value; + _data.push_back(static_cast

(matrix_value)); + } + } + } + const std::vector

& data() const { return _data; } + }; + + template + class Transformation { + private: + gp_Trsf trsf; + Matrix

_matrix; + public: + Transformation(const ElementSettings& settings, const gp_Trsf& trsf) + : trsf(trsf) + , _matrix(settings, trsf) + {} + const gp_Trsf& data() const { return trsf; } + const Matrix

& matrix() const { return _matrix; } + }; + + template + class Element { + private: + int _id; + int _parent_id; + std::string _name; + std::string _type; + std::string _guid; + std::string _context; + std::string _unique_id; + Transformation

_transformation; + IfcSchema::IfcProduct* product_; + Element

* _storey; + public: + int id() const { return _id; } + int parent_id() const { return _parent_id; } + const std::string& name() const { return _name; } + const std::string& type() const { return _type; } + const std::string& guid() const { return _guid; } + const std::string& context() const { return _context; } + const std::string& unique_id() const { return _unique_id; } + const Transformation

& transformation() const { return _transformation; } + IfcSchema::IfcProduct* product() const { return product_; } + const Element

* storey() const { return _storey; } + + Element(const ElementSettings& settings, int id, int parent_id, const std::string& name, const std::string& type, + const std::string& guid, const std::string& context, const gp_Trsf& trsf, IfcSchema::IfcProduct *product) + : _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _context(context), _transformation(settings, trsf) + , product_(product) + { + std::ostringstream oss; + oss << "product-" << IfcParse::IfcGlobalId(guid).formatted(); + if (!_context.empty()) { + std::string ctx = _context; + std::transform(ctx.begin(), ctx.end(), ctx.begin(), ::tolower); + std::replace(ctx.begin(), ctx.end(), ' ', '-'); + oss << "-" << ctx; + } + _unique_id = oss.str(); + + _storey = NULL; + // If we want to retrieve the storey hierarchy + if (settings.get(IteratorSettings::SEARCH_FLOOR)) + { + if (_parent_id != -1) + { + bool hasParent = true; + try { _storey = context_iterator.getObject(_parent_id); } + catch (std::exception e) + { + hasParent = false; + } + + while (_storey != NULL && parent_object->type() != "IfcBuildingStorey" && hasParent) + { + try { parent_object = context_iterator.getObject(parent_object->parent_id()); } + catch (std::exception e) + { + hasParent = false; + } + + hasParent = hasParent && parent_object->parent_id() != 1; + } + } + } + } + virtual ~Element() {} + }; + + template + class BRepElement : public Element

{ + private: + boost::shared_ptr _geometry; + public: + const boost::shared_ptr& geometry_pointer() const { return _geometry; } + const Representation::BRep& geometry() const { return *_geometry; } + BRepElement(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, + const std::string& context, const gp_Trsf& trsf, const boost::shared_ptr& geometry, + IfcSchema::IfcProduct* product) + : Element

(geometry->settings(),id,parent_id,name,type,guid,context,trsf, product) + , _geometry(geometry) + {} + private: + BRepElement(const BRepElement& other); + BRepElement& operator=(const BRepElement& other); + }; + + template + class TriangulationElement : public Element

{ + private: + boost::shared_ptr< Representation::Triangulation

> _geometry; + public: + const Representation::Triangulation

& geometry() const { return *_geometry; } + const boost::shared_ptr< Representation::Triangulation

>& geometry_pointer() const { return _geometry; } + TriangulationElement(const BRepElement

& shape_model) + : Element

(shape_model) + , _geometry(boost::shared_ptr >(new Representation::Triangulation

(shape_model.geometry()))) + {} + TriangulationElement(const Element

& element, const boost::shared_ptr >& geometry) + : Element

(element) + , _geometry(geometry) + {} + private: + TriangulationElement(const TriangulationElement& other); + TriangulationElement& operator=(const TriangulationElement& other); + }; + + template + class SerializedElement : public Element

{ + private: + Representation::Serialization* _geometry; + public: + const Representation::Serialization& geometry() const { return *_geometry; } + SerializedElement(const BRepElement

& shape_model) + : Element

(shape_model) + , _geometry(new Representation::Serialization(shape_model.geometry())) + {} + virtual ~SerializedElement() { + delete _geometry; + } + private: + SerializedElement(const SerializedElement& other); + SerializedElement& operator=(const SerializedElement& other); + }; +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 1bea3ddaaa..36e53273b7 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -573,6 +573,36 @@ namespace IfcGeom { if (current_triangulation) { ret = current_triangulation; } else if (current_serialization) { ret = current_serialization; } else if (current_shape_model) { ret = current_shape_model; } + + if (settings.get(IteratorSettings::SEARCH_FLOOR)) + { + if (ret->parent_id() != -1) + { + const IfcGeom::Element

* parent_object = NULL; + + bool hasParent = true; + try { parent_object = getObject(ret->parent_id()); } + catch (std::exception e) + { + hasParent = false; + } + + while (parent_object != NULL && parent_object->type() != "IfcBuildingStorey" && hasParent) + { + + try { parent_object = getObject(parent_object->parent_id()); } + catch (std::exception e) + { + hasParent = false; + } + + hasParent = hasParent && parent_object->parent_id() != 1; + } + + if (hasParent) { ret->SetFloor(parent_object); } + } + } + return ret; } diff --git a/src/ifcgeom/IfcGeomIteratorSettings.h b/src/ifcgeom/IfcGeomIteratorSettings.h index edc6e4ac15..b99088db88 100644 --- a/src/ifcgeom/IfcGeomIteratorSettings.h +++ b/src/ifcgeom/IfcGeomIteratorSettings.h @@ -78,8 +78,10 @@ namespace IfcGeom GENERATE_UVS = 1 << 12, /// Specifies whether to slice representations according to associated IfcLayerSets. APPLY_LAYERSETS = 1 << 13, + /// Search for a parent of type IfcBuildingStorey for each representation + SEARCH_FLOOR = 1 << 14, /// Number of different setting flags. - NUM_SETTINGS = 13 + NUM_SETTINGS = 14 }; /// Used to store logical OR combination of setting flags. typedef unsigned SettingField;