diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index 6bd664aafe..10390eee28 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -91,6 +91,10 @@ #include #include +#include +#include +#include + #include "../ifcgeom/IfcGeom.h" #define Kernel MAKE_TYPE_NAME(Kernel) @@ -421,7 +425,21 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& double parameterFactor = isConic ? getValue(GV_PLANEANGLE_UNIT) : getValue(GV_LENGTH_UNIT); Handle(Geom_Curve) curve; - if ( !convert_curve(basis_curve,curve) ) return false; + if (shape_type(basis_curve) == ST_CURVE) { + if (!convert_curve(basis_curve, curve)) return false; + } else if (shape_type(basis_curve) == ST_WIRE) { + Logger::Warning("Approximating BasisCurve due to possible discontinuities", l); + TopoDS_Wire w; + if (!convert_wire(basis_curve, w)) return false; + BRepAdaptor_CompCurve cc(w, true); + Handle(Adaptor3d_HCurve) hcc = Handle(Adaptor3d_HCurve)(new BRepAdaptor_HCompCurve(cc)); + // @todo, arbitrary numbers here, note they cannot be too high as contiguous memory is allocated based on them. + Approx_Curve3d approx(hcc, getValue(GV_PRECISION), GeomAbs_C0, 10, 10); + curve = approx.Curve(); + } else { + Logger::Error("Unknown BasisCurve", l); + return false; + } bool trim_cartesian = l->MasterRepresentation() != IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER; IfcEntityList::ptr trims1 = l->Trim1(); diff --git a/src/ifcopenshell-python/ifcopenshell/entity_instance.py b/src/ifcopenshell-python/ifcopenshell/entity_instance.py index 3586bfa793..7245785e16 100644 --- a/src/ifcopenshell-python/ifcopenshell/entity_instance.py +++ b/src/ifcopenshell-python/ifcopenshell/entity_instance.py @@ -108,22 +108,33 @@ class entity_instance(object): return entity_instance.wrap_value(self.wrapped_data.get_argument(key)) def __setitem__(self, idx, value): + attr_type = real_attr_type = self.attribute_type(idx).title().replace(' ', '') + real_attr_type = real_attr_type.replace('Derived', 'None') + attr_type = attr_type.replace('Binary', 'String') + attr_type = attr_type.replace('Enumeration', 'String') + if value is None: - self.wrapped_data.setArgumentAsNull(idx) + if attr_type != "Derived": + self.wrapped_data.setArgumentAsNull(idx) else: - attr_type = real_attr_type = self.attribute_type(idx).title().replace(' ', '') - attr_type = attr_type.replace('Binary', 'String') - attr_type = attr_type.replace('Enumeration', 'String') - try: - if isinstance(value, unicode): - value = value.encode("utf-8") - except BaseException: - pass - try: - getattr(self.wrapped_data, "setArgumentAs%s" % attr_type)(idx, entity_instance.unwrap_value(value)) - except BaseException: + valid = attr_type != "Derived" + if valid: + try: + if isinstance(value, unicode): + value = value.encode("utf-8") + except BaseException: + pass + + try: + if attr_type != "Derived": + getattr(self.wrapped_data, "setArgumentAs%s" % attr_type)(idx, entity_instance.unwrap_value(value)) + except BaseException as e: + valid = False + + if not valid: raise ValueError("Expected %s for attribute %s.%s, got %r" % ( real_attr_type, self.is_a(), self.attribute_name(idx), value)) + return value def __len__(self): diff --git a/src/ifcwrap/IfcParseWrapper.i b/src/ifcwrap/IfcParseWrapper.i index 174921f81c..67616f0f54 100644 --- a/src/ifcwrap/IfcParseWrapper.i +++ b/src/ifcwrap/IfcParseWrapper.i @@ -62,6 +62,9 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas const IfcParse::parameter_type* pt = 0; if (inst->declaration().as_entity()) { pt = inst->declaration().as_entity()->attribute_by_index(i)->type_of_attribute(); + if (inst->declaration().as_entity()->derived()[i]) { + return IfcUtil::Argument_DERIVED; + } } else if (inst->declaration().as_type_declaration() && i == 0) { pt = inst->declaration().as_type_declaration()->declared_type(); }