Arch: Moved building of IFC relationship tables into separate function

This commit is contained in:
Yorik van Havre
2019-08-20 17:59:30 -03:00
parent 037be677cd
commit aa344ffb39
2 changed files with 116 additions and 97 deletions

View File

@@ -284,102 +284,15 @@ def insert(filename,docname,skip=[],only=[],root=None):
if SPLIT_LAYERS and hasattr(settings,"APPLY_LAYERSETS"):
settings.set(settings.APPLY_LAYERSETS,True)
# gather easy entity types
sites = ifcfile.by_type("IfcSite")
buildings = ifcfile.by_type("IfcBuilding")
floors = ifcfile.by_type("IfcBuildingStorey")
products = ifcfile.by_type(ROOT_ELEMENT)
openings = ifcfile.by_type("IfcOpeningElement")
annotations = ifcfile.by_type("IfcAnnotation")
materials = ifcfile.by_type("IfcMaterial")
if DEBUG: print("Building relationships table...",end="")
# building relations tables
# TODO use inverse attributes, see https://forum.freecadweb.org/viewtopic.php?f=39&t=37892
# done for properties
# build all needed tables
objects,prodrepr,additions,groups,subtractions,colors,shapes, \
structshapes,mattable,sharedobjects,parametrics,profiles, \
sites,buildings,floors,products,openings,annotations,materials, \
style_material_id = importIFCHelper.buildRelationships(ifcfile,ROOT_ELEMENT)
objects = {} # { id:object, ... }
prodrepr = {} # product/representations table
additions = {} # { host:[child,...], ... }
groups = {} # { host:[child,...], ... } # used in structural IFC
subtractions = [] # [ [opening,host], ... ]
colors = {} # { id:(r,g,b) }
shapes = {} # { id:shaoe } only used for merge mode
structshapes = {} # { id:shaoe } only used for merge mode
mattable = {} # { objid:matid }
sharedobjects = {} # { representationmapid:object }
parametrics = [] # a list of imported objects whose parametric relationships need processing after all objects have been created
profiles = {} # to store reused extrusion profiles {ifcid:fcobj,...}
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("IfcRelAssociatesMaterial"):
for o in r.RelatedObjects:
if r.RelatingMaterial.is_a("IfcMaterial"):
mattable[o.id()] = r.RelatingMaterial.id()
elif r.RelatingMaterial.is_a("IfcMaterialLayer"):
mattable[o.id()] = r.RelatingMaterial.Material.id()
elif r.RelatingMaterial.is_a("IfcMaterialLayerSet"):
mattable[o.id()] = r.RelatingMaterial.MaterialLayers[0].Material.id()
elif r.RelatingMaterial.is_a("IfcMaterialLayerSetUsage"):
mattable[o.id()] = r.RelatingMaterial.ForLayerSet.MaterialLayers[0].Material.id()
for p in ifcfile.by_type("IfcProduct"):
if hasattr(p,"Representation"):
if p.Representation:
for it in p.Representation.Representations:
for it1 in it.Items:
prodrepr.setdefault(p.id(),[]).append(it1.id())
if it1.is_a("IfcBooleanResult"):
prodrepr.setdefault(p.id(),[]).append(it1.FirstOperand.id())
elif it.Items[0].is_a("IfcMappedItem"):
prodrepr.setdefault(p.id(),[]).append(it1.MappingSource.MappedRepresentation.id())
if it1.MappingSource.MappedRepresentation.is_a("IfcShapeRepresentation"):
for it2 in it1.MappingSource.MappedRepresentation.Items:
prodrepr.setdefault(p.id(),[]).append(it2.id())
# colors
style_color_rgb = {} # { style_entity_id: (r,g,b) }
for r in ifcfile.by_type("IfcStyledItem"):
if r.Styles:
if r.Styles[0].is_a("IfcPresentationStyleAssignment"):
for style1 in r.Styles[0].Styles:
if style1.is_a("IfcSurfaceStyle"):
for style2 in style1.Styles:
if style2.is_a("IfcSurfaceStyleRendering"):
if style2.SurfaceColour:
c = style2.SurfaceColour
style_color_rgb[r.id()] = (c.Red,c.Green,c.Blue)
style_material_id = {} # { style_entity_id: material_id) }
# Allplan, ArchiCAD
for m in ifcfile.by_type("IfcMaterialDefinitionRepresentation"):
for it in m.Representations:
if it.Items:
style_material_id[it.Items[0].id()] = m.RepresentedMaterial.id()
# Nova
for r in ifcfile.by_type("IfcStyledItem"):
if r.Item:
for p in prodrepr.keys():
if r.Item.id() in prodrepr[p]:
style_material_id[r.id()] = p
# create colors out of style_color_rgb and style_material_id
for k in style_material_id:
if k in style_color_rgb:
colors[style_material_id[k]] = style_color_rgb[k]
# remove any leftover annotations from products
tp = []
for product in products:
if product.is_a("IfcGrid") and not (product in annotations):
annotations.append(product)
elif not (product in annotations):
tp.append(product)
products = sorted(tp,key=lambda prod: prod.id())
if DEBUG: print("done.")
# only import a list of IDs and their children
if only:
@@ -391,13 +304,11 @@ def insert(filename,docname,skip=[],only=[],root=None):
only.extend(additions[currentid])
products = [ifcfile[currentid] for currentid in ids]
if DEBUG: print("done.")
count = 0
from FreeCAD import Base
progressbar = Base.ProgressIndicator()
progressbar.start("Importing IFC objects...",len(products))
if DEBUG: print("Processing",len(products),"BIM objects...")
if DEBUG: print("Prsing",len(products),"BIM objects...")
if FITVIEW_ONIMPORT and FreeCAD.GuiUp:
overallboundbox = None
@@ -1198,7 +1109,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
if mdict:
mat.Material = mdict
fcmats[mat.Name] = mat
# fill material attribute of the objects
# fill material attribute of the objects
for o,m in mattable.items():
if m == material.id():
if o in objects:

