diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 86ec41f731..3aa28b77ff 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -47,10 +47,6 @@ #include #include -#define INF std::numeric_limits::infinity() -real_t bounds_min[3] = { INF, INF, INF }; -real_t bounds_max[3] = { -INF, -INF, -INF }; - #if USE_VLD #include #endif @@ -198,8 +194,8 @@ int main(int argc, char** argv) { "Use material names instead of unique IDs for naming materials upon serialization. " "Applicable for OBJ and DAE output.") ("center-model", - "Centers the models upon serialization by applying the center point of " - "the scene bounds as an offset. Applicable only for DAE output currently."); + "Centers the elements upon serialization by applying the center point of " + "all placements as an offset. Applicable for OBJ and DAE output."); boost::program_options::options_description cmdline_options; cmdline_options.add(generic_options).add(fileio_options).add(geom_options).add(serializer_options); @@ -375,21 +371,18 @@ int main(int argc, char** argv) { return 1; } - if (output_extension != ".dae") { - if (center_model) { - Logger::Message(Logger::LOG_NOTICE, "--center-model setting ignored for non-DAE output"); - settings.set(IfcGeom::IteratorSettings::CENTER_MODEL, false); - center_model = false; - } - } - - if (!serializer->isTesselated()) { + const bool is_tesselated = serializer->isTesselated(); // isTesselated() doesn't change at run-time + if (!is_tesselated) { if (weld_vertices) { Logger::Message(Logger::LOG_NOTICE, "Weld vertices setting ignored when writing non-tesselated output"); } if (generate_uvs) { Logger::Message(Logger::LOG_NOTICE, "Generate UVs setting ignored when writing non-tesselated output"); } + if (center_model) { + Logger::Message(Logger::LOG_NOTICE, "Center model setting ignored when writing non-tesselated output"); + } + settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true); } @@ -453,42 +446,31 @@ int main(int argc, char** argv) { const int progress = context_iterator.progress() / 2; if (old_progress != progress) Logger::ProgressBar(progress); old_progress = progress; - - if (center_model) { - const std::vector& pos = geom_object->transformation().matrix().data(); - bounds_min[0] = std::min(bounds_min[0], pos[9]); - bounds_min[1] = std::min(bounds_min[1], pos[10]); - bounds_min[2] = std::min(bounds_min[2], pos[11]); - bounds_max[0] = std::max(bounds_max[0], pos[9]); - bounds_max[1] = std::max(bounds_max[1], pos[10]); - bounds_max[2] = std::max(bounds_max[2], pos[11]); - } } while (context_iterator.next()); Logger::Status("\rDone creating geometry (" + boost::lexical_cast(geometries.size()) + " objects) "); if (center_model) { - settings.offset[0] = -(bounds_min[0] + bounds_max[0]) * real_t(0.5); - settings.offset[1] = -(bounds_min[1] + bounds_max[1]) * real_t(0.5); - settings.offset[2] = -(bounds_min[2] + bounds_max[2]) * real_t(0.5); - //printf("Bounds min. (%g, %g, %g)\n", bounds_min[0], bounds_min[1], bounds_min[2]); - //printf("Bounds max. (%g, %g, %g)\n", bounds_max[0], bounds_max[1], bounds_max[2]); - printf("Using model offset (%g, %g, %g)\n", settings.offset[0], settings.offset[1], settings.offset[2]); //TODO Logger::Message(Logger::LOG_NOTICE, ...); + double* offset = serializer->settings().offset; + 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(); + //printf("Bounds min. (%g, %g, %g)\n", context_iterator.bounds_min().X(), context_iterator.bounds_min().Y(), context_iterator.bounds_min().Z()); + //printf("Bounds max. (%g, %g, %g)\n", context_iterator.bounds_min().X(), context_iterator.bounds_min().X(), context_iterator.bounds_min().Z()); + printf("Using model offset (%g, %g, %g)\n", offset[0], offset[1], offset[2]); //TODO Logger::Message(Logger::LOG_NOTICE, ...); } Logger::Status("Serializing geometry..."); - if (serializer->isTesselated()) { // isTesselated() doesn't change at run-time - foreach(const IfcGeom::Element* geom, geometries) { + foreach(const IfcGeom::Element* geom, geometries) { + if (is_tesselated) { serializer->write(static_cast*>(geom)); - delete geom; - } - } else { - foreach(const IfcGeom::Element* geom, geometries) { + } else { serializer->write(static_cast*>(geom)); - delete geom; } + delete geom; } serializer->finalize(); diff --git a/src/ifcconvert/WavefrontObjSerializer.cpp b/src/ifcconvert/WavefrontObjSerializer.cpp index 896edef76e..3be2357f39 100644 --- a/src/ifcconvert/WavefrontObjSerializer.cpp +++ b/src/ifcconvert/WavefrontObjSerializer.cpp @@ -84,9 +84,9 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* const int vcount = (int)mesh.verts().size() / 3; for ( std::vector::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) { - const real_t x = *(it++); - const real_t y = *(it++); - const real_t z = *(it++); + 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]; obj_stream << "v " << x << " " << y << " " << z << "\n"; } diff --git a/src/ifcconvert/WavefrontObjSerializer.h b/src/ifcconvert/WavefrontObjSerializer.h index c8e87f6cdd..52117c62a3 100644 --- a/src/ifcconvert/WavefrontObjSerializer.h +++ b/src/ifcconvert/WavefrontObjSerializer.h @@ -26,6 +26,7 @@ #include "../ifcconvert/GeometrySerializer.h" +// http://people.sc.fsu.edu/~jburkardt/txt/obj_format.txt class WaveFrontOBJSerializer : public GeometrySerializer { private: const std::string mtl_filename; diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index df554fe607..ab3eec863c 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -113,6 +113,8 @@ namespace IfcGeom { std::string unit_name; // double? P unit_magnitude; + gp_XYZ bounds_min_; + gp_XYZ bounds_max_; void initUnits() { IfcSchema::IfcProject::list::ptr projects = ifc_file->entitiesByType(); @@ -251,6 +253,28 @@ namespace IfcGeom { done = 0; total = representations->size(); + 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->entitiesByType(); + for (IfcSchema::IfcProduct::list::it iter = products->begin(); iter != products->end(); ++iter) { + IfcSchema::IfcProduct* product = *iter; + if (product->hasObjectPlacement()) { + gp_Trsf trsf; // Use a fresh trsf every time in order to prevent the result to be concatenated + if (kernel.convert(product->ObjectPlacement(), trsf)) { + 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())); + } + } + } + return true; } @@ -294,6 +318,9 @@ namespace IfcGeom { include_entities_in_processing = false; } + const gp_XYZ& bounds_min() const { return bounds_min_; } + const gp_XYZ& bounds_max() const { return bounds_max_; } + private: // Move to the next IfcRepresentation void _nextShape() { @@ -484,7 +511,8 @@ namespace IfcGeom { unit_magnitude = 1.f; kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.get(IteratorSettings::SEW_SHELLS) ? 1000 : -1); - kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IteratorSettings::INCLUDE_CURVES) ? (settings.get(IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.)); + kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IteratorSettings::INCLUDE_CURVES) + ? (settings.get(IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.)); } bool owns_ifc_file;