Reinstate old bespoke model-offset/rotation parsing in IfcConvert #6290

This commit is contained in:
Thomas Krijnen
2025-03-19 11:42:11 +01:00
parent 26b55216ca
commit e658b00768
2 changed files with 54 additions and 7 deletions
+45 -1
View File
@@ -298,6 +298,10 @@ int main(int argc, char** argv) {
"Can take several minutes on large models.") "Can take several minutes on large models.")
("center-model-geometry", ("center-model-geometry",
"Centers the elements by applying the center point of all mesh vertices as an offset.") "Centers the elements by applying the center point of all mesh vertices as an offset.")
("model-offset", po::value<std::string>(&offset_str),
"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.")
("include", po::value<inclusion_filter>(&include_filter)->multitoken(), ("include", po::value<inclusion_filter>(&include_filter)->multitoken(),
"Specifies that the instances that match a specific filtering criteria are to be included in the geometrical output:\n" "Specifies that the instances that match a specific filtering criteria are to be included in the geometrical output:\n"
"1) 'entities': the following list of types should be included. SVG output defaults " "1) 'entities': the following list of types should be included. SVG output defaults "
@@ -448,6 +452,8 @@ int main(int argc, char** argv) {
const bool center_model = vmap.count("center-model") != 0; const bool center_model = vmap.count("center-model") != 0;
const bool center_model_geometry = vmap.count("center-model-geometry") != 0; const bool center_model_geometry = vmap.count("center-model-geometry") != 0;
const bool model_offset = vmap.count("model-offset") != 0;
const bool model_rotation = vmap.count("model-rotation") != 0;
if (!quiet || vmap.count("version")) { if (!quiet || vmap.count("version")) {
print_version(); print_version();
@@ -925,6 +931,44 @@ int main(int argc, char** argv) {
Logger::SetOutput(quiet ? nullptr : &cout_, vcounter.count > 1 ? &cout_ : &log_stream); Logger::SetOutput(quiet ? nullptr : &cout_, vcounter.count > 1 ? &cout_ : &log_stream);
} }
if (model_rotation) {
std::vector<double> rotation(4);
int n = 0;
if (sscanf(rotation_str.c_str(), "%lf;%lf;%lf;%lf %n", &rotation[0], &rotation[1], &rotation[2], &rotation[3], &n) != 4 || n != rotation_str.size()) {
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());
geometry_settings.get<ifcopenshell::geometry::settings::ModelRotation>().value = rotation;
}
if (model_offset && (center_model || center_model_geometry)) {
Logger::Notice("--model-offset ignored with --center-model or --center-model-geometry");
}
if (model_offset && !(center_model || center_model_geometry)) {
std::vector<double> offset(3);
int n = 0;
if (sscanf(offset_str.c_str(), "%lf;%lf;%lf %n", &offset[0], &offset[1], &offset[2], &n) != 3 || n != offset_str.size()) {
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 << std::setprecision(std::numeric_limits<double>::max_digits10) << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")";
Logger::Notice(msg.str());
geometry_settings.get<ifcopenshell::geometry::settings::ModelOffset>().value = offset;
}
if (is_tesselated && (center_model || center_model_geometry)) { if (is_tesselated && (center_model || center_model_geometry)) {
std::vector<double> offset(3); std::vector<double> offset(3);
@@ -957,7 +1001,7 @@ int main(int argc, char** argv) {
offset[2] = -center(2); offset[2] = -center(2);
std::stringstream msg; std::stringstream msg;
msg << std::setprecision (std::numeric_limits< double >::max_digits10) << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")"; msg << std::setprecision (std::numeric_limits<double>::max_digits10) << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")";
Logger::Notice(msg.str()); Logger::Notice(msg.str());
geometry_settings.get<ifcopenshell::geometry::settings::ModelOffset>().value = offset; geometry_settings.get<ifcopenshell::geometry::settings::ModelOffset>().value = offset;
+9 -6
View File
@@ -47,7 +47,9 @@ namespace ifcopenshell {
// boost program options does not seem to handle optional<vector> types, so in case // boost program options does not seem to handle optional<vector> types, so in case
// of vector settings we need to strip away the optional and detect argument presence // of vector settings we need to strip away the optional and detect argument presence
// with !vector::empty() // with !vector::empty()
std::conditional_t<std::is_same_v<T, std::vector<double>>, T, boost::optional<T>> value; // tfk: we no longer do this because negative values can not be passed like this as boost confuses them with options
// std::conditional_t<std::is_same_v<T, std::vector<double>>, T, boost::optional<T>> value;
boost::optional<T> value;
SettingBase() {} SettingBase() {}
@@ -64,14 +66,15 @@ namespace ifcopenshell {
value.emplace(); value.emplace();
desc.add_options()(Derived::name, apply_default(po::bool_switch(&*value)), Derived::description); desc.add_options()(Derived::name, apply_default(po::bool_switch(&*value)), Derived::description);
} else if constexpr (std::is_same_v<T, std::vector<double>>) { } else if constexpr (std::is_same_v<T, std::vector<double>>) {
desc.add_options()(Derived::name, apply_default(po::value(&value)->multitoken()), Derived::description); // these options have to be supplied manually in IfcConvert.cpp
// desc.add_options()(Derived::name, apply_default(po::value(&value)->multitoken()), Derived::description);
} else { } else {
desc.add_options()(Derived::name, apply_default(po::value(&value)), Derived::description); desc.add_options()(Derived::name, apply_default(po::value(&value)), Derived::description);
} }
} }
T get() const { T get() const {
if constexpr (std::is_same_v<T, std::vector<double>>) { if constexpr (false && std::is_same_v<T, std::vector<double>>) {
return value; return value;
} else { } else {
if (value) { if (value) {
@@ -85,7 +88,7 @@ namespace ifcopenshell {
} }
bool has() const { bool has() const {
if constexpr (std::is_same_v<T, std::vector<double>>) { if constexpr (false && std::is_same_v<T, std::vector<double>>) {
return !value.empty(); return !value.empty();
} else { } else {
// @todo this is not reliable, better use vmap[...].defaulted() // @todo this is not reliable, better use vmap[...].defaulted()
@@ -391,12 +394,12 @@ namespace ifcopenshell {
struct ModelOffset : public SettingBase<ModelOffset, std::vector<double>> { struct ModelOffset : public SettingBase<ModelOffset, std::vector<double>> {
static constexpr const char* const name = "model-offset"; static constexpr const char* const name = "model-offset";
static constexpr const char* const description = "Applies an arbitrary offset of form 'x,y,z' to all placements."; static constexpr const char* const description = "Applies an arbitrary offset of form x,y,z to all placements.";
}; };
struct ModelRotation : public SettingBase<ModelRotation, std::vector<double>> { struct ModelRotation : public SettingBase<ModelRotation, std::vector<double>> {
static constexpr const char* const name = "model-rotation"; static constexpr const char* const name = "model-rotation";
static constexpr const char* const description = "Applies an arbitrary quaternion rotation of form 'x,y,z,w' to all placements."; static constexpr const char* const description = "Applies an arbitrary quaternion rotation of form x,y,z,w to all placements.";
}; };
enum TriangulationMethod { enum TriangulationMethod {