From af2799acd46ddeb5d2328cc410595a752fc0c6d9 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sat, 20 May 2017 19:50:10 +0200 Subject: [PATCH] Matrix multiplication in OCC rather than boost::ublas (re #211) --- src/ifcconvert/ColladaSerializer.cpp | 237 ++++++------------------ src/ifcconvert/ColladaSerializer.h | 66 +++---- src/ifcconvert/WavefrontObjSerializer.h | 1 - src/ifcgeom/IfcGeomElement.h | 36 +++- 4 files changed, 105 insertions(+), 235 deletions(-) diff --git a/src/ifcconvert/ColladaSerializer.cpp b/src/ifcconvert/ColladaSerializer.cpp index 01c337c60f..95f44c4a2c 100644 --- a/src/ifcconvert/ColladaSerializer.cpp +++ b/src/ifcconvert/ColladaSerializer.cpp @@ -32,14 +32,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include - using namespace IfcSchema; using namespace boost::numeric::ublas; @@ -69,7 +61,7 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const } void ColladaSerializer::ColladaExporter::ColladaGeometries::write( - const std::string &mesh_id, const std::string& default_material_name, const std::vector& positions, + const std::string &mesh_id, const std::string& /*default_material_name*/, const std::vector& positions, const std::vector& normals, const std::vector& faces, const std::vector& edges, const std::vector material_ids, const std::vector& materials, const std::vector& uvs) @@ -188,7 +180,7 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::close() { void ColladaSerializer::ColladaExporter::ColladaScene::add( const std::string& node_id, const std::string& node_name, const std::string& geom_name, - const std::vector& material_ids, const std::vector& posmatrix) + const std::vector& material_ids, const IfcGeom::Transformation& transformation) { if (!scene_opened) { openVisualScene(scene_id); @@ -202,46 +194,33 @@ void ColladaSerializer::ColladaExporter::ColladaScene::add( // The matrix attribute of an entity is basically a 4x3 representation of its ObjectPlacement. // Note that this placement is absolute, ie it is multiplied with all parent placements. - - double matrix_array[4][4] = { - { (double)posmatrix[0], (double)posmatrix[3], (double)posmatrix[6], (double)posmatrix[ 9] }, - { (double)posmatrix[1], (double)posmatrix[4], (double)posmatrix[7], (double)posmatrix[10] }, - { (double)posmatrix[2], (double)posmatrix[5], (double)posmatrix[8], (double)posmatrix[11] }, - { 0, 0, 0, 1 } - }; + + IfcGeom::Transformation* relative_trsf = 0; + const IfcGeom::Transformation* transformation_towrite = &transformation; // If this is not the first parent, get the relative placement if (parentNodes.size() > 0) { - double relative[4][4] = { - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 } - }; - - // Multiplication - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - for (int k = 0; k < 4; ++k) { - relative[i][j] += matrixStack.top()(i, k) * matrix_array[k][j]; - } - } - } - - // Copy from relative to matrix_array - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - matrix_array[i][j] = relative[i][j]; - } - } - + relative_trsf = new IfcGeom::Transformation(matrixStack.top().multiplied(transformation)); + transformation_towrite = relative_trsf; } + + const std::vector& posmatrix = transformation_towrite->matrix().data(); + + double matrix_array[4][4] = { + { (double)posmatrix[0], (double)posmatrix[3], (double)posmatrix[6], (double)posmatrix[9] }, + { (double)posmatrix[1], (double)posmatrix[4], (double)posmatrix[7], (double)posmatrix[10] }, + { (double)posmatrix[2], (double)posmatrix[5], (double)posmatrix[8], (double)posmatrix[11] }, + { 0, 0, 0, 1 } + }; + /// @todo: TFK: Rather than applying this offset to all leafs (which might be undesirable) should this offset be applied to a node higher up in the hierarchy? matrix_array[0][3] += serializer->settings().offset[0]; matrix_array[1][3] += serializer->settings().offset[1]; matrix_array[2][3] += serializer->settings().offset[2]; + delete relative_trsf; + node.start(); node.addMatrix(matrix_array); COLLADASW::InstanceGeometry instanceGeometry(mSW); @@ -263,63 +242,36 @@ void ColladaSerializer::ColladaExporter::ColladaScene::addParent(const IfcGeom:: scene_opened = true; } + const IfcGeom::Transformation& parent_trsf = parent.transformation(); + + IfcGeom::Transformation* relative_trsf = 0; + const IfcGeom::Transformation* transformation_towrite = &parent_trsf; + + // If this is not the first parent, get the relative placement + if (parentNodes.size() > 0) + { + relative_trsf = new IfcGeom::Transformation(matrixStack.top().multiplied(parent_trsf)); + transformation_towrite = relative_trsf; + } + + const std::vector& parentMatrix = transformation_towrite->matrix().data(); - const std::vector parentMatrix = parent.transformation().matrix().data(); - double matrix_array[4][4] = { { (double)parentMatrix[0], (double)parentMatrix[3], (double)parentMatrix[6], (double)parentMatrix[9] }, { (double)parentMatrix[1], (double)parentMatrix[4], (double)parentMatrix[7], (double)parentMatrix[10] }, { (double)parentMatrix[2], (double)parentMatrix[5], (double)parentMatrix[8], (double)parentMatrix[11] }, { 0, 0, 0, 1 } }; - - // ========= - - // If this is not the first parent, get the relative placement - if (parentNodes.size() > 0) - { - double relative[4][4] = { - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 } - }; - - // Multiplication - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - for (int k = 0; k < 4; ++k) { - relative[i][j] += matrixStack.top()(i, k) * matrix_array[k][j]; - } - } - } - - // TODO : Handle the case where there was no inverse - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - matrix_array[i][j] = relative[i][j]; - } - } - } - - //adding the offset to the matrix - //matrix_array[0][3] += serializer->settings().offset[0]; - //matrix_array[1][3] += serializer->settings().offset[1]; - //matrix_array[2][3] += serializer->settings().offset[2]; - - - const std::string id = "representation-" + boost::lexical_cast(parent.id()); // Chose a name of the parent object std::string name = ""; - if (serializer->settings().get(SerializerSettings::USE_ELEMENT_TYPES)) { name = parent.type() + " " + parent.name(); } - else - { - if (parent.name() == "") { name = "unnamed"; } - else { name = parent.name(); } + if (serializer->settings().get(SerializerSettings::USE_ELEMENT_TYPES)) { + name = parent.type() + " " + parent.name(); + } else { + name = parent.unique_id(); } - + + const std::string& id = name; COLLADASW::Node *current_node; current_node = new COLLADASW::Node(mSW); @@ -329,83 +281,10 @@ void ColladaSerializer::ColladaExporter::ColladaScene::addParent(const IfcGeom:: current_node->start(); current_node->addMatrix(matrix_array); - // ==== Inverse the matrix and save it ==== - - double m[4][4] = { - { (double)parentMatrix[0], (double)parentMatrix[3], (double)parentMatrix[6], (double)parentMatrix[9] }, - { (double)parentMatrix[1], (double)parentMatrix[4], (double)parentMatrix[7], (double)parentMatrix[10] }, - { (double)parentMatrix[2], (double)parentMatrix[5], (double)parentMatrix[8], (double)parentMatrix[11] }, - { 0, 0, 0, 1 } - }; - - double det = - m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0] - m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] + - m[0][2] * m[1][1] * m[2][3] * m[3][0] - m[0][1] * m[1][2] * m[2][3] * m[3][0] - m[0][3] * m[1][2] * m[2][0] * m[3][1] + m[0][2] * m[1][3] * m[2][0] * m[3][1] + - m[0][3] * m[1][0] * m[2][2] * m[3][1] - m[0][0] * m[1][3] * m[2][2] * m[3][1] - m[0][2] * m[1][0] * m[2][3] * m[3][1] + m[0][0] * m[1][2] * m[2][3] * m[3][1] + - m[0][3] * m[1][1] * m[2][0] * m[3][2] - m[0][1] * m[1][3] * m[2][0] * m[3][2] - m[0][3] * m[1][0] * m[2][1] * m[3][2] + m[0][0] * m[1][3] * m[2][1] * m[3][2] + - m[0][1] * m[1][0] * m[2][3] * m[3][2] - m[0][0] * m[1][1] * m[2][3] * m[3][2] - m[0][2] * m[1][1] * m[2][0] * m[3][3] + m[0][1] * m[1][2] * m[2][0] * m[3][3] + - m[0][2] * m[1][0] * m[2][1] * m[3][3] - m[0][0] * m[1][2] * m[2][1] * m[3][3] - m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3]; - - - if (det != 0) - { - double inverse[4][4]; - inverse[0][0] = m[1][2] * m[2][3] * m[3][1] - m[1][3] * m[2][2] * m[3][1] + m[1][3] * m[2][1] * m[3][2] - m[1][1] * m[2][3] * m[3][2] - m[1][2] * m[2][1] * m[3][3] + m[1][1] * m[2][2] * m[3][3]; - inverse[0][1] = m[0][3] * m[2][2] * m[3][1] - m[0][2] * m[2][3] * m[3][1] - m[0][3] * m[2][1] * m[3][2] + m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3] - m[0][1] * m[2][2] * m[3][3]; - inverse[0][2] = m[0][2] * m[1][3] * m[3][1] - m[0][3] * m[1][2] * m[3][1] + m[0][3] * m[1][1] * m[3][2] - m[0][1] * m[1][3] * m[3][2] - m[0][2] * m[1][1] * m[3][3] + m[0][1] * m[1][2] * m[3][3]; - inverse[0][3] = m[0][3] * m[1][2] * m[2][1] - m[0][2] * m[1][3] * m[2][1] - m[0][3] * m[1][1] * m[2][2] + m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3] - m[0][1] * m[1][2] * m[2][3]; - - inverse[1][0] = m[1][3] * m[2][2] * m[3][0] - m[1][2] * m[2][3] * m[3][0] - m[1][3] * m[2][0] * m[3][2] + m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3] - m[1][0] * m[2][2] * m[3][3]; - inverse[1][1] = m[0][2] * m[2][3] * m[3][0] - m[0][3] * m[2][2] * m[3][0] + m[0][3] * m[2][0] * m[3][2] - m[0][0] * m[2][3] * m[3][2] - m[0][2] * m[2][0] * m[3][3] + m[0][0] * m[2][2] * m[3][3]; - inverse[1][2] = m[0][3] * m[1][2] * m[3][0] - m[0][2] * m[1][3] * m[3][0] - m[0][3] * m[1][0] * m[3][2] + m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3] - m[0][0] * m[1][2] * m[3][3]; - inverse[1][3] = m[0][2] * m[1][3] * m[2][0] - m[0][3] * m[1][2] * m[2][0] + m[0][3] * m[1][0] * m[2][2] - m[0][0] * m[1][3] * m[2][2] - m[0][2] * m[1][0] * m[2][3] + m[0][0] * m[1][2] * m[2][3]; - - inverse[2][0] = m[1][1] * m[2][3] * m[3][0] - m[1][3] * m[2][1] * m[3][0] + m[1][3] * m[2][0] * m[3][1] - m[1][0] * m[2][3] * m[3][1] - m[1][1] * m[2][0] * m[3][3] + m[1][0] * m[2][1] * m[3][3]; - inverse[2][1] = m[0][3] * m[2][1] * m[3][0] - m[0][1] * m[2][3] * m[3][0] - m[0][3] * m[2][0] * m[3][1] + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] - m[0][0] * m[2][1] * m[3][3]; - inverse[2][2] = m[0][1] * m[1][3] * m[3][0] - m[0][3] * m[1][1] * m[3][0] + m[0][3] * m[1][0] * m[3][1] - m[0][0] * m[1][3] * m[3][1] - m[0][1] * m[1][0] * m[3][3] + m[0][0] * m[1][1] * m[3][3]; - inverse[2][3] = m[0][3] * m[1][1] * m[2][0] - m[0][1] * m[1][3] * m[2][0] - m[0][3] * m[1][0] * m[2][1] + m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3] - m[0][0] * m[1][1] * m[2][3]; - - inverse[3][0] = m[1][2] * m[2][1] * m[3][0] - m[1][1] * m[2][2] * m[3][0] - m[1][2] * m[2][0] * m[3][1] + m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2] - m[1][0] * m[2][1] * m[3][2]; - inverse[3][1] = m[0][1] * m[2][2] * m[3][0] - m[0][2] * m[2][1] * m[3][0] + m[0][2] * m[2][0] * m[3][1] - m[0][0] * m[2][2] * m[3][1] - m[0][1] * m[2][0] * m[3][2] + m[0][0] * m[2][1] * m[3][2]; - inverse[3][2] = m[0][2] * m[1][1] * m[3][0] - m[0][1] * m[1][2] * m[3][0] - m[0][2] * m[1][0] * m[3][1] + m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2] - m[0][0] * m[1][1] * m[3][2]; - inverse[3][3] = m[0][1] * m[1][2] * m[2][0] - m[0][2] * m[1][1] * m[2][0] + m[0][2] * m[1][0] * m[2][1] - m[0][0] * m[1][2] * m[2][1] - m[0][1] * m[1][0] * m[2][2] + m[0][0] * m[1][1] * m[2][2]; - - - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - inverse[i][j] /= det; - } - } - - // Create a save matrix to push to the stack - matrix toSave(4, 4); - - // Initialization - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - toSave(i, j) = 0; - } - } - - // Copy the inverse matrix - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - toSave(i, j) = inverse[i][j]; - } - } - - // Save the matrix - matrixStack.push(toSave); - } - else - { - std::cout << "couldn't inverse the position matrix \n"; - } - // Add the node to the parent stack + matrixStack.push(parent_trsf.inverted()); parentNodes.push(current_node); serializer->parentStackId.push(parent.id()); - } void ColladaSerializer::ColladaExporter::ColladaScene::closeParent() @@ -532,12 +411,14 @@ void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationEleme material_references.push_back(material_name); } - 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(), o->parents()) : - 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); + DeferredObject deferred(name, representation_id, o->type(), o->transformation(), mesh.verts(), mesh.normals(), + mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials(), material_references, mesh.uvs()); + + if (serializer->settings().get(SerializerSettings::USE_ELEMENT_HIERARCHY)) { + deferred.parents() = o->parents(); + } + + deferreds.push_back(deferred); } std::string ColladaSerializer::ColladaExporter::differentiateSlabTypes(const IfcGeom::TriangulationElement* o) { @@ -589,14 +470,12 @@ void ColladaSerializer::ColladaExporter::endDocument() { } geometries.close(); - int parent_id = -1; - bool is_parent_tag_opened = false; for (std::vector::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it){ const std::string object_name = it->unique_id; if (use_hierarchy) { - unsigned parentsNumber = it->parents.size(); + unsigned parentsNumber = it->parents_.size(); bool finished = false; // If we have no parent in the stack and the object has no parent, nothing to do : skip the loop @@ -607,29 +486,23 @@ void ColladaSerializer::ColladaExporter::endDocument() { // If we need to add a parent if (serializer->parentStackId.size() <= parentsNumber) { - if (serializer->parentStackId.empty()) { scene.addParent(*(it->parents.at(0))); } + if (serializer->parentStackId.empty()) { scene.addParent(*(it->parents_.at(0))); } else { unsigned diff = parentsNumber - serializer->parentStackId.size(); // If we have the wrong parent in the list - if (serializer->parentStackId.top() != it->parents.at(parentsNumber - diff - 1)->id()) - { + if (serializer->parentStackId.top() != it->parents_.at(parentsNumber - diff - 1)->id()) { scene.closeParent(); - } - // So far we have the right parents, we just need to add the missing ones - else - { - for (unsigned i = parentsNumber - diff; i < parentsNumber; i++) { scene.addParent(*(it->parents.at(i))); } + } else { + // So far we have the right parents, we just need to add the missing ones + for (unsigned i = parentsNumber - diff; i < parentsNumber; i++) { scene.addParent(*(it->parents_.at(i))); } // if diff == 0, we can leave the loop. In fact we have the right number of parents, and the last one is ok if (diff == 0) { finished = true; } } } - } - // IF serializer->parentStackId.size() > parentsNumber - else - { + } else { // Close the finished nodes. After this we get the first case (serializer->parentStackId.size() <= parentsNumber) while (serializer->parentStackId.size() > parentsNumber) { scene.closeParent(); } } @@ -637,7 +510,7 @@ void ColladaSerializer::ColladaExporter::endDocument() { } /// @todo redundant information using ID as both ID and Name, maybe omit Name or allow specifying what would be used as the name - scene.add(object_name, object_name, it->representation_id, it->material_references, it->matrix); + scene.add(object_name, object_name, it->representation_id, it->material_references, it->transformation); } //close the remaining parent tags. diff --git a/src/ifcconvert/ColladaSerializer.h b/src/ifcconvert/ColladaSerializer.h index 9d19da0bfc..3acf29ee8b 100644 --- a/src/ifcconvert/ColladaSerializer.h +++ b/src/ifcconvert/ColladaSerializer.h @@ -86,7 +86,7 @@ private: const std::string scene_id; bool scene_opened; std::stack parentNodes; - std::stack > matrixStack; + std::stack > matrixStack; public: ColladaScene(const std::string& scene_id, COLLADASW::StreamWriter& stream, ColladaSerializer *_serializer) : COLLADASW::LibraryVisualScenes(&stream) @@ -95,7 +95,7 @@ private: , serializer(_serializer) {} void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, - const std::vector& material_ids, const std::vector& matrix); + const std::vector& material_ids, const IfcGeom::Transformation& matrix); void addParent(const IfcGeom::Element& parent); void closeParent(); COLLADASW::Node* GetDirectParent(); @@ -132,28 +132,29 @@ private: ColladaSerializer *serializer; ColladaEffects effects; }; + class DeferredObject { - friend bool operator < (const DeferredObject & def_obj1, const DeferredObject & def_obj2) - { - unsigned size = (def_obj1.parents.size() < def_obj2.parents.size() ? def_obj1.parents.size() : def_obj2.parents.size()); - int cpt = 0; + friend bool operator < (const DeferredObject& def_obj1, const DeferredObject& def_obj2) { + size_t size = (def_obj1.parents_.size() < def_obj2.parents_.size() ? def_obj1.parents_.size() : def_obj2.parents_.size()); + size_t cpt = 0; - // Skip the shared parents - while (cpt < size && *(def_obj1.parents.at(cpt)) == *(def_obj2.parents.at(cpt))) { cpt++; } + // Skip the shared parents + while (cpt < size && *(def_obj1.parents_.at(cpt)) == *(def_obj2.parents_.at(cpt))) { + cpt++; + } - // If a parent list container the other one - if (cpt >= size) { return (def_obj1.parents.size() < def_obj2.parents.size() ? true : false); } - else - { - return *(def_obj1.parents.at(cpt)) < *(def_obj2.parents.at(cpt)); + // If a parent list container the other one + if (cpt >= size) { + return def_obj1.parents_.size() < def_obj2.parents_.size(); + } else { + return *(def_obj1.parents_.at(cpt)) < *(def_obj2.parents_.at(cpt)); + } } - } - public: std::string unique_id, representation_id, type; - std::vector matrix; + IfcGeom::Transformation transformation; std::vector vertices; std::vector normals; std::vector faces; @@ -162,36 +163,16 @@ private: std::vector materials; std::vector material_references; std::vector uvs; - std::vector*> parents; - DeferredObject(const std::string& unique_id, const std::string& representation_id, const std::string& type, const std::vector& matrix, - const std::vector& vertices, const std::vector& normals, const std::vector& faces, - const std::vector& edges, const std::vector& material_ids, const std::vector& materials, - const std::vector& material_references, const std::vector& uvs, const std::vector*>& parent) - : unique_id(unique_id) - , representation_id(representation_id) - , type(type) - , matrix(matrix) - , vertices(vertices) - , normals(normals) - , faces(faces) - , edges(edges) - , material_ids(material_ids) - , materials(materials) - , material_references(material_references) - , uvs(uvs) - , parents(parent) - { - - } + std::vector*> parents_; - DeferredObject(const std::string& unique_id, const std::string& representation_id, const std::string& type, const std::vector& matrix, + DeferredObject(const std::string& unique_id, const std::string& representation_id, const std::string& type, const IfcGeom::Transformation& transformation, const std::vector& vertices, const std::vector& normals, const std::vector& faces, const std::vector& edges, const std::vector& material_ids, const std::vector& materials, const std::vector& material_references, const std::vector& uvs) : unique_id(unique_id) , representation_id(representation_id) , type(type) - , matrix(matrix) + , transformation(transformation) , vertices(vertices) , normals(normals) , faces(faces) @@ -200,9 +181,10 @@ private: , materials(materials) , material_references(material_references) , uvs(uvs) - { - parents.clear(); - } + {} + + std::vector*>& parents() { return parents_; } + const std::vector*>& parents() const { return parents_; } }; COLLADABU::NativeString filename; COLLADASW::StreamWriter stream; diff --git a/src/ifcconvert/WavefrontObjSerializer.h b/src/ifcconvert/WavefrontObjSerializer.h index 5411d5f64f..2aa9708bdc 100644 --- a/src/ifcconvert/WavefrontObjSerializer.h +++ b/src/ifcconvert/WavefrontObjSerializer.h @@ -51,7 +51,6 @@ public: void writeHeader(); void writeMaterial(const IfcGeom::Material& style); 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/ifcgeom/IfcGeomElement.h b/src/ifcgeom/IfcGeomElement.h index 21411d806e..b27f335ade 100644 --- a/src/ifcgeom/IfcGeomElement.h +++ b/src/ifcgeom/IfcGeomElement.h @@ -58,15 +58,25 @@ namespace IfcGeom { template class Transformation { private: - gp_Trsf trsf; - Matrix

_matrix; + ElementSettings settings_; + gp_Trsf trsf_; + Matrix

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

& matrix() const { return _matrix; } + const gp_Trsf& data() const { return trsf_; } + const Matrix

& matrix() const { return matrix_; } + + Transformation inverted() const { + return Transformation(settings_, trsf_.Inverted()); + } + + Transformation multiplied(const Transformation& other) const { + return Transformation(settings_, trsf_.Multiplied(other.data())); + } }; template @@ -126,10 +136,15 @@ namespace IfcGeom { , product_(product) { std::ostringstream oss; - try { oss << "product-" << IfcParse::IfcGlobalId(guid).formatted(); } - catch (std::exception e) - { - oss << "product-cannotfindId"; + + if (type == "IfcProject") { + oss << "project"; + } else { + try { + oss << "product-" << IfcParse::IfcGlobalId(guid).formatted(); + } catch (const std::exception&) { + oss << "product"; + } } if (!_context.empty()) { @@ -138,6 +153,7 @@ namespace IfcGeom { boost::replace_all(ctx, " ", "-"); oss << "-" << ctx; } + _unique_id = oss.str(); } virtual ~Element() {}