From fdf1b296829e7e0538c783bd9be27c6525c77b13 Mon Sep 17 00:00:00 2001 From: aothms Date: Thu, 22 Oct 2015 12:04:49 +0200 Subject: [PATCH] Return shape for arbitrary representation items in ifcopenshell.geom.create_shape() --- src/ifcgeom/IfcRegister.cpp | 9 ++ .../ifcopenshell/geom/occ_utils.py | 15 +++- src/ifcwrap/IfcGeomWrapper.i | 84 ++++++++++++++----- 3 files changed, 82 insertions(+), 26 deletions(-) diff --git a/src/ifcgeom/IfcRegister.cpp b/src/ifcgeom/IfcRegister.cpp index e00654da5d..2b7d836c63 100644 --- a/src/ifcgeom/IfcRegister.cpp +++ b/src/ifcgeom/IfcRegister.cpp @@ -24,6 +24,15 @@ using namespace IfcSchema; using namespace IfcUtil; bool IfcGeom::Kernel::convert_shapes(const IfcBaseClass* l, IfcRepresentationShapeItems& r) { + if (shape_type(l) != ST_SHAPELIST) { + TopoDS_Shape shp; + if (convert_shape(l, shp)) { + r.push_back(IfcGeom::IfcRepresentationShapeItem(shp, get_style(l->as()))); + return true; + } + return false; + } + #include "IfcRegisterConvertShapes.h" Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); return false; diff --git a/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py b/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py index be5c93e8b3..591b0b1909 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py @@ -52,8 +52,14 @@ def get_bounding_box_center(bbox): def create_shape_from_serialization(brep_object): brep_data, occ_shape = None, None - try: brep_data = brep_object.geometry.brep_data - except: pass + is_product_shape = True + try: + brep_data = brep_object.geometry.brep_data + except: + try: + brep_data = brep_object.brep_data + is_product_shape = False + except: pass if not brep_data: return tuple(brep_object, None) try: @@ -62,5 +68,8 @@ def create_shape_from_serialization(brep_object): occ_shape = ss.Shape(ss.NbShapes()) except: pass - return tuple(brep_object, occ_shape) + if is_product_shape: + return tuple(brep_object, occ_shape) + else: + return occ_shape diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index 1069f6ba30..84a435b69e 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -72,17 +72,35 @@ } } +// A visitor +%{ +struct ShapeRTTI : public boost::static_visitor +{ + PyObject* operator()(IfcGeom::Element* elem) const { + IfcGeom::SerializedElement* serialized_elem = dynamic_cast*>(elem); + IfcGeom::TriangulationElement* triangulation_elem = dynamic_cast*>(elem); + if (triangulation_elem) { + return SWIG_NewPointerObj(SWIG_as_voidptr(triangulation_elem), SWIGTYPE_p_IfcGeom__TriangulationElementT_double_t, SWIG_POINTER_OWN); + } else if (serialized_elem) { + return SWIG_NewPointerObj(SWIG_as_voidptr(serialized_elem), SWIGTYPE_p_IfcGeom__SerializedElementT_double_t, SWIG_POINTER_OWN); + } + } + PyObject* operator()(IfcGeom::Representation::Representation* representation) const { + IfcGeom::Representation::Serialization* serialized_representation = dynamic_cast(representation); + IfcGeom::Representation::Triangulation* triangulated_representation = dynamic_cast*>(representation); + if (serialized_representation) { + return SWIG_NewPointerObj(SWIG_as_voidptr(serialized_representation), SWIGTYPE_p_IfcGeom__Representation__Serialization, SWIG_POINTER_OWN); + } else if (triangulated_representation) { + return SWIG_NewPointerObj(SWIG_as_voidptr(triangulated_representation), SWIGTYPE_p_IfcGeom__Representation__TriangulationT_double_t, SWIG_POINTER_OWN); + } + } +}; +%} + // Note that these elements ARE to be owned by SWIG/Python %typemap(out) boost::variant*, IfcGeom::Representation::Representation*> { // See which type is set and return appropriate - IfcGeom::Element* elem = boost::get*>($1); - IfcGeom::SerializedElement* serialized_elem = dynamic_cast*>(elem); - IfcGeom::TriangulationElement* triangulation_elem = dynamic_cast*>(elem); - if (triangulation_elem) { - $result = SWIG_NewPointerObj(SWIG_as_voidptr(triangulation_elem), SWIGTYPE_p_IfcGeom__TriangulationElementT_double_t, SWIG_POINTER_OWN); - } else if (serialized_elem) { - $result = SWIG_NewPointerObj(SWIG_as_voidptr(serialized_elem), SWIGTYPE_p_IfcGeom__SerializedElementT_double_t, SWIG_POINTER_OWN); - } + $result = boost::apply_visitor(ShapeRTTI(), $1); } // This does not seem to work: @@ -218,25 +236,25 @@ %inline %{ boost::variant*, IfcGeom::Representation::Representation*> create_shape(IfcGeom::IteratorSettings& settings, IfcParse::IfcLateBoundEntity* instance, IfcParse::IfcLateBoundEntity* representation = 0) { + IfcParse::IfcFile* file = instance->entity->file; + IfcSchema::IfcProject::list::ptr projects = file->entitiesByType(); + if (projects->size() != 1) { + throw IfcParse::IfcException("Not a single IfcProject instance"); + } + IfcSchema::IfcProject* project = *projects->begin(); + + IfcGeom::Kernel kernel; + kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1); + kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.include_curves() ? (settings.exclude_solids_and_surfaces() ? -1. : 0.) : +1.)); + std::pair length_unit = kernel.initializeUnits(project->UnitsInContext()); + if (instance->is(IfcSchema::Type::IfcProduct)) { if (representation) { if (!representation->is(IfcSchema::Type::IfcRepresentation)) { throw IfcParse::IfcException("Supplied representation not of type IfcRepresentation"); } } - - IfcParse::IfcFile* file = instance->entity->file; - - IfcSchema::IfcProject::list::ptr projects = file->entitiesByType(); - if (projects->size() != 1) { - throw IfcParse::IfcException("Not a single IfcProject instance"); - } - IfcSchema::IfcProject* project = *projects->begin(); - - IfcGeom::Kernel kernel; - kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1); - kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.include_curves() ? (settings.exclude_solids_and_surfaces() ? -1. : 0.) : +1.)); - + IfcSchema::IfcProduct* product = (IfcSchema::IfcProduct*) instance; if (!representation && !product->hasRepresentation()) { @@ -318,7 +336,6 @@ if (context->hasPrecision()) { precision = context->Precision(); } - std::pair length_unit = kernel.initializeUnits(project->UnitsInContext()); precision *= length_unit.second; // Some arbitrary factor that has proven to work better for the models in the set of test files. @@ -342,7 +359,28 @@ throw IfcParse::IfcException("No element to return based on provided settings"); } } else { - throw IfcParse::IfcException("Only obtaining representations for IfcProduct instances is currently supported"); + if (!representation) { + if (instance->is(IfcSchema::Type::IfcRepresentationItem) || instance->is(IfcSchema::Type::IfcRepresentation)) { + IfcGeom::IfcRepresentationShapeItems shapes; + if (kernel.convert_shapes(instance, shapes)) { + IfcGeom::ElementSettings element_settings(settings, kernel.getValue(IfcGeom::Kernel::GV_LENGTH_UNIT), IfcSchema::Type::ToString(instance->type())); + IfcGeom::Representation::BRep brep(element_settings, instance->entity->id(), shapes); + try { + if (settings.use_brep_data()) { + return new IfcGeom::Representation::Serialization(brep); + } else if (!settings.disable_triangulation()) { + return new IfcGeom::Representation::Triangulation(brep); + } + } catch (...) { + throw IfcParse::IfcException("Error during shape serialization"); + } + } else { + throw IfcParse::IfcException("Geometrical element not understood"); + } + } + } else { + throw IfcParse::IfcException("Invalid additional representation specified"); + } } } %}