diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 5fbb6f9f85..bfaf623ff1 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -293,6 +293,9 @@ int main(int argc, char** argv) "all placements as an offset. Applicable for OBJ and DAE output.") ("model-offset", po::value(&offset_str), "Applies an arbitrary offset of form 'x;y;z' to all placements. Applicable for OBJ and DAE output.") + ("site-local-placement", + "Place elements locally in the IfcSite coordinate system, instead of placing " + "them in the IFC global coords. Applicable for OBJ and DAE output.") ("precision", po::value(&precision)->default_value(SerializerSettings::DEFAULT_PRECISION), "Sets the precision to be used to format floating-point values, 15 by default. " "Use a negative value to use the system's default precision (should be 6 typically). " @@ -364,6 +367,7 @@ int main(int argc, char** argv) const bool no_normals = vmap.count("no-normals") != 0 ; const bool center_model = vmap.count("center-model") != 0 ; const bool model_offset = vmap.count("model-offset") != 0 ; + const bool site_local_placement = vmap.count("site-local-placement") != 0 ; const bool generate_uvs = vmap.count("generate-uvs") != 0 ; #ifdef HAVE_ICU @@ -496,6 +500,7 @@ int main(int argc, char** argv) settings.set(IfcGeom::IteratorSettings::NO_NORMALS, no_normals); settings.set(IfcGeom::IteratorSettings::GENERATE_UVS, generate_uvs); settings.set(IfcGeom::IteratorSettings::SEARCH_FLOOR, use_element_hierarchy); + settings.set(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT, site_local_placement); settings.set(SerializerSettings::USE_ELEMENT_NAMES, use_element_names); settings.set(SerializerSettings::USE_ELEMENT_GUIDS, use_element_guids); @@ -602,6 +607,11 @@ int main(int argc, char** argv) if (center_model || model_offset) { double* offset = serializer->settings().offset; if (center_model) { + if (site_local_placement) { + Logger::Error("Cannot use --center-model together with --site-local-placement"); + delete serializer; + return EXIT_FAILURE; + } gp_XYZ center = (context_iterator.bounds_min() + context_iterator.bounds_max()) * 0.5; offset[0] = -center.X(); offset[1] = -center.Y(); diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index 64b3ea4c23..07d8d67480 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -99,6 +99,10 @@ private: std::map style_cache; const SurfaceStyle* internalize_surface_style(const std::pair& shading_style); + + // For stopping PlacementRelTo recursion in convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) + IfcSchema::Type::Enum placement_rel_to; + public: Kernel() : deflection_tolerance(0.001) @@ -109,6 +113,7 @@ public: , ifc_planeangle_unit(-1.0) , modelling_precision(0.00001) , dimensionality(1.) + , placement_rel_to(IfcSchema::Type::UNDEFINED) {} Kernel(const Kernel& other) { @@ -313,6 +318,8 @@ public: #endif } + void set_conversion_placement_rel_to(IfcSchema::Type::Enum type); + #include "IfcRegisterGeomHeader.h" }; diff --git a/src/ifcgeom/IfcGeomHelpers.cpp b/src/ifcgeom/IfcGeomHelpers.cpp index 29851a2627..cf440772ab 100644 --- a/src/ifcgeom/IfcGeomHelpers.cpp +++ b/src/ifcgeom/IfcGeomHelpers.cpp @@ -357,6 +357,10 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement2D* l, gp_Trsf2d return true; } +void IfcGeom::Kernel::set_conversion_placement_rel_to(IfcSchema::Type::Enum type) { + placement_rel_to = type; +} + bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) { IN_CACHE(IfcObjectPlacement,l,gp_Trsf,trsf) if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) { @@ -372,12 +376,20 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& t trsf.PreMultiply(trsf2); } if ( current->hasPlacementRelTo() ) { - IfcSchema::IfcObjectPlacement* relto = current->PlacementRelTo(); - if ( relto->is(IfcSchema::Type::IfcLocalPlacement) ) + IfcSchema::IfcObjectPlacement* parent = current->PlacementRelTo(); + IfcSchema::IfcProduct::list::ptr parentPlaces = parent->PlacesObject(); + bool parentPlacesType = false; + for ( IfcSchema::IfcProduct::list::it iter = parentPlaces->begin(); + iter != parentPlaces->end(); ++iter) { + if ( (*iter)->is(placement_rel_to) ) parentPlacesType = true; + } + + if ( parentPlacesType ) break; + else if ( parent->is(IfcSchema::Type::IfcLocalPlacement) ) current = (IfcSchema::IfcLocalPlacement*)current->PlacementRelTo(); - else break; + else break; } else break; } CACHE(IfcObjectPlacement,l,trsf) return true; -} \ No newline at end of file +} diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index e8df3f0c3c..12c16ab7cf 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -755,6 +755,9 @@ namespace IfcGeom { 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.)); + if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) { + kernel.set_conversion_placement_rel_to(IfcSchema::Type::IfcSite); + } } bool owns_ifc_file; diff --git a/src/ifcgeom/IfcGeomIteratorSettings.h b/src/ifcgeom/IfcGeomIteratorSettings.h index 3108b16ad4..1a765a37a3 100644 --- a/src/ifcgeom/IfcGeomIteratorSettings.h +++ b/src/ifcgeom/IfcGeomIteratorSettings.h @@ -80,8 +80,10 @@ namespace IfcGeom APPLY_LAYERSETS = 1 << 13, /// Search for a parent of type IfcBuildingStorey for each representation SEARCH_FLOOR = 1 << 14, + /// + SITE_LOCAL_PLACEMENT = 1 << 15, /// Number of different setting flags. - NUM_SETTINGS = 14 + NUM_SETTINGS = 15 }; /// Used to store logical OR combination of setting flags. typedef unsigned SettingField;