View File

@@ -68,3 +68,111 @@ class ProjectImporter:
def calculateTrueNorthAngle(self, x, y):
return round(math.degrees(math.atan2(y, x)) - 90, 6)
def buildRelationships(ifcfile,root_element):
"""Builds different tables from an IFC file"""
# building relations tables
# TODO use inverse attributes, see https://forum.freecadweb.org/viewtopic.php?f=39&t=37892
# done for properties
objects = {} # { id:object, ... }
prodrepr = {} # product/representations table
additions = {} # { host:[child,...], ... }
groups = {} # { host:[child,...], ... } # used in structural IFC
subtractions = [] # [ [opening,host], ... ]
colors = {} # { id:(r,g,b) }
shapes = {} # { id:shaoe } only used for merge mode
structshapes = {} # { id:shaoe } only used for merge mode
mattable = {} # { objid:matid }
sharedobjects = {} # { representationmapid:object }
parametrics = [] # a list of imported objects whose parametric relationships need processing after all objects have been created
profiles = {} # to store reused extrusion profiles {ifcid:fcobj,...}
style_material_id = {} # { style_entity_id: material_id) }
# gather easy entity types
sites = ifcfile.by_type("IfcSite")
buildings = ifcfile.by_type("IfcBuilding")
floors = ifcfile.by_type("IfcBuildingStorey")
products = ifcfile.by_type(root_element)
openings = ifcfile.by_type("IfcOpeningElement")
annotations = ifcfile.by_type("IfcAnnotation")
materials = ifcfile.by_type("IfcMaterial")
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("IfcRelAssociatesMaterial"):
for o in r.RelatedObjects:
if r.RelatingMaterial.is_a("IfcMaterial"):
mattable[o.id()] = r.RelatingMaterial.id()
elif r.RelatingMaterial.is_a("IfcMaterialLayer"):
mattable[o.id()] = r.RelatingMaterial.Material.id()
elif r.RelatingMaterial.is_a("IfcMaterialLayerSet"):
mattable[o.id()] = r.RelatingMaterial.MaterialLayers[0].Material.id()
elif r.RelatingMaterial.is_a("IfcMaterialLayerSetUsage"):
mattable[o.id()] = r.RelatingMaterial.ForLayerSet.MaterialLayers[0].Material.id()
for p in ifcfile.by_type("IfcProduct"):
if hasattr(p,"Representation"):
if p.Representation:
for it in p.Representation.Representations:
for it1 in it.Items:
prodrepr.setdefault(p.id(),[]).append(it1.id())
if it1.is_a("IfcBooleanResult"):
prodrepr.setdefault(p.id(),[]).append(it1.FirstOperand.id())
elif it.Items[0].is_a("IfcMappedItem"):
prodrepr.setdefault(p.id(),[]).append(it1.MappingSource.MappedRepresentation.id())
if it1.MappingSource.MappedRepresentation.is_a("IfcShapeRepresentation"):
for it2 in it1.MappingSource.MappedRepresentation.Items:
prodrepr.setdefault(p.id(),[]).append(it2.id())
# colors
style_color_rgb = {} # { style_entity_id: (r,g,b) }
for r in ifcfile.by_type("IfcStyledItem"):
if r.Styles:
if r.Styles[0].is_a("IfcPresentationStyleAssignment"):
for style1 in r.Styles[0].Styles:
if style1.is_a("IfcSurfaceStyle"):
for style2 in style1.Styles:
if style2.is_a("IfcSurfaceStyleRendering"):
if style2.SurfaceColour:
c = style2.SurfaceColour
style_color_rgb[r.id()] = (c.Red,c.Green,c.Blue)
# Nova
if r.Item:
for p in prodrepr.keys():
if r.Item.id() in prodrepr[p]:
style_material_id[r.id()] = p
# Allplan, ArchiCAD
for m in ifcfile.by_type("IfcMaterialDefinitionRepresentation"):
for it in m.Representations:
if it.Items:
style_material_id[it.Items[0].id()] = m.RepresentedMaterial.id()
# create colors out of style_color_rgb and style_material_id
for k in style_material_id:
if k in style_color_rgb:
colors[style_material_id[k]] = style_color_rgb[k]
# remove any leftover annotations from products
tp = []
for product in products:
if product.is_a("IfcGrid") and not (product in annotations):
annotations.append(product)
elif not (product in annotations):
tp.append(product)
products = sorted(tp,key=lambda prod: prod.id())
return objects,prodrepr,additions,groups,subtractions,colors,shapes, \
structshapes,mattable,sharedobjects,parametrics,profiles, \
sites,buildings,floors,products,openings,annotations,materials, \
style_material_id