BIM: Several fixes to nativeIFC lock/unlock system - fixes #17862

This commit is contained in:
Yorik van Havre
2024-12-17 17:03:33 +01:00
committed by Yorik van Havre
parent bcdfcce95c
commit a7c550da98
5 changed files with 74 additions and 15 deletions

View File

@@ -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()

View File

@@ -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 = "<html><body>\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.") + "<br/>\n"
elif diff:
diff = diff.split("\n")
for l in diff:
if l.startswith("+"):

View File

@@ -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)

View File

@@ -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):

View File

@@ -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)