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

Applying model-offset in IfcGeom::Kernel makes it work
independently of the serializer.

`model-rotation` was also added to support rotation in the same
manner as `model-offset` supports offset.
This commit is contained in:
Birger Brekke
2019-09-13 15:19:54 +02:00
parent d917e738db
commit e6606e363a
8 changed files with 99 additions and 29 deletions
+2 -2
View File
@@ -56,11 +56,11 @@ public:
SerializerSettings() SerializerSettings()
: precision(DEFAULT_PRECISION) : precision(DEFAULT_PRECISION)
{ {
memset(offset, 0, sizeof(offset)); memset(serializer_offset, 0, sizeof(serializer_offset));
} }
/// Optional offset that is applied to serialized objects, (0,0,0) by default. /// Optional offset that is applied to serialized objects, (0,0,0) by default.
double offset[3]; double serializer_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).
+52 -24
View File
@@ -295,7 +295,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.");
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
@@ -332,7 +332,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.")
@@ -398,6 +400,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;
@@ -618,6 +621,39 @@ int main(int argc, char** argv) {
settings.set_deflection_tolerance(deflection_tolerance); settings.set_deflection_tolerance(deflection_tolerance);
settings.precision = precision; settings.precision = precision;
if (model_offset && center_model) {
Logger::Error("Cannot use --center-model together with --model-offset");
return EXIT_FAILURE;
}
if (model_offset) {
std::array<double,3> &offset = settings.offset;
if (sscanf(offset_str.c_str(), "%lf;%lf;%lf", &offset[0], &offset[1], &offset[2]) != 3) {
cerr_ << "[Error] Invalid use of --model-offset\n" << offset_str;
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 (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" << rotation_str;
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());
}
boost::shared_ptr<GeometrySerializer> serializer; /**< @todo use std::unique_ptr when possible */ boost::shared_ptr<GeometrySerializer> serializer; /**< @todo use std::unique_ptr when possible */
if (output_extension == OBJ) { if (output_extension == OBJ) {
// Do not use temp file for MTL as it's such a small file. // Do not use temp file for MTL as it's such a small file.
@@ -716,31 +752,23 @@ 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)) { if (is_tesselated && center_model) {
double* offset = serializer->settings().offset; double* offset = serializer->settings().serializer_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..."); if (site_local_placement || building_local_placement) {
context_iterator.compute_bounds(); Logger::Error("Cannot use --center-model together with --{site,building}-local-placement");
if (!quiet) Logger::Status("Done!"); return EXIT_FAILURE;
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;
}
} }
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();
std::stringstream msg; std::stringstream msg;
msg << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")"; msg << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")";
Logger::Notice(msg.str()); Logger::Notice(msg.str());
+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++) + (real_t)settings().serializer_offset[0];
const real_t y = *(it++) + (real_t)settings().offset[1]; const real_t y = *(it++) + (real_t)settings().serializer_offset[1];
const real_t z = *(it++) + (real_t)settings().offset[2]; const real_t z = *(it++) + (real_t)settings().serializer_offset[2];
obj_stream << "v " << x << " " << y << " " << z << "\n"; obj_stream << "v " << x << " " << y << " " << z << "\n";
} }
+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>
@@ -108,6 +110,9 @@ private:
double ifc_planeangle_unit; double ifc_planeangle_unit;
double modelling_precision; double modelling_precision;
double dimensionality; double dimensionality;
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
Cache cache; Cache cache;
@@ -184,6 +189,9 @@ public:
GV_DIMENSIONALITY GV_DIMENSIONALITY
}; };
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
@@ -304,6 +304,28 @@ namespace {
} }
} }
} }
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
@@ -413,6 +413,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;
} }
+2
View File
@@ -720,6 +720,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::Type::IfcSite); kernel.set_conversion_placement_rel_to(IfcSchema::Type::IfcSite);
} }
kernel.set_offset(settings.offset);
kernel.set_rotation(settings.rotation);
} }
bool owns_ifc_file; bool owns_ifc_file;
+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"
@@ -128,6 +130,11 @@ namespace IfcGeom
} }
} }
/// Optional offset x,y,z that is applied to all elements, (0,0,0) by default.
std::array<double,3> offset = {0.0, 0.0, 0.0};
/// Optional rotation x,y,z,w that is applied to all elements, (0,0,0,1) by default.
std::array<double,4> rotation = {0.0, 0.0, 0.0, 1.0};
protected: protected:
SettingField settings_; SettingField settings_;
double deflection_tolerance_; double deflection_tolerance_;