Use model-offset in IfcGeom::Kernel and add model-rotation

This commit is contained in:
blocovin
2020-01-31 15:55:04 +01:00
committed by Thomas Krijnen
parent 76e7205692
commit 6e2038c1f5
9 changed files with 97 additions and 47 deletions
+51 -32
View File
@@ -311,7 +311,7 @@ int main(int argc, char** argv) {
"if an object does not have any specified material in the IFC file.") "if an object does not have any specified material in the IFC file.")
("validate", "Checks whether geometrical output conforms to the included explicit quantities."); ("validate", "Checks whether geometrical output conforms to the included explicit quantities.");
std::string bounds, offset_str; std::string bounds, offset_str, rotation_str;
#ifdef HAVE_ICU #ifdef HAVE_ICU
std::string unicode_mode; std::string unicode_mode;
#endif #endif
@@ -348,7 +348,9 @@ int main(int argc, char** argv) {
"Centers the elements upon serialization by applying the center point of " "Centers the elements upon serialization by applying the center point of "
"all placements as an offset. Applicable for OBJ and DAE output. Can take several minutes on large models.") "all placements as an offset. Applicable for OBJ and DAE output. Can take several minutes on large models.")
("model-offset", po::value<std::string>(&offset_str), ("model-offset", po::value<std::string>(&offset_str),
"Applies an arbitrary offset of form 'x;y;z' to all placements. Applicable for OBJ and DAE output.") "Applies an arbitrary offset of form 'x;y;z' to all placements.")
("model-rotation", po::value<std::string>(&rotation_str),
"Applies an arbitrary quaternion rotation of form 'x;y;z;w' to all placements.")
("site-local-placement", ("site-local-placement",
"Place elements locally in the IfcSite coordinate system, instead of placing " "Place elements locally in the IfcSite coordinate system, instead of placing "
"them in the IFC global coords. Applicable for OBJ and DAE output.") "them in the IFC global coords. Applicable for OBJ and DAE output.")
@@ -417,6 +419,7 @@ int main(int argc, char** argv) {
const bool no_normals = vmap.count("no-normals") != 0; const bool no_normals = vmap.count("no-normals") != 0;
const bool center_model = vmap.count("center-model") != 0; const bool center_model = vmap.count("center-model") != 0;
const bool model_offset = vmap.count("model-offset") != 0; const bool model_offset = vmap.count("model-offset") != 0;
const bool model_rotation = vmap.count("model-rotation") != 0;
const bool site_local_placement = vmap.count("site-local-placement") != 0; const bool site_local_placement = vmap.count("site-local-placement") != 0;
const bool building_local_placement = vmap.count("building-local-placement") != 0; const bool building_local_placement = vmap.count("building-local-placement") != 0;
const bool generate_uvs = vmap.count("generate-uvs") != 0; const bool generate_uvs = vmap.count("generate-uvs") != 0;
@@ -758,6 +761,52 @@ int main(int argc, char** argv) {
Logger::SetOutput(quiet ? nullptr : &cout_, &log_stream); Logger::SetOutput(quiet ? nullptr : &cout_, &log_stream);
if (model_rotation) {
std::array<double, 4> &rotation = settings.rotation;
if (sscanf(rotation_str.c_str(), "%lf;%lf;%lf;%lf", &rotation[0], &rotation[1], &rotation[2], &rotation[3]) != 4) {
cerr_ << "[Error] Invalid use of --model-rotation\n";
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
print_options(serializer_options);
return EXIT_FAILURE;
}
std::stringstream msg;
msg << "Using model rotation (" << rotation[0] << "," << rotation[1] << "," << rotation[2] << "," << rotation[3] << ")";
Logger::Notice(msg.str());
}
if (is_tesselated && (center_model || model_offset)) {
std::array<double, 3> &offset = settings.offset;
if (center_model) {
if (site_local_placement || building_local_placement) {
Logger::Error("Cannot use --center-model together with --{site,building}-local-placement");
return EXIT_FAILURE;
}
IfcGeom::Iterator<real_t> tmp_context_iterator(settings, ifc_file, filter_funcs, num_threads);
if (!quiet) Logger::Status("Computing bounds...");
tmp_context_iterator.compute_bounds();
if (!quiet) Logger::Status("Done!");
gp_XYZ center = (tmp_context_iterator.bounds_min() + tmp_context_iterator.bounds_max()) * 0.5;
offset[0] = -center.X();
offset[1] = -center.Y();
offset[2] = -center.Z();
} else {
if (sscanf(offset_str.c_str(), "%lf;%lf;%lf", &offset[0], &offset[1], &offset[2]) != 3) {
cerr_ << "[Error] Invalid use of --model-offset\n";
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
print_options(serializer_options);
return EXIT_FAILURE;
}
}
std::stringstream msg;
msg << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")";
Logger::Notice(msg.str());
}
IfcGeom::Iterator<real_t> context_iterator(settings, ifc_file, filter_funcs, num_threads); IfcGeom::Iterator<real_t> context_iterator(settings, ifc_file, filter_funcs, num_threads);
if (!context_iterator.initialize()) { if (!context_iterator.initialize()) {
/// @todo It would be nice to know and print separate error prints for a case where we found no entities /// @todo It would be nice to know and print separate error prints for a case where we found no entities
@@ -781,36 +830,6 @@ int main(int argc, char** argv) {
int old_progress = quiet ? 0 : -1; int old_progress = quiet ? 0 : -1;
if (is_tesselated && (center_model || model_offset)) {
double* offset = serializer->settings().offset;
if (center_model) {
if (site_local_placement || building_local_placement) {
Logger::Error("Cannot use --center-model together with --{site,building}-local-placement");
return EXIT_FAILURE;
}
if (!quiet) Logger::Status("Computing bounds...");
context_iterator.compute_bounds();
if (!quiet) Logger::Status("Done!");
gp_XYZ center = (context_iterator.bounds_min() + context_iterator.bounds_max()) * 0.5;
offset[0] = -center.X();
offset[1] = -center.Y();
offset[2] = -center.Z();
} else {
if (sscanf(offset_str.c_str(), "%lf;%lf;%lf", &offset[0], &offset[1], &offset[2]) != 3) {
cerr_ << "[Error] Invalid use of --model-offset\n";
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
print_options(serializer_options);
return EXIT_FAILURE;
}
}
std::stringstream msg;
msg << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")";
Logger::Notice(msg.str());
}
if (!quiet) { if (!quiet) {
if (num_threads == 1) { if (num_threads == 1) {
Logger::Status("Creating geometry..."); Logger::Status("Creating geometry...");
+8
View File
@@ -21,6 +21,7 @@
#define IFCGEOM_H #define IFCGEOM_H
#include <cmath> #include <cmath>
#include <array>
static const double ALMOST_ZERO = 1.e-9; static const double ALMOST_ZERO = 1.e-9;
@@ -37,6 +38,7 @@ inline static bool ALMOST_THE_SAME(const T& a, const T& b, double tolerance=ALMO
#include <gp_GTrsf2d.hxx> #include <gp_GTrsf2d.hxx>
#include <gp_Trsf.hxx> #include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx> #include <gp_Trsf2d.hxx>
#include <gp_Quaternion.hxx>
#include <TopoDS.hxx> #include <TopoDS.hxx>
#include <TopoDS_Wire.hxx> #include <TopoDS_Wire.hxx>
#include <TopoDS_Face.hxx> #include <TopoDS_Face.hxx>
@@ -222,6 +224,9 @@ private:
double modelling_precision; double modelling_precision;
double dimensionality; double dimensionality;
double layerset_first; double layerset_first;
gp_Vec offset = gp_Vec{0.0, 0.0, 0.0};
gp_Quaternion rotation = gp_Quaternion{};
gp_Trsf offset_and_rotation = gp_Trsf();
#ifndef NO_CACHE #ifndef NO_CACHE
MAKE_TYPE_NAME(Cache) cache; MAKE_TYPE_NAME(Cache) cache;
@@ -264,6 +269,9 @@ public:
return *this; return *this;
} }
void set_offset(const std::array<double, 3>& offset);
void set_rotation(const std::array<double, 4>& rotation);
bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face); bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);
bool convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire); bool convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire);
bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result); bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result);
+22
View File
@@ -505,6 +505,28 @@ namespace {
usd.Build(); usd.Build();
return usd.Shape(); return usd.Shape();
} }
gp_Trsf combine_offset_and_rotation(const gp_Vec &offset, const gp_Quaternion& rotation) {
auto offset_transform = gp_Trsf{};
offset_transform.SetTranslation(offset);
auto rotation_transform = gp_Trsf{};
rotation_transform.SetRotation(rotation);
return rotation_transform * offset_transform;
}
}
void IfcGeom::Kernel::set_offset(const std::array<double, 3> &p_offset) {
offset = gp_Vec(p_offset[0], p_offset[1], p_offset[2]);
offset_and_rotation = combine_offset_and_rotation(offset, rotation);
}
void IfcGeom::Kernel::set_rotation(const std::array<double, 4> &p_rotation) {
rotation = gp_Quaternion(p_rotation[0], p_rotation[1], p_rotation[2], p_rotation[3]);
offset_and_rotation = combine_offset_and_rotation(offset, rotation);
} }
bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) { bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
+3
View File
@@ -418,6 +418,9 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& t
else break; else break;
} else break; } else break;
} }
trsf.PreMultiply(offset_and_rotation);
CACHE(IfcObjectPlacement,l,trsf) CACHE(IfcObjectPlacement,l,trsf)
return true; return true;
} }
@@ -985,6 +985,8 @@ namespace IfcGeom {
} else if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) { } else if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) {
kernel.set_conversion_placement_rel_to(&IfcSchema::IfcSite::Class()); kernel.set_conversion_placement_rel_to(&IfcSchema::IfcSite::Class());
} }
kernel.set_offset(settings.offset);
kernel.set_rotation(settings.rotation);
} }
public: public:
+7
View File
@@ -20,6 +20,8 @@
#ifndef IFCGEOMITERATORSETTINGS_H #ifndef IFCGEOMITERATORSETTINGS_H
#define IFCGEOMITERATORSETTINGS_H #define IFCGEOMITERATORSETTINGS_H
#include <array>
#include "ifc_geom_api.h" #include "ifc_geom_api.h"
#include "../ifcparse/IfcException.h" #include "../ifcparse/IfcException.h"
#include "../ifcparse/IfcBaseClass.h" #include "../ifcparse/IfcBaseClass.h"
@@ -132,6 +134,11 @@ namespace IfcGeom
} }
} }
/// Optional offset that is applied to serialized objects, (0,0,0) by default.
std::array<double,3> offset = std::array<double,3>{0.0, 0.0, 0.0};
/// Optional rotation that is applied to serialized objects, (0,0,0,1) by default.
std::array<double,4> rotation = std::array<double,4>{0.0, 0.0, 0.0, 1.0};
protected: protected:
SettingField settings_; SettingField settings_;
double deflection_tolerance_; double deflection_tolerance_;
-5
View File
@@ -213,11 +213,6 @@ void ColladaSerializer::ColladaExporter::ColladaScene::add(
{ 0, 0, 0, 1 } { 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; delete relative_trsf;
node.start(); node.start();
+1 -7
View File
@@ -55,13 +55,7 @@ public:
}; };
SerializerSettings() SerializerSettings()
: precision(DEFAULT_PRECISION) : precision(DEFAULT_PRECISION) { }
{
memset(offset, 0, sizeof(offset));
}
/// Optional offset that is applied to serialized objects, (0,0,0) by default.
double offset[3];
/// Sets the precision used to format floating-point values, 15 by default. /// Sets the precision used to format floating-point values, 15 by default.
/// Use a negative value to use the system's default precision (should be 6 typically). /// Use a negative value to use the system's default precision (should be 6 typically).
+3 -3
View File
@@ -93,9 +93,9 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement<real_t>*
const int vcount = (int)mesh.verts().size() / 3; const int vcount = (int)mesh.verts().size() / 3;
for ( std::vector<real_t>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) { for ( std::vector<real_t>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) {
const real_t x = *(it++) + (real_t)settings().offset[0]; const real_t x = *(it++);
const real_t y = *(it++) + (real_t)settings().offset[1]; const real_t y = *(it++);
const real_t z = *(it++) + (real_t)settings().offset[2]; const real_t z = *(it++);
obj_stream << "v " << x << " " << y << " " << z << "\n"; obj_stream << "v " << x << " " << y << " " << z << "\n";
} }