mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 14:41:25 +00:00
Add center-model-geometry
This commit is contained in:
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user