Add center-model-geometry

This commit is contained in:
blocovin
2020-02-12 11:38:08 +01:00
committed by Thomas Krijnen
parent 5fbb324d7d
commit 1018118341
4 changed files with 80 additions and 37 deletions
+28 -8
View File
@@ -256,6 +256,8 @@ int main(int argc, char** argv) {
("center-model", ("center-model",
"Centers the elements by applying the center point of all placements as an offset." "Centers the elements by applying the center point of all placements as an offset."
"Can take several minutes on large models.") "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<std::string>(&offset_str), ("model-offset", po::value<std::string>(&offset_str),
"Applies an arbitrary offset of form 'x;y;z' to all placements.") "Applies an arbitrary offset of form 'x;y;z' to all placements.")
("model-rotation", po::value<std::string>(&rotation_str), ("model-rotation", po::value<std::string>(&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 use_element_hierarchy = vmap.count("use-element-hierarchy") != 0;
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 center_model_geometry = vmap.count("center-model-geometry") != 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 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;
@@ -722,7 +725,7 @@ int main(int argc, char** argv) {
if (generate_uvs) { if (generate_uvs) {
Logger::Notice("Generate UVs setting ignored when writing non-tesselated output"); 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"); 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()); Logger::Notice(msg.str());
} }
if (is_tesselated && (center_model || model_offset)) { if (is_tesselated && (center_model || center_model_geometry || model_offset)) {
std::array<double, 3> &offset = settings.offset; std::array<double, 3> &offset = settings.offset;
if (center_model) { if (center_model || center_model_geometry) {
if (site_local_placement || building_local_placement) { 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; return EXIT_FAILURE;
} }
IfcGeom::Iterator<real_t> tmp_context_iterator(settings, ifc_file, filter_funcs, num_threads); IfcGeom::Iterator<real_t> tmp_context_iterator(settings, ifc_file, filter_funcs, num_threads);
if (!quiet) Logger::Status("Computing bounds..."); time_t start, end;
tmp_context_iterator.compute_bounds(); time(&start);
if (!quiet) Logger::Status("Done!"); if (!quiet) Logger::Status("Computing bounds...");
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; gp_XYZ center = (tmp_context_iterator.bounds_min() + tmp_context_iterator.bounds_max()) * 0.5;
offset[0] = -center.X(); offset[0] = -center.X();
@@ -798,7 +818,7 @@ int main(int argc, char** argv) {
} }
std::stringstream msg; 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()); Logger::Notice(msg.str());
} }
+50 -27
View File
@@ -496,42 +496,65 @@ namespace IfcGeom {
/// Computes model's bounding box (bounds_min and bounds_max). /// Computes model's bounding box (bounds_min and bounds_max).
/// @note Can take several minutes for large files. /// @note Can take several minutes for large files.
void compute_bounds() void compute_bounds(bool with_geometry)
{ {
for (int i = 1; i < 4; ++i) { for (int i = 1; i < 4; ++i) {
bounds_min_.SetCoord(i, std::numeric_limits<double>::infinity()); bounds_min_.SetCoord(i, std::numeric_limits<double>::infinity());
bounds_max_.SetCoord(i, -std::numeric_limits<double>::infinity()); bounds_max_.SetCoord(i, -std::numeric_limits<double>::infinity());
} }
IfcSchema::IfcProduct::list::ptr products = ifc_file->instances_by_type<IfcSchema::IfcProduct>(); if (with_geometry) {
for (IfcSchema::IfcProduct::list::it iter = products->begin(); iter != products->end(); ++iter) { size_t num_created = 0;
IfcSchema::IfcProduct* product = *iter; do {
if (product->hasObjectPlacement()) { IfcGeom::Element<P, PP>* geom_object = get();
// Use a fresh trsf every time in order to prevent the result to be concatenated const IfcGeom::TriangulationElement<P, PP>* o = static_cast<const IfcGeom::TriangulationElement<P, PP>*>(geom_object);
gp_Trsf trsf; const IfcGeom::Representation::Triangulation<P>& mesh = o->geometry();
bool success = false; const gp_XYZ& pos = o->transformation().data().TranslationPart();
try { for (typename std::vector<P>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end();) {
success = kernel.convert(product->ObjectPlacement(), trsf); const P x = *(it++);
} catch (const std::exception& e) { const P y = *(it++);
Logger::Error(e); const P z = *(it++);
} catch (...) {
Logger::Error("Failed to construct placement");
}
if (!success) { bounds_min_.SetX(std::min(bounds_min_.X(), pos.X() + x));
continue; 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<IfcSchema::IfcProduct>();
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;
const gp_XYZ& pos = trsf.TranslationPart(); try {
bounds_min_.SetX(std::min(bounds_min_.X(), pos.X())); success = kernel.convert(product->ObjectPlacement(), trsf);
bounds_min_.SetY(std::min(bounds_min_.Y(), pos.Y())); } catch (const std::exception& e) {
bounds_min_.SetZ(std::min(bounds_min_.Z(), pos.Z())); Logger::Error(e);
bounds_max_.SetX(std::max(bounds_max_.X(), pos.X())); } catch (...) {
bounds_max_.SetY(std::max(bounds_max_.Y(), pos.Y())); Logger::Error("Failed to construct placement");
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 { int progress() const {
@@ -118,7 +118,7 @@ namespace IfcGeom {
int progress() const { return implementation_->progress(); } 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_min() const { return implementation_->bounds_min(); }
const gp_XYZ& bounds_max() const { return implementation_->bounds_max(); } const gp_XYZ& bounds_max() const { return implementation_->bounds_max(); }
@@ -62,7 +62,7 @@ namespace IfcGeom {
class IteratorImplementation { class IteratorImplementation {
public: public:
virtual bool initialize() = 0; 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_min() const = 0;
virtual const gp_XYZ& bounds_max() const = 0; virtual const gp_XYZ& bounds_max() const = 0;
virtual int progress() const = 0; virtual int progress() const = 0;