From 3e00139a873016be15c0912b41136d586c5ecd77 Mon Sep 17 00:00:00 2001 From: aothms Date: Mon, 5 Oct 2015 13:07:40 +0200 Subject: [PATCH 01/16] Add const pointer cast to IfcBaseClass --- src/ifcparse/IfcUtil.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ifcparse/IfcUtil.h b/src/ifcparse/IfcUtil.h index e57f5da279..3c10cd51b2 100644 --- a/src/ifcparse/IfcUtil.h +++ b/src/ifcparse/IfcUtil.h @@ -89,6 +89,13 @@ namespace IfcUtil { ? static_cast(this) : static_cast(0); } + + template + const T* as() const { + return is(T::Class()) + ? static_cast(this) + : static_cast(0); + } }; class IfcBaseEntity : public IfcBaseClass { From 7b82bfb477efe5ddec5247aff78e7117e77e5558 Mon Sep 17 00:00:00 2001 From: aothms Date: Mon, 5 Oct 2015 13:08:24 +0200 Subject: [PATCH 02/16] Update log messages in parser --- src/ifcparse/IfcParse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index ac3e0cc99c..3bb2cf36af 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -969,7 +969,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* s) { const std::string guid = ifc_root->GlobalId(); if ( byguid.find(guid) != byguid.end() ) { std::stringstream ss; - ss << "Overwriting entity with guid " << guid; + ss << "Instance encountered with non-unique GlobalId " << guid; Logger::Message(Logger::LOG_WARNING,ss.str()); } byguid[guid] = ifc_root; @@ -991,7 +991,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* s) { if ( byid.find(currentId) != byid.end() ) { std::stringstream ss; - ss << "Overwriting entity with id " << currentId; + ss << "Overwriting instance with name #" << currentId; Logger::Message(Logger::LOG_WARNING,ss.str()); } byid[currentId] = entity; From c20afd24a56d167db26f85f96d62bb5329edca77 Mon Sep 17 00:00:00 2001 From: aothms Date: Mon, 5 Oct 2015 13:09:16 +0200 Subject: [PATCH 03/16] Remove unnecessary precision cast --- src/ifcgeom/IfcGeomWires.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index c212ad6422..a4b74f995d 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -257,7 +257,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& flts[1] -= M_PI / 2.; } } - if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],(double)(M_PI*2.0)),0.0f) ) { + if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],M_PI*2.),0.) ) { w.Add(BRepBuilderAPI_MakeEdge(curve)); } else { BRepBuilderAPI_MakeEdge e (curve,flts[0],flts[1]); From db6630c1f83b05c29f32535da16eebe9eda7aef8 Mon Sep 17 00:00:00 2001 From: aothms Date: Mon, 5 Oct 2015 13:34:43 +0200 Subject: [PATCH 04/16] Use boost::to_lower() --- src/ifcconvert/IfcConvert.cpp | 12 ++++-------- src/ifcgeom/IfcGeomIterator.h | 8 +++----- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 8bb776cc73..b1df5ee3bd 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -32,6 +32,7 @@ #include #include +#include #include "../ifcgeom/IfcGeomIterator.h" @@ -197,11 +198,8 @@ int main(int argc, char** argv) { // Gets the set ifc types to be ignored from the command line. std::set entities; for (std::vector::const_iterator it = entity_vector.begin(); it != entity_vector.end(); ++it) { - std::string lowercase_type = *it; - for (std::string::iterator c = lowercase_type.begin(); c != lowercase_type.end(); ++c) { - *c = tolower(*c); - } - entities.insert(lowercase_type); + const std::string& mixed_case_type = *it; + entities.insert(boost::to_lower_copy(mixed_case_type)); } const std::string input_filename = vmap["input-file"].as(); @@ -217,9 +215,7 @@ int main(int argc, char** argv) { } std::string output_extension = output_filename.substr(output_filename.size()-4); - for (std::string::iterator c = output_extension.begin(); c != output_extension.end(); ++c) { - *c = tolower(*c); - } + boost::to_lower(output_extension); // If no entities are specified these are the defaults to skip from output if (entity_vector.empty()) { diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index fc62b3bbf4..70e24234ac 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -181,11 +181,9 @@ namespace IfcGeom { continue; } if (context->hasContextType()) { - std::string context_type_lc = context->ContextType(); - for (std::string::iterator c = context_type_lc.begin(); c != context_type_lc.end(); ++c) { - *c = tolower(*c); - } - if (context_types.find(context_type_lc) != context_types.end()) { + std::string context_type = context->ContextType(); + boost::to_lower(context_type); + if (context_types.find(context_type) != context_types.end()) { filtered_contexts->push(context); } } From 3a9e90f94fdf4c1f54da3d5498ab7730f4521d86 Mon Sep 17 00:00:00 2001 From: aothms Date: Wed, 7 Oct 2015 16:13:25 +0200 Subject: [PATCH 05/16] Mark IfcGeom::Kernel::getValue as const --- src/ifcgeom/IfcGeom.h | 2 +- src/ifcgeom/IfcGeomFunctions.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index 78d8ded544..94f6f51290 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -121,7 +121,7 @@ public: double face_area(const TopoDS_Face& f); void apply_tolerance(TopoDS_Shape& s, double t); void setValue(GeomValue var, double value); - double getValue(GeomValue var); + double getValue(GeomValue var) const; bool fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape); void remove_redundant_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index c8e430283f..4fbd154d39 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -554,7 +554,7 @@ void IfcGeom::Kernel::setValue(GeomValue var, double value) { } } -double IfcGeom::Kernel::getValue(GeomValue var) { +double IfcGeom::Kernel::getValue(GeomValue var) const { switch (var) { case GV_DEFLECTION_TOLERANCE: return deflection_tolerance; From c7ddc0643e129f553c1a533d24538227779c9d40 Mon Sep 17 00:00:00 2001 From: aothms Date: Wed, 7 Oct 2015 16:14:34 +0200 Subject: [PATCH 06/16] Fixes to flatten_shape_list() --- src/ifcgeom/IfcGeomFunctions.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 4fbd154d39..51e6584e12 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -776,8 +776,14 @@ bool IfcGeom::Kernel::flatten_shape_list(const IfcGeom::IfcRepresentationShapeIt _trsf = trsf.Trsf(); trsf_valid = true; } catch (...) {} - const TopoDS_Shape moved_shape = trsf_valid ? merged.Moved(_trsf) : - BRepBuilderAPI_GTransform(merged,trsf,true).Shape(); + + const TopoDS_Shape moved_shape = trsf.Form() == gp_Identity + ? merged + : ( + trsf_valid + ? merged.Moved(_trsf) + : BRepBuilderAPI_GTransform(merged,trsf,true).Shape() + ); if (shapes.size() == 1) { result = moved_shape; @@ -809,6 +815,10 @@ bool IfcGeom::Kernel::flatten_shape_list(const IfcGeom::IfcRepresentationShapeIt } } + if (!fuse) { + result = compound; + } + const bool success = !result.IsNull(); if (success) { const double precision = getValue(GV_PRECISION); From 44ddc5e6dc3086852c1541b1a651576cf1f4abb8 Mon Sep 17 00:00:00 2001 From: aothms Date: Fri, 9 Oct 2015 14:23:38 +0200 Subject: [PATCH 07/16] =?UTF-8?q?Don't=20use=20IfcMappedItems=20for=20IfcO?= =?UTF-8?q?penHouse=20walls,=20as=20suggested=20by=20Ian=20Cl=C3=A9vy=20in?= =?UTF-8?q?=20https://sourceforge.net/p/ifcopenshell/discussion/1782716/th?= =?UTF-8?q?read/f9b586ca/=3Flimit=3D25#ab87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/examples/IfcOpenHouse.cpp | 43 +++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/examples/IfcOpenHouse.cpp b/src/examples/IfcOpenHouse.cpp index 9f4887c5f9..00cfe1503d 100644 --- a/src/examples/IfcOpenHouse.cpp +++ b/src/examples/IfcOpenHouse.cpp @@ -195,43 +195,46 @@ int main(int argc, char** argv) { file.addBuildingProduct(north_wall); file.setSurfaceColour(north_wall->Representation(), wall_colour); - IfcSchema::IfcShapeRepresentation* clipped_wall_body_rep = file.addEmptyRepresentation(); - file.addBox(clipped_wall_body_rep, 5000, 360, 6000); - // The east wall geometry is clipped using two IfcHalfSpaceSolids, created from an - // 'axis 3d placement' that specifies the plane against which the geometry is clipped. - file.clipRepresentation(clipped_wall_body_rep, file.addPlacement3d(-2500, 0, 3000, -1, 0, 1), false); - file.clipRepresentation(clipped_wall_body_rep, file.addPlacement3d(2500, 0, 3000, 1, 0, 1), false); + // Two identical representations are created for the two remaining walls. Mapped items + // are not used, because it is not allowed by the standard for wall body representations. + // MappedItems are not allowed for Axis representations as per CV-2x3-161 + IfcSchema::IfcProductDefinitionShape* clipped_wall_body_reps[2]; + for (int i = 0; i < 2; ++i) { + IfcSchema::IfcShapeRepresentation* body = file.addEmptyRepresentation(); + file.addBox(body, 5000, 360, 6000); + // The wall geometry is clipped using two IfcHalfSpaceSolids, created from an + // 'axis 3d placement' that specifies the plane against which the geometry is clipped. + file.clipRepresentation(body, file.addPlacement3d(-2500, 0, 3000, -1, 0, 1), false); + file.clipRepresentation(body, file.addPlacement3d(2500, 0, 3000, 1, 0, 1), false); + file.setSurfaceColour(body, wall_colour); + + IfcSchema::IfcShapeRepresentation* axis = file.addEmptyRepresentation("Axis", "Curve2D"); + file.addAxis(axis, 5000); + + IfcSchema::IfcRepresentation::list::ptr reps(new IfcSchema::IfcRepresentation::list); + reps->push(body); + reps->push(axis); + clipped_wall_body_reps[i] = new IfcSchema::IfcProductDefinitionShape(null, null, reps); + } // Now create a wall on the east of the building, again starting with just a box shape IfcSchema::IfcWallStandardCase* east_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle(), - S("East wall"), null, null, file.addLocalPlacement(storey_placement, 4820, 2500, 0, 0, 0, 1, 0, 1, 0), file.addMappedItem(clipped_wall_body_rep), null + S("East wall"), null, null, file.addLocalPlacement(storey_placement, 4820, 2500, 0, 0, 0, 1, 0, 1, 0), clipped_wall_body_reps[0], null #ifdef USE_IFC4 , IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD #endif ); file.addBuildingProduct(east_wall); - file.setSurfaceColour(clipped_wall_body_rep, wall_colour); - // The east wall is copied to the west location of the house IfcSchema::IfcWallStandardCase* west_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle(), - S("West wall"), null, null, file.addLocalPlacement(storey_placement, -4820, 2500, 0, 0, 0, 1, 0, -1, 0), file.addMappedItem(clipped_wall_body_rep), null + S("West wall"), null, null, file.addLocalPlacement(storey_placement, -4820, 2500, 0, 0, 0, 1, 0, -1, 0), clipped_wall_body_reps[1], null #ifdef USE_IFC4 , IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD #endif ); file.addBuildingProduct(west_wall); - for (int i = 0; i < 2; ++i) { - // CV-2x3-161: MappedItems are not allowed for Axis representations - IfcSchema::IfcWallStandardCase* wall = i == 0 ? east_wall : west_wall; - IfcSchema::IfcShapeRepresentation* wall_axis_rep = file.addEmptyRepresentation("Axis", "Curve2D"); - file.addAxis(wall_axis_rep, 5000); - IfcSchema::IfcRepresentation::list::ptr reps = wall->Representation()->Representations(); - reps->push(wall_axis_rep); - wall->Representation()->setRepresentations(reps); - } - // The west wall is assigned an opening element we created for the south wall, opening elements are // not shared accross building elements, even if they share the same representation. Hence, the east // wall will not feature this opening. From f3af39546be9ecd485737ff0954cfb92807fca1d Mon Sep 17 00:00:00 2001 From: aothms Date: Tue, 13 Oct 2015 11:15:45 +0200 Subject: [PATCH 08/16] Don't construct transformation from matrix, but use original data. --- src/ifcconvert/OpenCascadeBasedSerializer.cpp | 14 +------------- src/ifcconvert/SvgSerializer.cpp | 12 +----------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/src/ifcconvert/OpenCascadeBasedSerializer.cpp b/src/ifcconvert/OpenCascadeBasedSerializer.cpp index 77bc7e7fc9..3dc8ad9386 100644 --- a/src/ifcconvert/OpenCascadeBasedSerializer.cpp +++ b/src/ifcconvert/OpenCascadeBasedSerializer.cpp @@ -40,19 +40,7 @@ void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement* o) { for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) { gp_GTrsf gtrsf = it->Placement(); - const std::vector& matrix = o->transformation().matrix().data(); - - // Convert the matrix back into a transformation object. The tolerance values - // are taken into consideration to reconstruct the form of the transformation. - gp_Trsf o_trsf; - o_trsf.SetValues( - matrix[0], matrix[3], matrix[6], matrix[ 9], - matrix[1], matrix[4], matrix[7], matrix[10], - matrix[2], matrix[5], matrix[8], matrix[11] -#if OCC_VERSION_HEX < 0x60800 - , Precision::Angular(), Precision::Confusion() -#endif - ); + const gp_Trsf& o_trsf = o->transformation().data(); gtrsf.PreMultiply(o_trsf); const TopoDS_Shape& s = it->Shape(); diff --git a/src/ifcconvert/SvgSerializer.cpp b/src/ifcconvert/SvgSerializer.cpp index 8319393ff8..7c03241971 100644 --- a/src/ifcconvert/SvgSerializer.cpp +++ b/src/ifcconvert/SvgSerializer.cpp @@ -217,17 +217,7 @@ void SvgSerializer::write(const IfcGeom::BRepElement* o) { for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) { gp_GTrsf gtrsf = it->Placement(); - gp_Trsf o_trsf; - const std::vector& matrix = o->transformation().matrix().data(); - o_trsf.SetValues( - matrix[0], matrix[3], matrix[6], matrix[ 9], - matrix[1], matrix[4], matrix[7], matrix[10], - matrix[2], matrix[5], matrix[8], matrix[11] -#if OCC_VERSION_HEX < 0x60800 - , Precision::Angular(), Precision::Confusion() -#endif - ); - gtrsf.PreMultiply(o_trsf); + const gp_Trsf& o_trsf = o->transformation().data(); const TopoDS_Shape& s = it->Shape(); bool trsf_valid = false; From fdf1b296829e7e0538c783bd9be27c6525c77b13 Mon Sep 17 00:00:00 2001 From: aothms Date: Thu, 22 Oct 2015 12:04:49 +0200 Subject: [PATCH 09/16] 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"); + } } } %} From bf292cccd00e9f2dc5232f035a9357233d95982b Mon Sep 17 00:00:00 2001 From: aothms Date: Mon, 30 Nov 2015 22:59:21 +0100 Subject: [PATCH 10/16] Precision fixes --- src/ifcconvert/WavefrontObjSerializer.cpp | 7 +++++-- src/ifcparse/IfcWrite.cpp | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ifcconvert/WavefrontObjSerializer.cpp b/src/ifcconvert/WavefrontObjSerializer.cpp index 19643be430..6244b001fa 100644 --- a/src/ifcconvert/WavefrontObjSerializer.cpp +++ b/src/ifcconvert/WavefrontObjSerializer.cpp @@ -17,12 +17,13 @@ * * ********************************************************************************/ +#include +#include + #include "../ifcgeom/IfcGeomRenderStyles.h" #include "WavefrontObjSerializer.h" -#include - bool WaveFrontOBJSerializer::ready() { return obj_stream.is_open() && mtl_stream.is_open(); } @@ -70,6 +71,8 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* obj_stream << "g " << o->unique_id() << "\n"; obj_stream << "s 1" << "\n"; + obj_stream << std::setprecision(std::numeric_limits::digits10); + const IfcGeom::Representation::Triangulation& mesh = o->geometry(); const int vcount = mesh.verts().size() / 3; diff --git a/src/ifcparse/IfcWrite.cpp b/src/ifcparse/IfcWrite.cpp index 86486ed992..f324742389 100644 --- a/src/ifcparse/IfcWrite.cpp +++ b/src/ifcparse/IfcWrite.cpp @@ -19,6 +19,7 @@ #include #include +#include #include @@ -327,7 +328,7 @@ private: std::string format_double(const double& d) { std::ostringstream oss; oss.imbue(std::locale::classic()); - oss << std::setprecision(15) << d; + oss << std::setprecision(std::numeric_limits::digits10) << d; const std::string str = oss.str(); oss.str(""); std::string::size_type e = str.find('e'); From b6e2d78bfa09dffb90b60f7b0261994a9be9d6ec Mon Sep 17 00:00:00 2001 From: aothms Date: Mon, 30 Nov 2015 23:41:27 +0100 Subject: [PATCH 11/16] Catch syntax errors during iterator initialization --- src/ifcgeom/IfcGeomIterator.h | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 70e24234ac..a2b6cb9e34 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -180,13 +180,15 @@ namespace IfcGeom { // by the parent's context inverse attributes. continue; } - if (context->hasContextType()) { - std::string context_type = context->ContextType(); - boost::to_lower(context_type); - if (context_types.find(context_type) != context_types.end()) { - filtered_contexts->push(context); + try { + if (context->hasContextType()) { + std::string context_type = context->ContextType(); + boost::to_lower(context_type); + if (context_types.find(context_type) != context_types.end()) { + filtered_contexts->push(context); + } } - } + } catch (const IfcParse::IfcException&) {} } // In case no contexts are identified based on their ContextType, all contexts are @@ -204,10 +206,12 @@ namespace IfcGeom { IfcSchema::IfcGeometricRepresentationContext* context = *it; representations->push(context->RepresentationsInContext()); - if (context->hasPrecision() && context->Precision() < lowest_precision_encountered) { - lowest_precision_encountered = context->Precision(); - any_precision_encountered = true; - } + try { + if (context->hasPrecision() && context->Precision() < lowest_precision_encountered) { + lowest_precision_encountered = context->Precision(); + any_precision_encountered = true; + } + } catch (const IfcParse::IfcException&) {} IfcSchema::IfcGeometricRepresentationSubContext::list::ptr sub_contexts = context->HasSubContexts(); for (jt = sub_contexts->begin(); jt != sub_contexts->end(); ++jt) { representations->push((*jt)->RepresentationsInContext()); From e62ce005dc2fe801e97d78dc837555f2d7212aea Mon Sep 17 00:00:00 2001 From: aothms Date: Tue, 1 Dec 2015 11:14:50 +0100 Subject: [PATCH 12/16] Work on unit issues with step and iges files --- src/ifcconvert/IgesSerializer.h | 1 + src/ifcconvert/OpenCascadeBasedSerializer.cpp | 6 ++++++ src/ifcconvert/StepSerializer.h | 1 + 3 files changed, 8 insertions(+) diff --git a/src/ifcconvert/IgesSerializer.h b/src/ifcconvert/IgesSerializer.h index 8591af9902..fccb0a09f1 100644 --- a/src/ifcconvert/IgesSerializer.h +++ b/src/ifcconvert/IgesSerializer.h @@ -46,6 +46,7 @@ public: void setUnitNameAndMagnitude(const std::string& name, float magnitude) { const char* symbol = getSymbolForUnitMagnitude(magnitude); if (symbol) { + Interface_Static::SetCVal("xstep.cascade.unit", symbol); Interface_Static::SetCVal("write.iges.unit", symbol); } } diff --git a/src/ifcconvert/OpenCascadeBasedSerializer.cpp b/src/ifcconvert/OpenCascadeBasedSerializer.cpp index 3dc8ad9386..2dbb642c3d 100644 --- a/src/ifcconvert/OpenCascadeBasedSerializer.cpp +++ b/src/ifcconvert/OpenCascadeBasedSerializer.cpp @@ -42,6 +42,12 @@ void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement* o) { const gp_Trsf& o_trsf = o->transformation().data(); gtrsf.PreMultiply(o_trsf); + + if (o->geometry().settings().convert_back_units()) { + gp_Trsf scale; + scale.SetScaleFactor(1.0 / o->geometry().settings().unit_magnitude()); + gtrsf.PreMultiply(scale); + } const TopoDS_Shape& s = it->Shape(); diff --git a/src/ifcconvert/StepSerializer.h b/src/ifcconvert/StepSerializer.h index 4667104a38..9d8ca7b211 100644 --- a/src/ifcconvert/StepSerializer.h +++ b/src/ifcconvert/StepSerializer.h @@ -52,6 +52,7 @@ public: void setUnitNameAndMagnitude(const std::string& name, float magnitude) { const char* symbol = getSymbolForUnitMagnitude(magnitude); if (symbol) { + Interface_Static::SetCVal("xstep.cascade.unit", symbol); Interface_Static::SetCVal("write.step.unit", symbol); } } From 0301e2fb1bb6f997da3dd330d34f60ce7d4a38cb Mon Sep 17 00:00:00 2001 From: aothms Date: Wed, 2 Dec 2015 10:17:59 +0100 Subject: [PATCH 13/16] Emit an error message on extrusions with negative height or under model precision --- src/ifcgeom/IfcGeomShapes.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index 896863805d..1ee17e9221 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -99,10 +99,15 @@ #include "../ifcgeom/IfcGeom.h" bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& shape) { + const double height = l->Depth() * getValue(GV_LENGTH_UNIT); + if (height < getValue(GV_PRECISION)) { + Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l); + return false; + } + TopoDS_Shape face; if ( !convert_face(l->SweptArea(),face) ) return false; - const double height = l->Depth() * getValue(GV_LENGTH_UNIT); gp_Trsf trsf; IfcGeom::Kernel::convert(l->Position(),trsf); From a2d91f93318ba2d15452fba6818ae12e763d45a7 Mon Sep 17 00:00:00 2001 From: aothms Date: Fri, 4 Dec 2015 11:56:54 +0100 Subject: [PATCH 14/16] Fix compilation error reported by bezumenez --- src/ifcgeom/IfcGeomShapes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index 1ee17e9221..2402e1319d 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -101,7 +101,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& shape) { const double height = l->Depth() * getValue(GV_LENGTH_UNIT); if (height < getValue(GV_PRECISION)) { - Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l); + Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l->entity); return false; } From b243572d231f12d19808d792f5806916bcb79448 Mon Sep 17 00:00:00 2001 From: aothms Date: Sat, 5 Dec 2015 17:14:10 +0100 Subject: [PATCH 15/16] Don't fail on opening elements lacking representation or placement --- src/ifcgeom/IfcGeomFunctions.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 51e6584e12..fe0bf7b00e 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -160,10 +160,15 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons IfcSchema::IfcRelVoidsElement* v = *it; IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement(); if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) { + if (!fes->hasRepresentation()) continue; // Convert the IfcRepresentation of the IfcOpeningElement gp_Trsf opening_trsf; - IfcGeom::Kernel::convert(fes->ObjectPlacement(),opening_trsf); + if (fes->hasObjectPlacement()) { + try { + convert(fes->ObjectPlacement(),opening_trsf); + } catch (...) {} + } // Move the opening into the coordinate system of the IfcProduct opening_trsf.PreMultiply(entity_trsf.Inverted()); @@ -303,10 +308,15 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, IfcSchema::IfcRelVoidsElement* v = *it; IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement(); if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) { + if (!fes->hasRepresentation()) continue; // Convert the IfcRepresentation of the IfcOpeningElement gp_Trsf opening_trsf; - IfcGeom::Kernel::convert(fes->ObjectPlacement(),opening_trsf); + if (fes->hasObjectPlacement()) { + try { + convert(fes->ObjectPlacement(),opening_trsf); + } catch (...) {} + } // Move the opening into the coordinate system of the IfcProduct opening_trsf.PreMultiply(entity_trsf.Inverted()); From fe699e0a81140d33b5c3a45a219e4fbd9892900b Mon Sep 17 00:00:00 2001 From: aothms Date: Mon, 21 Dec 2015 11:47:38 +0100 Subject: [PATCH 16/16] Fix python module import --- src/ifcopenshell-python/ifcopenshell/geom/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifcopenshell-python/ifcopenshell/geom/__init__.py b/src/ifcopenshell-python/ifcopenshell/geom/__init__.py index 8550f4013d..f4d05f86dc 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/__init__.py @@ -31,7 +31,7 @@ def has_occ(): has_occ = has_occ() wrap_shape_creation = lambda settings, shape: shape if has_occ: - import occ_utils as utils + from . import occ_utils as utils wrap_shape_creation = lambda settings, shape: utils.create_shape_from_serialization(shape) if getattr(settings, 'use_python_opencascade', False) else shape