diff --git a/src/Mod/Arch/Resources/ui/preferences-ifc.ui b/src/Mod/Arch/Resources/ui/preferences-ifc.ui
index 73fe1a5ad..a66584aa0 100644
--- a/src/Mod/Arch/Resources/ui/preferences-ifc.ui
+++ b/src/Mod/Arch/Resources/ui/preferences-ifc.ui
@@ -6,8 +6,8 @@
0
0
- 376
- 399
+ 456
+ 478
@@ -60,7 +60,7 @@
-
- Import IFC objects as
+ Import arch IFC objects as
@@ -70,7 +70,7 @@
Specifies what kind of objects will be created in FreeCAD
- ifcImportMode
+ ifcImportModeArch
Mod/Arch
@@ -95,6 +95,55 @@
One compound per floor
+ -
+
+ Do not import Arch objects
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Import struct IFC objects as
+
+
+
+ -
+
+
+ Specifies what kind of objects will be created in FreeCAD
+
+
+ ifcImportModeStruct
+
+
+ Mod/Arch
+
+
-
+
+ Non-parametric Arch objects
+
+
+ -
+
+ Simple Part shapes
+
+
+ -
+
+ One compound for all
+
+
+ -
+
+ Do not import structural objects
+
+
diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py
index 1be622b39..c53ca6506 100644
--- a/src/Mod/Arch/importIFC.py
+++ b/src/Mod/Arch/importIFC.py
@@ -44,6 +44,11 @@ typesmap = { "Site": ["IfcSite"],
"Equipment": ["IfcFurnishingElement","IfcSanitaryTerminal","IfcFlowTerminal","IfcElectricAppliance"]
}
+# which IFC entity (product) is a structural object
+structuralifcobjects = ('IfcStructuralSurfaceMember', 'IfcStructuralCurveMember',
+ 'IfcStructuralPointConnection', 'IfcStructuralSurfaceConnection',
+ 'IfcStructuralAction', 'IfcStructuralPointAction')
+
# specific name translations
translationtable = { "Foundation":"Footing",
"Floor":"BuildingStorey",
@@ -286,8 +291,9 @@ def insert(filename,docname,skip=[],only=[],root=None):
MERGE_MATERIALS = p.GetBool("ifcMergeMaterials",False)
if root:
ROOT_ELEMENT = root
- MERGE_MODE = p.GetInt("ifcImportMode",0)
- if MERGE_MODE > 0:
+ MERGE_MODE_ARCH = p.GetInt("ifcImportModeArch",0)
+ MERGE_MODE_STRUCT = p.GetInt("ifcImportModeStruct",1)
+ if MERGE_MODE_ARCH > 0:
SEPARATE_OPENINGS = False
GET_EXTRUSIONS = False
if not SEPARATE_OPENINGS:
@@ -318,6 +324,8 @@ def insert(filename,docname,skip=[],only=[],root=None):
settings.set(settings.USE_WORLD_COORDS,True)
if SEPARATE_OPENINGS:
settings.set(settings.DISABLE_OPENING_SUBTRACTIONS,True)
+ if MERGE_MODE_STRUCT != 3:
+ settings.set(settings.INCLUDE_CURVES,True)
sites = ifcfile.by_type("IfcSite")
buildings = ifcfile.by_type("IfcBuilding")
floors = ifcfile.by_type("IfcBuildingStorey")
@@ -331,15 +339,19 @@ def insert(filename,docname,skip=[],only=[],root=None):
# building relations tables
objects = {} # { id:object, ... }
additions = {} # { host:[child,...], ... }
+ groups = {} # { host:[child,...], ... } # used in structural IFC
subtractions = [] # [ [opening,host], ... ]
properties = {} # { host:[property, ...], ... }
colors = {} # { id:(r,g,b) }
shapes = {} # { id:shaoe } only used for merge mode
+ structshapes = {} # { id:shaoe } only used for merge mode
mattable = {} # { objid:matid }
for r in ifcfile.by_type("IfcRelContainedInSpatialStructure"):
additions.setdefault(r.RelatingStructure.id(),[]).extend([e.id() for e in r.RelatedElements])
for r in ifcfile.by_type("IfcRelAggregates"):
additions.setdefault(r.RelatingObject.id(),[]).extend([e.id() for e in r.RelatedObjects])
+ for r in ifcfile.by_type("IfcRelAssignsToGroup"):
+ groups.setdefault(r.RelatingGroup.id(),[]).extend([e.id() for e in r.RelatedObjects])
for r in ifcfile.by_type("IfcRelVoidsElement"):
subtractions.append([r.RelatedOpeningElement.id(), r.RelatingBuildingElement.id()])
for r in ifcfile.by_type("IfcRelDefinesByProperties"):
@@ -403,6 +415,15 @@ def insert(filename,docname,skip=[],only=[],root=None):
baseobj = None
brep = None
+ archobj = True # assume all objects not in structuralifcobjects are architecture
+ if ptype in structuralifcobjects:
+ archobj = False
+ if MERGE_MODE_ARCH == 4 and archobj:
+ if DEBUG: print " skipped."
+ continue
+ if MERGE_MODE_STRUCT == 3 and not archobj:
+ if DEBUG: print " skipped."
+ continue
if pid in skip: # user given id skip list
if DEBUG: print " skipped."
continue
@@ -425,9 +446,13 @@ def insert(filename,docname,skip=[],only=[],root=None):
shape.scale(1000.0) # IfcOpenShell always outputs in meters
if not shape.isNull():
- if MERGE_MODE > 0:
+ if (MERGE_MODE_ARCH > 0 and archobj) or not archobj:
if ptype == "IfcSpace": # do not add spaces to compounds
if DEBUG: print "skipping space ",pid
+ elif not archobj:
+ structshapes[pid] = shape
+ if DEBUG: print shape.Solids
+ baseobj = shape
else:
shapes[pid] = shape
if DEBUG: print shape.Solids
@@ -456,7 +481,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
else:
if DEBUG: print " no brep ",
- if MERGE_MODE == 0:
+ if MERGE_MODE_ARCH == 0 and archobj :
# full Arch objects
for freecadtype,ifctypes in typesmap.items():
@@ -490,7 +515,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
if DEBUG: print sols
objects[pid] = obj
- elif MERGE_MODE == 1:
+ elif (MERGE_MODE_ARCH == 1 and archobj) or (MERGE_MODE_STRUCT == 0 and not archobj):
# non-parametric Arch objects
if ptype in ["IfcSite","IfcBuilding","IfcBuildingStorey"]:
@@ -500,7 +525,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
elif baseobj:
obj = Arch.makeComponent(baseobj,name=name,delete=True)
- elif MERGE_MODE == 2:
+ elif (MERGE_MODE_ARCH == 2 and archobj) or (MERGE_MODE_STRUCT == 1 and not archobj):
# Part shapes
if ptype in ["IfcSite","IfcBuilding","IfcBuildingStorey"]:
@@ -540,11 +565,57 @@ def insert(filename,docname,skip=[],only=[],root=None):
progressbar.stop()
FreeCAD.ActiveDocument.recompute()
- if MERGE_MODE == 3:
+ if MERGE_MODE_STRUCT == 2:
+
+ if DEBUG: print "Joining Structural shapes..."
+
+ for host,children in groups.items(): # Structural
+ if ifcfile[host].is_a("IfcStructuralAnalysisModel"):
+ compound = []
+ for c in children:
+ if c in structshapes.keys():
+ compound.append(structshapes[c])
+ del structshapes[c]
+ if compound:
+ name = ifcfile[host].Name or "AnalysisModel"
+ if PREFIX_NUMBERS: name = "ID" + str(host) + " " + name
+ obj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
+ obj.Label = name
+ obj.Shape = Part.makeCompound(compound)
+ if structshapes: # remaining Structural shapes
+ obj = FreeCAD.ActiveDocument.addObject("Part::Feature","UnclaimedStruct")
+ obj.Shape = Part.makeCompound(structshapes.values())
+ else:
- if DEBUG: print "Joining shapes..."
+ if DEBUG: print "Processing Struct relationships..."
+
+ # groups
+ for host,children in groups.items():
+ if ifcfile[host].is_a("IfcStructuralAnalysisModel"):
+ obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup","AnalysisModel")
+ objects[host] = obj
+ if host in objects.keys():
+ cobs = [objects[child] for child in children if child in objects.keys()]
+ if cobs:
+ if DEBUG: print "adding ",len(cobs), " object(s) to ", objects[host].Label
+ Arch.addComponents(cobs,objects[host])
+ if DEBUG: FreeCAD.ActiveDocument.recompute()
+
+ if MERGE_MODE_ARCH > 2: # if ArchObj is compound or ArchObj not imported
+ FreeCAD.ActiveDocument.recompute()
+
+ # cleaning bad shapes
+ for obj in objects.values():
+ if obj.isDerivedFrom("Part::Feature"):
+ if obj.Shape.isNull():
+ Arch.rebuildArchShape(obj)
+
+
+ if MERGE_MODE_ARCH == 3:
- for host,children in additions.items():
+ if DEBUG: print "Joining Arch shapes..."
+
+ for host,children in additions.items(): # Arch
if ifcfile[host].is_a("IfcBuildingStorey"):
compound = []
for c in children:
@@ -562,13 +633,13 @@ def insert(filename,docname,skip=[],only=[],root=None):
obj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
obj.Label = name
obj.Shape = Part.makeCompound(compound)
- if shapes: # remaining shapes
- obj = FreeCAD.ActiveDocument.addObject("Part::Feature","Unclaimed")
+ if shapes: # remaining Arch shapes
+ obj = FreeCAD.ActiveDocument.addObject("Part::Feature","UnclaimedArch")
obj.Shape = Part.makeCompound(shapes.values())
else:
- if DEBUG: print "Processing relationships..."
+ if DEBUG: print "Processing Arch relationships..."
# subtractions
if SEPARATE_OPENINGS: