diff --git a/src/Mod/BIM/ArchSite.py b/src/Mod/BIM/ArchSite.py index 4c51e09458..ee67ead19f 100644 --- a/src/Mod/BIM/ArchSite.py +++ b/src/Mod/BIM/ArchSite.py @@ -967,11 +967,20 @@ class _ViewProviderSite: https://forum.freecad.org/viewtopic.php?t=75883 """ + from pivy import coin + + def find_node(parent, nodetype): + for i in range(parent.getNumChildren()): + if isinstance(parent.getChild(i), nodetype): + return parent.getChild(i) + return None + if not hasattr(self, "terrain_switches"): if vobj.RootNode.getNumChildren() > 2: - main_switch = vobj.RootNode.getChild(2) # The display mode switch. + main_switch = find_node(vobj.RootNode, coin.SoSwitch) + if not main_switch: + return if main_switch.getNumChildren() == 4: # Check if all display modes are available. - from pivy import coin self.terrain_switches = [] for node in tuple(main_switch.getChildren()): new_switch = coin.SoSwitch() diff --git a/src/Mod/BIM/nativeifc/ifc_diff.py b/src/Mod/BIM/nativeifc/ifc_diff.py index be418fca63..404328fac5 100644 --- a/src/Mod/BIM/nativeifc/ifc_diff.py +++ b/src/Mod/BIM/nativeifc/ifc_diff.py @@ -37,6 +37,7 @@ def get_diff(proj): if not getattr(proj, "IfcFilePath", None): old = [] + return 1 else: # cannot use open() here as it gives different encoding # than ifcopenshell and diff does not work @@ -59,7 +60,11 @@ def htmlize(diff): """Returns an HTML version of a diff list""" html = "\n" - if diff: + if diff == 1: + html += translate("BIM", "The IFC file is not saved. Please save once" + " to have an existing IFC file to compare with." + " Then, run this command again.") + "
\n" + elif diff: diff = diff.split("\n") for l in diff: if l.startswith("+"): diff --git a/src/Mod/BIM/nativeifc/ifc_export.py b/src/Mod/BIM/nativeifc/ifc_export.py index d55e159c9c..4d52f9dd05 100644 --- a/src/Mod/BIM/nativeifc/ifc_export.py +++ b/src/Mod/BIM/nativeifc/ifc_export.py @@ -20,6 +20,8 @@ # * * # *************************************************************************** +import tempfile + import FreeCAD import Draft import ifcopenshell @@ -29,6 +31,10 @@ from importers import exportIFCHelper from importers import importIFCHelper from nativeifc import ifc_tools +from nativeifc import ifc_import + + +PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/NativeIFC") def get_export_preferences(ifcfile, preferred_context=None, create=None): @@ -354,8 +360,34 @@ def get_scaled_point(point, ifcfile=None, is2d=False): v = v[:2] return v + def get_scaled_value(value, ifcfile): """Returns a scaled dimension value""" s = 0.001 / ifcopenshell.util.unit.calculate_unit_scale(ifcfile) return value * s + + +def export_and_convert(objs, doc): + """Exports the given objects and their descendents to the given IFC file + and re-imports it into the given document. This is slower than direct_conversion() + but gives an intermediate file which can be useful for debugging""" + + tf = tempfile.mkstemp(suffix=".ifc")[1] + exportIFC.export(objs, tf) + ifc_import.insert(tf, doc.Name, singledoc=True) + + +def direct_conversion(objs, doc): + """Exports the given objects to the given ifcfile and recreates the contents""" + + prj_obj = ifc_tools.convert_document(doc, silent=True) + exportIFC.export(objs, doc.Proxy.ifcfile) + if PARAMS.GetBool("LoadOrphans", True): + ifc_tools.load_orphans(prj_obj) + if PARAMS.GetBool("LoadMaterials", False): + ifc_materials.load_materials(prj_obj) + if PARAMS.GetBool("LoadLayers", False): + ifc_layers.load_layers(prj_obj) + if PARAMS.GetBool("LoadPsets", False): + ifc_psets.load_psets(prj_obj) diff --git a/src/Mod/BIM/nativeifc/ifc_status.py b/src/Mod/BIM/nativeifc/ifc_status.py index 72381b8a16..c4c7823276 100644 --- a/src/Mod/BIM/nativeifc/ifc_status.py +++ b/src/Mod/BIM/nativeifc/ifc_status.py @@ -414,15 +414,14 @@ def lock_document(): elif doc.Objects: # 3 there is no project but objects doc.openTransaction("Lock document") - ifc_tools.convert_document(doc, silent=True) - ifcfile = doc.Proxy.ifcfile objs = find_toplevel(doc.Objects) - prefs, context = ifc_export.get_export_preferences(ifcfile) - exportIFC.export(objs, ifcfile, preferences=prefs) - for n in [o.Name for o in doc.Objects]: + deletelist = [o.Name for o in doc.Objects] + #ifc_export.export_and_convert(objs, doc) + ifc_export.direct_conversion(objs, doc) + for n in deletelist: if doc.getObject(n): doc.removeObject(n) - ifc_tools.create_children(doc, ifcfile, recursive=True) + doc.IfcFilePath = "" doc.Modified = True doc.commitTransaction() doc.recompute() @@ -443,7 +442,7 @@ def lock_document(): if create: if not ifcfile: ifcfile = doc.Proxy.ifcfile - ifc_tools.create_children(doc, recursive=False) + ifc_tools.create_children(doc, ifcfile, recursive=False) def find_toplevel(objs): diff --git a/src/Mod/BIM/nativeifc/ifc_tools.py b/src/Mod/BIM/nativeifc/ifc_tools.py index 1c3dd9aa39..9eaa5737be 100644 --- a/src/Mod/BIM/nativeifc/ifc_tools.py +++ b/src/Mod/BIM/nativeifc/ifc_tools.py @@ -66,7 +66,7 @@ def create_document(document, filename=None, shapemode=0, strategy=0, silent=Fal 1 = coin only 2 = no representation strategy: 0 = only root object - 1 = only bbuilding structure, + 1 = only building structure 2 = all children """ @@ -86,7 +86,7 @@ def create_document_object( 1 = coin only 2 = no representation strategy: 0 = only root object - 1 = only bbuilding structure, + 1 = only building structure 2 = all children """ @@ -199,10 +199,18 @@ def create_ifcfile(): application = "FreeCAD" version = FreeCAD.Version() version = ".".join([str(v) for v in version[0:3]]) + freecadorg = api_run( + "owner.add_organisation", + ifcfile, + identification="FreeCAD.org", + name="The FreeCAD project" + ) application = api_run( "owner.add_application", ifcfile, + application_developer=freecadorg, application_full_name=application, + application_identifier=application, version=version, ) # context @@ -225,9 +233,14 @@ def create_ifcfile(): parent=model3d, ) # unit - # for now, assign a default metre unit, as per https://blenderbim.org/docs-python/autoapi/ifcopenshell/api/unit/assign_unit/index.html + # for now, assign a default metre + sqm +degrees unit, as per + # https://docs.ifcopenshell.org/autoapi/ifcopenshell/api/unit/index.html # TODO allow to set this at creation, from the current FreeCAD units schema - api_run("unit.assign_unit", ifcfile) + length = api_run("unit.add_si_unit", ifcfile, unit_type="LENGTHUNIT") + area = api_run("unit.add_si_unit", ifcfile, unit_type="AREAUNIT") + angle = api_run("unit.add_conversion_based_unit", ifcfile, name="degree") + api_run("unit.assign_unit", ifcfile, units=[length, area, angle]) + # TODO add user history return ifcfile @@ -1608,6 +1621,7 @@ def recompute(children): stime = time.time() for c in children: c.touch() - FreeCAD.ActiveDocument.recompute() + if not FreeCAD.ActiveDocument.Recomputing: + FreeCAD.ActiveDocument.recompute() endtime = "%02d:%02d" % (divmod(round(time.time() - stime, 1), 60)) print("DEBUG: Extra recomputing of",len(children),"objects took",endtime)