From 10181183419205c301ad3ecdfdce62c808e470c2 Mon Sep 17 00:00:00 2001 From: blocovin Date: Wed, 12 Feb 2020 11:38:08 +0100 Subject: [PATCH] Add center-model-geometry --- src/ifcconvert/IfcConvert.cpp | 36 +++++++-- src/ifcgeom/IfcGeomIteratorImplementation.h | 77 ++++++++++++------- src/ifcgeom_schema_agnostic/IfcGeomIterator.h | 2 +- .../IteratorImplementation.h | 2 +- 4 files changed, 80 insertions(+), 37 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 4ce51acc09..f1c6b7de09 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -256,6 +256,8 @@ int main(int argc, char** argv) { ("center-model", "Centers the elements by applying the center point of all placements as an offset." "Can take several minutes on large models.") + ("center-model-geometry", + "Centers the elements by applying the center point of all mesh vertices as an offset.") ("model-offset", po::value(&offset_str), "Applies an arbitrary offset of form 'x;y;z' to all placements.") ("model-rotation", po::value(&rotation_str), @@ -424,6 +426,7 @@ int main(int argc, char** argv) { const bool use_element_hierarchy = vmap.count("use-element-hierarchy") != 0; const bool no_normals = vmap.count("no-normals") != 0; const bool center_model = vmap.count("center-model") != 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; const bool site_local_placement = vmap.count("site-local-placement") != 0; @@ -722,7 +725,7 @@ int main(int argc, char** argv) { if (generate_uvs) { Logger::Notice("Generate UVs setting ignored when writing non-tesselated output"); } - if (center_model || model_offset) { + if (center_model || center_model_geometry || model_offset) { Logger::Notice("Centering/offsetting model setting ignored when writing non-tesselated output"); } @@ -770,19 +773,36 @@ int main(int argc, char** argv) { Logger::Notice(msg.str()); } - if (is_tesselated && (center_model || model_offset)) { + if (is_tesselated && (center_model || center_model_geometry || model_offset)) { std::array &offset = settings.offset; - if (center_model) { + if (center_model || center_model_geometry) { if (site_local_placement || building_local_placement) { - Logger::Error("Cannot use --center-model together with --{site,building}-local-placement"); + Logger::Error("Cannot use --center-model or --center-model-geometry together with --{site,building}-local-placement"); return EXIT_FAILURE; } IfcGeom::Iterator tmp_context_iterator(settings, ifc_file, filter_funcs, num_threads); + + time_t start, end; + time(&start); + if (!quiet) Logger::Status("Computing bounds..."); - if (!quiet) Logger::Status("Computing bounds..."); - tmp_context_iterator.compute_bounds(); - if (!quiet) Logger::Status("Done!"); + if (center_model_geometry) { + if (!tmp_context_iterator.initialize()) { + /// @todo It would be nice to know and print separate error prints for a case where we found no entities + /// and for a case we found no entities that satisfy our filtering criteria. + Logger::Notice("No geometrical elements found or none succesfully converted"); + serializer.reset(); + IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename)); + write_log(!quiet); + return EXIT_FAILURE; + } + } + + tmp_context_iterator.compute_bounds(center_model_geometry); + + time(&end); + if (!quiet) Logger::Status("Done ! Bounds computed in " + format_duration(start, end)); gp_XYZ center = (tmp_context_iterator.bounds_min() + tmp_context_iterator.bounds_max()) * 0.5; offset[0] = -center.X(); @@ -798,7 +818,7 @@ int main(int argc, char** argv) { } std::stringstream msg; - msg << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")"; + msg << std::setprecision (17) << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")"; Logger::Notice(msg.str()); } diff --git a/src/ifcgeom/IfcGeomIteratorImplementation.h b/src/ifcgeom/IfcGeomIteratorImplementation.h index 82b50962eb..172f19a837 100644 --- a/src/ifcgeom/IfcGeomIteratorImplementation.h +++ b/src/ifcgeom/IfcGeomIteratorImplementation.h @@ -496,42 +496,65 @@ namespace IfcGeom { /// Computes model's bounding box (bounds_min and bounds_max). /// @note Can take several minutes for large files. - void compute_bounds() + void compute_bounds(bool with_geometry) { for (int i = 1; i < 4; ++i) { bounds_min_.SetCoord(i, std::numeric_limits::infinity()); bounds_max_.SetCoord(i, -std::numeric_limits::infinity()); } - IfcSchema::IfcProduct::list::ptr products = ifc_file->instances_by_type(); - for (IfcSchema::IfcProduct::list::it iter = products->begin(); iter != products->end(); ++iter) { - IfcSchema::IfcProduct* product = *iter; - if (product->hasObjectPlacement()) { - // Use a fresh trsf every time in order to prevent the result to be concatenated - gp_Trsf trsf; - bool success = false; + if (with_geometry) { + size_t num_created = 0; + do { + IfcGeom::Element* geom_object = get(); + const IfcGeom::TriangulationElement* o = static_cast*>(geom_object); + const IfcGeom::Representation::Triangulation

& mesh = o->geometry(); + const gp_XYZ& pos = o->transformation().data().TranslationPart(); - try { - success = kernel.convert(product->ObjectPlacement(), trsf); - } catch (const std::exception& e) { - Logger::Error(e); - } catch (...) { - Logger::Error("Failed to construct placement"); - } + for (typename std::vector

::const_iterator it = mesh.verts().begin(); it != mesh.verts().end();) { + const P x = *(it++); + const P y = *(it++); + const P z = *(it++); + + bounds_min_.SetX(std::min(bounds_min_.X(), pos.X() + x)); + bounds_min_.SetY(std::min(bounds_min_.Y(), pos.Y() + y)); + bounds_min_.SetZ(std::min(bounds_min_.Z(), pos.Z() + z)); + bounds_max_.SetX(std::max(bounds_max_.X(), pos.X() + x)); + bounds_max_.SetY(std::max(bounds_max_.Y(), pos.Y() + y)); + bounds_max_.SetZ(std::max(bounds_max_.Z(), pos.Z() + z)); + } + } while (++num_created, next()); + } else { + IfcSchema::IfcProduct::list::ptr products = ifc_file->instances_by_type(); + for (IfcSchema::IfcProduct::list::it iter = products->begin(); iter != products->end(); ++iter) { + IfcSchema::IfcProduct* product = *iter; + if (product->hasObjectPlacement()) { + // Use a fresh trsf every time in order to prevent the result to be concatenated + gp_Trsf trsf; + bool success = false; - if (!success) { - continue; - } + try { + success = kernel.convert(product->ObjectPlacement(), trsf); + } catch (const std::exception& e) { + Logger::Error(e); + } catch (...) { + Logger::Error("Failed to construct placement"); + } - const gp_XYZ& pos = trsf.TranslationPart(); - bounds_min_.SetX(std::min(bounds_min_.X(), pos.X())); - bounds_min_.SetY(std::min(bounds_min_.Y(), pos.Y())); - bounds_min_.SetZ(std::min(bounds_min_.Z(), pos.Z())); - bounds_max_.SetX(std::max(bounds_max_.X(), pos.X())); - bounds_max_.SetY(std::max(bounds_max_.Y(), pos.Y())); - bounds_max_.SetZ(std::max(bounds_max_.Z(), pos.Z())); - } - } + if (!success) { + continue; + } + + const gp_XYZ& pos = trsf.TranslationPart(); + bounds_min_.SetX(std::min(bounds_min_.X(), pos.X())); + bounds_min_.SetY(std::min(bounds_min_.Y(), pos.Y())); + bounds_min_.SetZ(std::min(bounds_min_.Z(), pos.Z())); + bounds_max_.SetX(std::max(bounds_max_.X(), pos.X())); + bounds_max_.SetY(std::max(bounds_max_.Y(), pos.Y())); + bounds_max_.SetZ(std::max(bounds_max_.Z(), pos.Z())); + } + } + } } int progress() const { diff --git a/src/ifcgeom_schema_agnostic/IfcGeomIterator.h b/src/ifcgeom_schema_agnostic/IfcGeomIterator.h index 58a2b21d1b..3d86660cd8 100644 --- a/src/ifcgeom_schema_agnostic/IfcGeomIterator.h +++ b/src/ifcgeom_schema_agnostic/IfcGeomIterator.h @@ -118,7 +118,7 @@ namespace IfcGeom { int progress() const { return implementation_->progress(); } - void compute_bounds() { implementation_->compute_bounds(); } + void compute_bounds(bool with_geometry) { implementation_->compute_bounds(with_geometry); } const gp_XYZ& bounds_min() const { return implementation_->bounds_min(); } const gp_XYZ& bounds_max() const { return implementation_->bounds_max(); } diff --git a/src/ifcgeom_schema_agnostic/IteratorImplementation.h b/src/ifcgeom_schema_agnostic/IteratorImplementation.h index 0d6ec96c4c..34badca50e 100644 --- a/src/ifcgeom_schema_agnostic/IteratorImplementation.h +++ b/src/ifcgeom_schema_agnostic/IteratorImplementation.h @@ -62,7 +62,7 @@ namespace IfcGeom { class IteratorImplementation { public: virtual bool initialize() = 0; - virtual void compute_bounds() = 0; + virtual void compute_bounds(bool with_geometry) = 0; virtual const gp_XYZ& bounds_min() const = 0; virtual const gp_XYZ& bounds_max() const = 0; virtual int progress() const = 0;