diff --git a/src/Mod/BIM/importers/exportIFC.py b/src/Mod/BIM/importers/exportIFC.py index df25562c90..7e09064fa3 100644 --- a/src/Mod/BIM/importers/exportIFC.py +++ b/src/Mod/BIM/importers/exportIFC.py @@ -2464,6 +2464,7 @@ def create_annotation(anno, ifcfile, context, history, preferences): ovc = None zvc = None xvc = None + reps = [] repid = "Annotation" reptype = "Annotation2D" if anno.isDerivedFrom("Part::Feature"): @@ -2475,7 +2476,6 @@ def create_annotation(anno, ifcfile, context, history, preferences): objectType = "AREA" else: objectType = "LINEWORK" - reps = [] sh = anno.Shape.copy() sh.scale(preferences['SCALE_FACTOR']) # to meters ehc = [] @@ -2520,24 +2520,13 @@ def create_annotation(anno, ifcfile, context, history, preferences): if FreeCAD.GuiUp: objectType = "DIMENSION" vp = anno.ViewObject.Proxy - reps = [] - sh = Part.makePolygon([vp.p1,vp.p2,vp.p3,vp.p4]) + if "BBIMDIMS" in preferences and preferences["BBIMDIMS"]: + sh = Part.makePolygon([vp.p2,vp.p3]) + else: + sh = Part.makePolygon([vp.p1,vp.p2,vp.p3,vp.p4]) sh.scale(preferences['SCALE_FACTOR']) # to meters - ehc = [] - curves = [] - for w in sh.Wires: - curves.append(createCurve(ifcfile,w)) - for e in w.Edges: - ehc.append(e.hashCode()) - if curves: - reps.append(ifcfile.createIfcGeometricCurveSet(curves)) - curves = [] - # leftover edges - for e in sh.Edges: - if e.hashCode() not in ehc: - curves.append(createCurve(ifcfile,e)) - if curves: - reps.append(ifcfile.createIfcGeometricCurveSet(curves)) + curve = createCurve(ifcfile,sh) + reps = [ifcfile.createIfcGeometricCurveSet([curve])] # Append text l = FreeCAD.Vector(vp.tbase).multiply(preferences['SCALE_FACTOR']) zdir = None diff --git a/src/Mod/BIM/nativeifc/ifc_export.py b/src/Mod/BIM/nativeifc/ifc_export.py index 403f597c97..d962595e0f 100644 --- a/src/Mod/BIM/nativeifc/ifc_export.py +++ b/src/Mod/BIM/nativeifc/ifc_export.py @@ -31,18 +31,41 @@ from importers import importIFCHelper from nativeifc import ifc_tools -def get_export_preferences(ifcfile): - """returns a preferences dict for exportIFC""" +def get_export_preferences(ifcfile, preferred_context=None): + """returns a preferences dict for exportIFC. + Preferred context can either indicate a ContextType like 'Model' or 'Plan', + or a [ContextIdentifier,ContextType] list or tuple, for ex. + ('Annotation','Plan'). This function will do its best to find the most + appropriate context.""" prefs = exportIFC.getPreferences() prefs["SCHEMA"] = ifcfile.wrapped_data.schema_name() s = ifcopenshell.util.unit.calculate_unit_scale(ifcfile) # the above lines yields meter -> file unit scale factor. We need mm prefs["SCALE_FACTOR"] = 0.001 / s - context = ifcfile[ - ifc_tools.get_body_context_ids(ifcfile)[0] - ] # we take the first one (first found subcontext) - return prefs, context + cids = ifc_tools.get_body_context_ids(ifcfile) + contexts = [ifcfile[i] for i in cids] + best_context = None + if preferred_context: + if isinstance(preferred_context, str): + for context in contexts: + if context.ContextType == preferred_context: + best_context = context + break + elif isinstance(preferred_context, (list, tuple)): + second_choice = None + for context in contexts: + if context.ContextType == preferred_context[1]: + second_choice = context + if context.ContextIdentifier == preferred_context[0]: + best_context = context + break + else: + if second_choice: + best_context = second_choice + if not best_context: + best_context = contexts[0] + return prefs, best_context def create_product(obj, parent, ifcfile, ifcclass=None): @@ -198,7 +221,8 @@ def create_annotation(obj, ifcfile): exportIFC.curvestyles = {} exportIFC.ifcopenshell = ifcopenshell exportIFC.ifcbin = exportIFCHelper.recycler(ifcfile, template=False) - prefs, context = get_export_preferences(ifcfile) + prefs, context = get_export_preferences(ifcfile, preferred_context="Plan") + prefs["BBIMDIMS"] = True # Save dimensions as 2-point polylines history = get_history(ifcfile) # TODO The following prints each edge as a separate IfcGeometricCurveSet # It should be refined to create polylines instead diff --git a/src/Mod/BIM/nativeifc/ifc_objects.py b/src/Mod/BIM/nativeifc/ifc_objects.py index d5ce797180..ffda99c4aa 100644 --- a/src/Mod/BIM/nativeifc/ifc_objects.py +++ b/src/Mod/BIM/nativeifc/ifc_objects.py @@ -214,11 +214,11 @@ class ifc_object: l = w = h = 1000 if obj.ViewObject: if obj.ViewObject.DisplayLength.Value: - l = ifc_export.get_scaled_value(obj.ViewObject.DisplayLength.Value) + l = ifc_export.get_scaled_value(obj.ViewObject.DisplayLength.Value, ifcfile) if obj.ViewObject.DisplayHeight.Value: - w = ifc_export.get_scaled_value(obj.ViewObject.DisplayHeight.Value) + w = ifc_export.get_scaled_value(obj.ViewObject.DisplayHeight.Value, ifcfile) if obj.Depth.Value: - h = ifc_export.get_scaled_value(obj.Depth.Value) + h = ifc_export.get_scaled_value(obj.Depth.Value, ifcfile) if elt.Representation.Representations: for rep in elt.Representation.Representations: for item in rep.Items: @@ -356,9 +356,9 @@ class ifc_object: import Part if not obj.IfcClass == "IfcAnnotation": - return None, None + return [], None if obj.ObjectType != "DRAWING": - return None, None + return [], None objs = getattr(obj, "Objects", []) if not objs: # no object defined, we automatically use the project @@ -388,7 +388,8 @@ class ifc_object: plane.Placement = obj.Placement return objs, plane else: - return None, None + print("DEBUG: Section plane returned no objects") + return [], None class document_object: diff --git a/src/Mod/BIM/nativeifc/ifc_tools.py b/src/Mod/BIM/nativeifc/ifc_tools.py index eaaa283947..6aa2e9dce0 100644 --- a/src/Mod/BIM/nativeifc/ifc_tools.py +++ b/src/Mod/BIM/nativeifc/ifc_tools.py @@ -1216,7 +1216,17 @@ def create_relationship(old_obj, obj, parent, element, ifcfile, mode=None): parent_element = parent # case 4: anything inside group if parent_element.is_a("IfcGroup"): + # special case: adding a section plane to a grouo turns it into a drawing + # and removes it from any containment + if element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING": + parent.ObjectType = "DRAWING" + try: + api_run("spatial.unassign_container", ifcfile, products=[parent_element]) + except: + # older version of IfcOpenShell + api_run("spatial.unassign_container", ifcfile, product=parent_element) # IFC objects can be part of multiple groups but we do the FreeCAD way here + # and remove from any previous group for assignment in getattr(element,"HasAssignments",[]): if assignment.is_a("IfcRelAssignsToGroup"): if element in assignment.RelatedObjects: