feature (WIP) : retrieve full hierarchy

Bug : the element are not at the right location
This commit is contained in:
Balleux Benjamin
2017-05-15 17:45:05 +02:00
parent 4f6e8a7d56
commit be3dbce9f4
5 changed files with 345 additions and 84 deletions
+252 -34
View File
@@ -29,12 +29,19 @@
#include <COLLADASWBaseInputElement.h> #include <COLLADASWBaseInputElement.h>
#include <COLLADASWAsset.h> #include <COLLADASWAsset.h>
#include <boost/lexical_cast.hpp>
#include <string> #include <string>
#include <cmath> #include <cmath>
#include <boost/lexical_cast.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/vector_proxy.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/io.hpp>
using namespace IfcSchema; using namespace IfcSchema;
using namespace boost::numeric::ublas;
static void collada_id(std::string &s) static void collada_id(std::string &s)
{ {
@@ -181,7 +188,7 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::close() {
void ColladaSerializer::ColladaExporter::ColladaScene::add( void ColladaSerializer::ColladaExporter::ColladaScene::add(
const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::string& node_id, const std::string& node_name, const std::string& geom_name,
const std::vector<std::string>& material_ids, const std::vector<real_t>& matrix) const std::vector<std::string>& material_ids, const std::vector<real_t>& posmatrix)
{ {
if (!scene_opened) { if (!scene_opened) {
openVisualScene(scene_id); openVisualScene(scene_id);
@@ -195,13 +202,42 @@ void ColladaSerializer::ColladaExporter::ColladaScene::add(
// The matrix attribute of an entity is basically a 4x3 representation of its ObjectPlacement. // 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. // Note that this placement is absolute, ie it is multiplied with all parent placements.
double matrix_array[4][4] = { double matrix_array[4][4] = {
{ (double)matrix[0], (double)matrix[3], (double)matrix[6], (double)matrix[ 9] }, { (double)posmatrix[0], (double)posmatrix[3], (double)posmatrix[6], (double)posmatrix[ 9] },
{ (double)matrix[1], (double)matrix[4], (double)matrix[7], (double)matrix[10] }, { (double)posmatrix[1], (double)posmatrix[4], (double)posmatrix[7], (double)posmatrix[10] },
{ (double)matrix[2], (double)matrix[5], (double)matrix[8], (double)matrix[11] }, { (double)posmatrix[2], (double)posmatrix[5], (double)posmatrix[8], (double)posmatrix[11] },
{ 0, 0, 0, 1 } { 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 }
};
std::cout << "placement de " << node_name << " | utilisation de " << parentNodes.top()->getNodeName() << "\n";
// 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] += matrix_array[i][k] * matrixStack.top()(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];
}
}
}
matrix_array[0][3] += serializer->settings().offset[0]; matrix_array[0][3] += serializer->settings().offset[0];
matrix_array[1][3] += serializer->settings().offset[1]; matrix_array[1][3] += serializer->settings().offset[1];
matrix_array[2][3] += serializer->settings().offset[2]; matrix_array[2][3] += serializer->settings().offset[2];
@@ -228,33 +264,180 @@ void ColladaSerializer::ColladaExporter::ColladaScene::addParent(const IfcGeom::
} }
const std::vector<real_t> matrix = parent.transformation().matrix().data(); const std::vector<real_t> parentMatrix = parent.transformation().matrix().data();
double matrix_array[4][4] = { double matrix_array[4][4] = {
{ (double)matrix[0], (double)matrix[3], (double)matrix[6], (double)matrix[9] }, { (double)parentMatrix[0], (double)parentMatrix[3], (double)parentMatrix[6], (double)parentMatrix[9] },
{ (double)matrix[1], (double)matrix[4], (double)matrix[7], (double)matrix[10] }, { (double)parentMatrix[1], (double)parentMatrix[4], (double)parentMatrix[7], (double)parentMatrix[10] },
{ (double)matrix[2], (double)matrix[5], (double)matrix[8], (double)matrix[11] }, { (double)parentMatrix[2], (double)parentMatrix[5], (double)parentMatrix[8], (double)parentMatrix[11] },
{ 0, 0, 0, 1 } { 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 }
};
std::cout << "placement de " << parent.name() << "_" << parent.type() << " | utilisation de " << parentNodes.top()->getNodeName() << "\n";
// 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] += matrix_array[i][k] * matrixStack.top()(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 //adding the offset to the matrix
matrix_array[0][3] += serializer->settings().offset[0]; //matrix_array[0][3] += serializer->settings().offset[0];
matrix_array[1][3] += serializer->settings().offset[1]; //matrix_array[1][3] += serializer->settings().offset[1];
matrix_array[2][3] += serializer->settings().offset[2]; //matrix_array[2][3] += serializer->settings().offset[2];
const std::string id = "representation-" + boost::lexical_cast<std::string>(parent.id()); const std::string id = "representation-" + boost::lexical_cast<std::string>(parent.id());
COLLADASW::Node *current_node;
current_node = new COLLADASW::Node(mSW); current_node = new COLLADASW::Node(mSW);
current_node->setNodeId(id); current_node->setNodeId(id);
current_node->setNodeName(parent.name()); current_node->setNodeName(parent.type() + " " + parent.name());
current_node->addMatrix(matrix_array); current_node->addMatrix(matrix_array);
current_node->setType(COLLADASW::Node::NODE); current_node->setType(COLLADASW::Node::NODE);
current_node->start(); current_node->start();
// ==== 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;
}
}
std::cout << " ===== TEST INVERSE " << parent.name() << "===== \n";
double test[4][4];
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
test[i][j] = 0;
}
}
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
for (int k = 0; k < 4; ++k) {
if (false)
{
std::cout << "test [" << i << "][" << j << "] += " << m[i][k] << " * " << inverse[k][j] << "\n";
}
test[i][j] += m[i][k] * inverse[k][j];
}
}
}
std::cout << "matrix array : \n";
std::cout << m[0][0] << " | " << m[0][1] << " | " << m[0][2] << " | " << m[0][3] << " \n ";
std::cout << m[1][0] << " | " << m[1][1] << " | " << m[1][2] << " | " << m[1][3] << " \n ";
std::cout << m[2][0] << " | " << m[2][1] << " | " << m[2][2] << " | " << m[2][3] << " \n ";
std::cout << m[3][0] << " | " << m[3][1] << " | " << m[3][2] << " | " << m[3][3] << " \n ";
std::cout << "det = " << det << "\n";
std::cout << "test array : \n";
std::cout << test[0][0] << " | " << test[0][1] << " | " << test[0][2] << " | " << test[0][3] << " \n ";
std::cout << test[1][0] << " | " << test[1][1] << " | " << test[1][2] << " | " << test[1][3] << " \n ";
std::cout << test[2][0] << " | " << test[2][1] << " | " << test[2][2] << " | " << test[2][3] << " \n ";
std::cout << test[3][0] << " | " << test[3][1] << " | " << test[3][2] << " | " << test[3][3] << " \n ";
matrix<double> save(4, 4);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
save(i, j) = inverse[i][j];
}
}
matrixStack.push(save);
}
else
{
std::cout << "couldn't inverse the position matrix \n";
}
// Add the node to the parent stack
parentNodes.push(current_node);
serializer->parentStackId.push(parent.id());
} }
void ColladaSerializer::ColladaExporter::ColladaScene::closeParent(){ void ColladaSerializer::ColladaExporter::ColladaScene::closeParent()
if (current_node != NULL) { current_node->end(); } {
// Get the top element
COLLADASW::Node *current_node = parentNodes.top();
// Close the node
current_node->end();
// Remove it from the stack
parentNodes.pop();
matrixStack.pop();
serializer->parentStackId.pop();
// Free the memory
delete current_node;
current_node = NULL;
} }
void ColladaSerializer::ColladaExporter::ColladaScene::write() { void ColladaSerializer::ColladaExporter::ColladaScene::write() {
@@ -350,7 +533,7 @@ void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationEleme
const std::string name = serializer->settings().get(SerializerSettings::USE_ELEMENT_GUIDS) ? const std::string name = serializer->settings().get(SerializerSettings::USE_ELEMENT_GUIDS) ?
o->guid() : (serializer->settings().get(SerializerSettings::USE_ELEMENT_NAMES) ? o->guid() : (serializer->settings().get(SerializerSettings::USE_ELEMENT_NAMES) ?
o->name() : (serializer->settings().get(SerializerSettings::USE_ELEMENT_TYPES) ? o->type() + slabSuffix : o->unique_id())); o->name() : (serializer->settings().get(SerializerSettings::USE_ELEMENT_TYPES) ? o->type() + std::to_string(o->id()) + slabSuffix : o->unique_id()));
const std::string representation_id = "representation-" + boost::lexical_cast<std::string>(o->geometry().id()); const std::string representation_id = "representation-" + boost::lexical_cast<std::string>(o->geometry().id());
std::vector<std::string> material_references; std::vector<std::string> material_references;
foreach(const IfcGeom::Material& material, mesh.materials()) { foreach(const IfcGeom::Material& material, mesh.materials()) {
@@ -363,9 +546,9 @@ void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationEleme
material_references.push_back(material_name); material_references.push_back(material_name);
} }
DeferredObject defered = (serializer->settings().get(SerializerSettings::USE_ELEMENT_HIERARCHY) && o->storey() != NULL ? DeferredObject defered = (serializer->settings().get(SerializerSettings::USE_ELEMENT_HIERARCHY) ?
DeferredObject(name, representation_id, o->type(), o->transformation().matrix().data(), mesh.verts(), mesh.normals(), 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->storey())) : 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(), 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())); mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials(), material_references, mesh.uvs()));
deferreds.push_back(defered); deferreds.push_back(defered);
@@ -408,9 +591,11 @@ void ColladaSerializer::ColladaExporter::endDocument() {
std::set<std::string> geometries_written; std::set<std::string> geometries_written;
//if the setting USE_ELEMENT_HIERARCHY is in use, we sort the deferreds objects by their parents. //if the setting USE_ELEMENT_HIERARCHY is in use, we sort the deferreds objects by their parents.
if (use_hierarchy) { if (use_hierarchy) {
std::sort(deferreds.begin(), deferreds.end()); std::sort(deferreds.begin(), deferreds.end());
} }
for (std::vector<DeferredObject>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it) { for (std::vector<DeferredObject>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it) {
if (geometries_written.find(it->representation_id) != geometries_written.end()) { if (geometries_written.find(it->representation_id) != geometries_written.end()) {
continue; continue;
@@ -425,29 +610,62 @@ void ColladaSerializer::ColladaExporter::endDocument() {
for (std::vector<DeferredObject>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it){ for (std::vector<DeferredObject>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it){
const std::string object_name = it->unique_id; const std::string object_name = it->unique_id;
// if the setting USE_ELEMENT_HIERARCHY is used /*
// And if "it" has not parent AND a parent node is opened, OR it has a parent AND another parent node is opened std::cout << "******************************\n";
if (use_hierarchy && ((it->parent == NULL && parent_id != -1) || (it->parent != NULL && parent_id != it->parent->id()))) std::cout << "== " << it->unique_id << " ==\n";
std::cout << " has " << it->parents.size() << " parents \n";
for (unsigned i = 0; i < it->parents.size(); i++)
{ {
//close the parent tag if one is already open. std::cout << "=== " << it->parents.at(i)->name() << " | " << it->parents.at(i)->id() << " ===\n";
if (is_parent_tag_opened){ }
scene.closeParent(); */
}
if (it->parent != NULL){ // TODO : handle the case where a representation object has no parent (Can this really happen ?)
parent_id = it->parent->id(); if (use_hierarchy)
scene.addParent(*it->parent); {
is_parent_tag_opened = true; unsigned parentsNumber = it->parents.size();
bool finished = false;
while (!finished)
{
// If we need to add a parent
if (serializer->parentStackId.size() <= parentsNumber)
{
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())
{
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))); }
// 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
{
// Close the finished nodes. After this we get the first case (serializer->parentStackId.size() <= parentsNumber)
while (serializer->parentStackId.size() > parentsNumber) { scene.closeParent(); }
}
} }
} }
/// @todo redundant information using ID as both ID and Name, maybe omit Name or allow specifying what would be used as the name /// @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->matrix);
} }
//close the last parent tag.
if (is_parent_tag_opened) { //close the remaining parent tags.
scene.closeParent(); while (serializer->parentStackId.size() > 0) { scene.closeParent(); }
};
scene.write(); scene.write();
stream.endDocument(); stream.endDocument();
} }
+36 -31
View File
@@ -45,10 +45,16 @@
#include "../ifcconvert/GeometrySerializer.h" #include "../ifcconvert/GeometrySerializer.h"
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
class ColladaSerializer : public GeometrySerializer class ColladaSerializer : public GeometrySerializer
{ {
// TODO The vast amount of implement details of ColladaSerializer could be hidden to the cpp file. // TODO The vast amount of implement details of ColladaSerializer could be hidden to the cpp file.
private: private:
std::stack<int> parentStackId;
class ColladaExporter class ColladaExporter
{ {
private: private:
@@ -79,7 +85,8 @@ private:
const std::string scene_id; const std::string scene_id;
bool scene_opened; bool scene_opened;
COLLADASW::Node *current_node; std::stack<COLLADASW::Node*> parentNodes;
std::stack<boost::numeric::ublas::matrix<double>> matrixStack;
public: public:
ColladaScene(const std::string& scene_id, COLLADASW::StreamWriter& stream, ColladaSerializer *_serializer) ColladaScene(const std::string& scene_id, COLLADASW::StreamWriter& stream, ColladaSerializer *_serializer)
: COLLADASW::LibraryVisualScenes(&stream) : COLLADASW::LibraryVisualScenes(&stream)
@@ -91,6 +98,7 @@ private:
const std::vector<std::string>& material_ids, const std::vector<real_t>& matrix); const std::vector<std::string>& material_ids, const std::vector<real_t>& matrix);
void addParent(const IfcGeom::Element<real_t>& parent); void addParent(const IfcGeom::Element<real_t>& parent);
void closeParent(); void closeParent();
COLLADASW::Node* GetDirectParent();
void write(); void write();
ColladaSerializer *serializer; ColladaSerializer *serializer;
}; };
@@ -125,39 +133,37 @@ private:
ColladaEffects effects; ColladaEffects effects;
}; };
class DeferredObject { class DeferredObject {
friend bool operator < (const DeferredObject & def_obj1, const DeferredObject & def_obj2) friend bool operator < (const DeferredObject & def_obj1, const DeferredObject & def_obj2)
{ {
// Retrieve the parents of the objects to compare /*
const IfcGeom::Element<real_t>* parent1 = def_obj1.parent; std::cout << "*************** COMPARE ***************\n";
const IfcGeom::Element<real_t>* parent2 = def_obj2.parent; std::cout << "range 1 : " << def_obj1.unique_id << "\n";
for (unsigned i = 0; i < def_obj1.parents.size(); i++)
// If a parent is null
if (parent1 == NULL || parent2 == NULL)
{ {
bool res = (parent1 == NULL) ? true : false; std::cout << "=== " << def_obj1.parents.at(i)->name() << " | " << def_obj1.parents.at(i)->id() << " ===\n";
return res;
} }
// If both parent are not null std::cout << "range 2 : " << def_obj2.unique_id << "\n";
for (unsigned i = 0; i < def_obj2.parents.size(); i++)
{
std::cout << "=== " << def_obj2.parents.at(i)->name() << " | " << def_obj2.parents.at(i)->id() << " ===\n";
}
*/
unsigned size = (def_obj1.parents.size() < def_obj2.parents.size() ? def_obj1.parents.size() : def_obj2.parents.size());
int cpt = 0;
// 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 else
{ {
// Retrieve the IfcBuildingStorey return *(def_obj1.parents.at(cpt)) < *(def_obj2.parents.at(cpt));
IfcSchema::IfcBuildingStorey* storey1 = (IfcSchema::IfcBuildingStorey*)parent1->product();
IfcSchema::IfcBuildingStorey* storey2 = (IfcSchema::IfcBuildingStorey*)parent2->product();
bool res = true;
// Check if the storeys both have an elevation value
if (storey1->hasElevation() && storey2->hasElevation())
{
// Use the elevation in order to sort
res = storey1->Elevation() > storey2->Elevation() ? true : false;
}
// If the evelations are not set, use the names to sort
else { res = parent1->name().compare(parent2->name()) > 0 ? true : false; }
return res;
} }
} }
public: public:
std::string unique_id, representation_id, type; std::string unique_id, representation_id, type;
std::vector<real_t> matrix; std::vector<real_t> matrix;
@@ -169,11 +175,11 @@ private:
std::vector<IfcGeom::Material> materials; std::vector<IfcGeom::Material> materials;
std::vector<std::string> material_references; std::vector<std::string> material_references;
std::vector<real_t> uvs; std::vector<real_t> uvs;
const IfcGeom::Element<real_t>* parent; std::vector<const IfcGeom::Element<real_t>*> parents;
DeferredObject(const std::string& unique_id, const std::string& representation_id, const std::string& type, const std::vector<real_t>& matrix, DeferredObject(const std::string& unique_id, const std::string& representation_id, const std::string& type, const std::vector<real_t>& matrix,
const std::vector<real_t>& vertices, const std::vector<real_t>& normals, const std::vector<int>& faces, const std::vector<real_t>& vertices, const std::vector<real_t>& normals, const std::vector<int>& faces,
const std::vector<int>& edges, const std::vector<int>& material_ids, const std::vector<IfcGeom::Material>& materials, const std::vector<int>& edges, const std::vector<int>& material_ids, const std::vector<IfcGeom::Material>& materials,
const std::vector<std::string>& material_references, const std::vector<real_t>& uvs, const IfcGeom::Element<real_t>& _parent) const std::vector<std::string>& material_references, const std::vector<real_t>& uvs, const std::vector<const IfcGeom::Element<real_t>*>& parent)
: unique_id(unique_id) : unique_id(unique_id)
, representation_id(representation_id) , representation_id(representation_id)
, type(type) , type(type)
@@ -186,7 +192,7 @@ private:
, materials(materials) , materials(materials)
, material_references(material_references) , material_references(material_references)
, uvs(uvs) , uvs(uvs)
, parent(&_parent) , parents(parent)
{ {
} }
@@ -207,9 +213,8 @@ private:
, materials(materials) , materials(materials)
, material_references(material_references) , material_references(material_references)
, uvs(uvs) , uvs(uvs)
, parent(NULL)
{ {
parents.clear();
} }
}; };
COLLADABU::NativeString filename; COLLADABU::NativeString filename;
+1
View File
@@ -110,6 +110,7 @@ boost::optional<std::string> format_attribute(const Argument* argument, IfcUtil:
IfcSchema::IfcLocalPlacement* placement = e->as<IfcSchema::IfcLocalPlacement>(); IfcSchema::IfcLocalPlacement* placement = e->as<IfcSchema::IfcLocalPlacement>();
gp_Trsf trsf; gp_Trsf trsf;
IfcGeom::Kernel kernel; IfcGeom::Kernel kernel;
if (kernel.convert(placement, trsf)) { if (kernel.convert(placement, trsf)) {
std::stringstream stream; std::stringstream stream;
for (int i = 1; i < 5; ++i) { for (int i = 1; i < 5; ++i) {
+22 -5
View File
@@ -81,8 +81,21 @@ namespace IfcGeom {
std::string _unique_id; std::string _unique_id;
Transformation<P> _transformation; Transformation<P> _transformation;
IfcSchema::IfcProduct* product_; IfcSchema::IfcProduct* product_;
const Element<P>* _storey; std::vector<const IfcGeom::Element<P>*> _parents;
public: public:
friend bool operator == (const Element<P> & element1, const Element<P> & element2)
{
//std::cout << " //// Compare == " << element1.name() << element1.id() << " | " << element1.type() << " and " << element2.name() << element2.id() << " | " << element2.type() << "\n";
return element1.id() == element2.id();
}
friend bool operator < (const Element<P> & element1, const Element<P> & element2)
{
//std::cout << " //// Compare < " << element1.name() << element1.id() << " | " << element1.type() << " and " << element2.name() << element2.id() << " | " << element2.type() << "\n";
return element1.id() < element2.id();
}
int id() const { return _id; } int id() const { return _id; }
int parent_id() const { return _parent_id; } int parent_id() const { return _parent_id; }
const std::string& name() const { return _name; } const std::string& name() const { return _name; }
@@ -92,8 +105,8 @@ namespace IfcGeom {
const std::string& unique_id() const { return _unique_id; } const std::string& unique_id() const { return _unique_id; }
const Transformation<P>& transformation() const { return _transformation; } const Transformation<P>& transformation() const { return _transformation; }
IfcSchema::IfcProduct* product() const { return product_; } IfcSchema::IfcProduct* product() const { return product_; }
const Element<P>* storey() const { return _storey; } const std::vector<const IfcGeom::Element<P>*> parents() const { return _parents; }
void SetFloor(const Element<P>* floor) { _storey = floor; } void SetParents(std::vector<const IfcGeom::Element<P>*> newparents) { _parents = newparents; }
Element(const ElementSettings& settings, int id, int parent_id, const std::string& name, const std::string& type, 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) const std::string& guid, const std::string& context, const gp_Trsf& trsf, IfcSchema::IfcProduct *product)
@@ -101,7 +114,12 @@ namespace IfcGeom {
, product_(product) , product_(product)
{ {
std::ostringstream oss; std::ostringstream oss;
oss << "product-" << IfcParse::IfcGlobalId(guid).formatted(); try { oss << "product-" << IfcParse::IfcGlobalId(guid).formatted(); }
catch (std::exception e)
{
oss << "product-cannotfindId";
}
if (!_context.empty()) { if (!_context.empty()) {
std::string ctx = _context; std::string ctx = _context;
std::transform(ctx.begin(), ctx.end(), ctx.begin(), ::tolower); std::transform(ctx.begin(), ctx.end(), ctx.begin(), ::tolower);
@@ -109,7 +127,6 @@ namespace IfcGeom {
oss << "-" << ctx; oss << "-" << ctx;
} }
_unique_id = oss.str(); _unique_id = oss.str();
} }
virtual ~Element() {} virtual ~Element() {}
}; };
+33 -13
View File
@@ -574,14 +574,17 @@ namespace IfcGeom {
else if (current_serialization) { ret = current_serialization; } else if (current_serialization) { ret = current_serialization; }
else if (current_shape_model) { ret = current_shape_model; } else if (current_shape_model) { ret = current_shape_model; }
// If we want to organize the element by floors we need to get the floor of the element // If we want to organize the element considering their hierarchy
if (settings.get(IteratorSettings::SEARCH_FLOOR)) if (settings.get(IteratorSettings::SEARCH_FLOOR))
{ {
// We are going to build a vector with the element parents.
// First, create the parent vector
std::vector<const IfcGeom::Element<P>*> parents;
// if the element has a parent // if the element has a parent
if (ret->parent_id() != -1) if (ret->parent_id() != -1)
{ {
const IfcGeom::Element<P>* parent_object = NULL; const IfcGeom::Element<P>* parent_object = NULL;
bool hasParent = true; bool hasParent = true;
// get the parent // get the parent
@@ -591,20 +594,28 @@ namespace IfcGeom {
hasParent = false; hasParent = false;
} }
// We need to find an IfcBuildingStorey in the parent // Add the previously found parent to the vector
while (parent_object != NULL && parent_object->type() != "IfcBuildingStorey" && hasParent) if (hasParent) parents.insert(parents.begin(), parent_object);
// We need to find all the parents
while (parent_object != NULL && hasParent)
{ {
// Find the next parent
try { parent_object = getObject(parent_object->parent_id()); } try { parent_object = getObject(parent_object->parent_id()); }
catch (std::exception e) catch (std::exception e)
{ {
std::cout << e.what();
hasParent = false; hasParent = false;
} }
hasParent = hasParent && parent_object->parent_id() != 1; // Add the previously found parent to the vector
if (hasParent) parents.insert(parents.begin(), parent_object);
hasParent = hasParent && parent_object->parent_id() != -1;
} }
if (hasParent) { ret->SetFloor(parent_object); } // when done push the parent list in the Element object
else { ret->SetFloor(NULL); } // Set it so null in order to know that we didn't found any IfcBuildingStorey type parent ret->SetParents(parents);
} }
} }
@@ -619,38 +630,47 @@ namespace IfcGeom {
} }
const Element<P>* getObject(int id) { const Element<P>* getObject(int id) {
//std::cout << "1";
gp_Trsf trsf; gp_Trsf trsf;
int parent_id = -1; int parent_id = -1;
std::string instance_type, product_name, product_guid; std::string instance_type, product_name, product_guid;
IfcSchema::IfcProduct* ifc_product = 0; IfcSchema::IfcProduct* ifc_product = 0;
//std::cout << "2";
try { try {
const IfcUtil::IfcBaseClass* ifc_entity = ifc_file->entityById(id); const IfcUtil::IfcBaseClass* ifc_entity = ifc_file->entityById(id);
instance_type = IfcSchema::Type::ToString(ifc_entity->type()); instance_type = IfcSchema::Type::ToString(ifc_entity->type());
if ( ifc_entity->is(IfcSchema::Type::IfcProduct) ) { if ( ifc_entity->is(IfcSchema::Type::IfcProduct) ) {
ifc_product = (IfcSchema::IfcProduct*)ifc_entity; ifc_product = (IfcSchema::IfcProduct*)ifc_entity;
//std::cout << "3";
product_guid = ifc_product->GlobalId(); product_guid = ifc_product->GlobalId();
product_name = ifc_product->hasName() ? ifc_product->Name() : ""; product_name = ifc_product->hasName() ? ifc_product->Name() : "";
parent_id = -1; parent_id = -1;
try { try {
//std::cout << "4";
IfcSchema::IfcObjectDefinition* parent_object = kernel.get_decomposing_entity(ifc_product); IfcSchema::IfcObjectDefinition* parent_object = kernel.get_decomposing_entity(ifc_product);
if (parent_object) { if (parent_object) {
parent_id = parent_object->entity->id(); parent_id = parent_object->entity->id();
} }
} catch (...) {} } catch (...) {}
//std::cout << "5";
try { try {
kernel.convert(ifc_product->ObjectPlacement(), trsf); kernel.convert(ifc_product->ObjectPlacement(), trsf);
} catch (...) {} } catch (...) {}
} }
//std::cout << "6";
} catch(...) {} } catch(...) {}
//std::cout << "7";
ElementSettings element_settings(settings, unit_magnitude, instance_type); ElementSettings element_settings(settings, unit_magnitude, instance_type);
Element<P>* ifc_object = new Element<P>(element_settings, id, parent_id, product_name, instance_type, product_guid, "", trsf, ifc_product);
//std::cout << "8";
//std::cout << "id " << id << "\n";
//std::cout << "parent_id " << parent_id << "\n";
//std::cout << "product_name " << product_name << "\n";
//std::cout << "instance_type " << instance_type << "\n";
//std::cout << "product_guid " << product_guid << "\n";
Element<P>* ifc_object = new Element<P>(element_settings, id, parent_id, product_name, instance_type, product_guid, "", trsf, ifc_product);
//std::cout << "9\n";
return ifc_object; return ifc_object;
} }