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()
: 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.
double offset[3];
double serializer_offset[3];
/// 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).
+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.");
std::string bounds, offset_str;
std::string bounds, offset_str, rotation_str;
#ifdef HAVE_ICU
std::string unicode_mode;
#endif
@@ -332,7 +332,9 @@ int main(int argc, char** argv) {
"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.")
("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",
"Place elements locally in the IfcSite coordinate system, instead of placing "
"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 center_model = vmap.count("center-model") != 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 building_local_placement = vmap.count("building-local-placement") != 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.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 */
if (output_extension == OBJ) {
// 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;
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 (is_tesselated && center_model) {
double* offset = serializer->settings().serializer_offset;
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;
}
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();
std::stringstream msg;
msg << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")";
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;
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 y = *(it++) + (real_t)settings().offset[1];
const real_t z = *(it++) + (real_t)settings().offset[2];
const real_t x = *(it++) + (real_t)settings().serializer_offset[0];
const real_t y = *(it++) + (real_t)settings().serializer_offset[1];
const real_t z = *(it++) + (real_t)settings().serializer_offset[2];
obj_stream << "v " << x << " " << y << " " << z << "\n";
}
+8
View File
@@ -21,6 +21,7 @@
#define IFCGEOM_H
#include <cmath>
#include <array>
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_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include <gp_Quaternion.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Face.hxx>
@@ -108,6 +110,9 @@ private:
double ifc_planeangle_unit;
double modelling_precision;
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
Cache cache;
@@ -184,6 +189,9 @@ public:
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_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire);
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) {
+3
View File
@@ -413,6 +413,9 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& t
else break;
} else break;
}
trsf.PreMultiply(offset_and_rotation);
CACHE(IfcObjectPlacement,l,trsf)
return true;
}
+2
View File
@@ -720,6 +720,8 @@ namespace IfcGeom {
} else if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) {
kernel.set_conversion_placement_rel_to(IfcSchema::Type::IfcSite);
}
kernel.set_offset(settings.offset);
kernel.set_rotation(settings.rotation);
}
bool owns_ifc_file;
+7
View File
@@ -20,6 +20,8 @@
#ifndef IFCGEOMITERATORSETTINGS_H
#define IFCGEOMITERATORSETTINGS_H
#include <array>
#include "ifc_geom_api.h"
#include "../ifcparse/IfcException.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:
SettingField settings_;
double deflection_tolerance_;