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)