Merge pull request #89 from wood-galaxy/bim-ifcproperty3

Arch - BIM - Add IFC Spreadsheet properties system
This commit is contained in:
Yorik van Havre 2016-02-04 23:29:55 -02:00
commit 1867c0d276
5 changed files with 196 additions and 42 deletions

View File

@ -1208,6 +1208,47 @@ class _CommandComponent:
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
def makeIfcSpreadsheet(obj=None):
import Spreadsheet
ifc_spreadsheet = FreeCAD.ActiveDocument.addObject('Spreadsheet::Sheet','IfcProperties')
ifc_spreadsheet.set('A1', translate("Arch","Category"))
ifc_spreadsheet.set('B1', translate("Arch","Key"))
ifc_spreadsheet.set('C1', translate("Arch","Type"))
ifc_spreadsheet.set('D1', translate("Arch","Value"))
ifc_spreadsheet.set('E1', translate("Arch","Unit"))
if obj :
if hasattr(obj,"IfcProperties"):
obj.IfcProperties = ifc_spreadsheet
return ifc_spreadsheet
else :
FreeCAD.Console.PrintWarning(translate("Arch", "The object have not IfcProperties attribute. Cancel spreadsheet creation for object : ") + obj.Label)
FreeCAD.ActiveDocument.removeObject(ifc_spreadsheet)
else:
return ifc_spreadsheet
class _CommandIfcSpreadsheet:
"the Arch Schedule command definition"
def GetResources(self):
return {'Pixmap': 'Arch_Schedule',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_IfcSpreadsheet","Create IFC spreadsheet..."),
'Accel': "I, P",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_IfcSpreadsheet","Creates a spreadsheet to store ifc properties of an object.")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create IFC properties spreadsheet"))
FreeCADGui.addModule("Arch")
FreeCADGui.Control.closeDialog()
if sel:
for o in sel:
FreeCADGui.doCommand("Arch.makeIfcSpreadsheet(FreeCAD.ActiveDocument."+o.Name+")")
else :
FreeCADGui.doCommand("Arch.makeIfcSpreadsheet()")
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Add',_CommandAdd())
@ -1222,3 +1263,4 @@ if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Survey',_CommandSurvey())
FreeCADGui.addCommand('Arch_ToggleIfcBrepFlag',_ToggleIfcBrepFlag())
FreeCADGui.addCommand('Arch_Component',_CommandComponent())
FreeCADGui.addCommand('Arch_IfcSpreadsheet',_CommandIfcSpreadsheet())

View File

@ -299,6 +299,7 @@ class Component:
obj.addProperty("App::PropertyLink","BaseMaterial","Material",translate("Arch","A material for this object"))
obj.addProperty("App::PropertyEnumeration","Role","Arch",translate("Arch","The role of this object"))
obj.addProperty("App::PropertyBool","MoveWithHost","Arch",translate("Arch","Specifies if this object must move together when its host is moved"))
obj.addProperty("App::PropertyLink","IfcProperties","Arch",translate("Arch","Custom IFC properties and attributes"))
obj.Proxy = self
self.Type = "Component"
self.Subvolume = None

View File

@ -80,7 +80,7 @@ class ArchWorkbench(Workbench):
"Arch_SelectNonSolidMeshes","Arch_RemoveShape",
"Arch_CloseHoles","Arch_MergeWalls","Arch_Check",
"Arch_IfcExplorer","Arch_ToggleIfcBrepFlag","Arch_3Views",
"Arch_Bimserver","Arch_Git"]
"Arch_Bimserver","Arch_Git","Arch_IfcSpreadsheet"]
# draft tools
self.drafttools = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse",

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>456</width>
<height>542</height>
<height>564</height>
</rect>
</property>
<property name="windowTitle">
@ -288,6 +288,26 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="Gui::PrefCheckBox" name="checkBox_8">
<property name="toolTip">
<string>If checked each object will have their Ifc Properties stored in a spreadsheet object.</string>
</property>
<property name="text">
<string>Import Ifc Properties in spreadsheet</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>ifcImportProperties</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Arch</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
@ -414,13 +434,13 @@
<header>Gui/PrefWidgets.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefComboBox</class>
<extends>QComboBox</extends>
<class>Gui::PrefLineEdit</class>
<extends>QLineEdit</extends>
<header>Gui/PrefWidgets.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefLineEdit</class>
<extends>QLineEdit</extends>
<class>Gui::PrefComboBox</class>
<extends>QComboBox</extends>
<header>Gui/PrefWidgets.h</header>
</customwidget>
</customwidgets>

View File

@ -22,7 +22,7 @@
#***************************************************************************
__title__ = "FreeCAD IFC importer - Enhanced ifcopenshell-only version"
__author__ = "Yorik van Havre"
__author__ = "Yorik van Havre","Jonathan Wiedemann"
__url__ = "http://www.freecadweb.org"
import os,time,tempfile,uuid,FreeCAD,Part,Draft,Arch,math,DraftVecUtils
@ -124,7 +124,7 @@ def getPreferences():
global DEBUG, PREFIX_NUMBERS, SKIP, SEPARATE_OPENINGS
global ROOT_ELEMENT, GET_EXTRUSIONS, MERGE_MATERIALS
global MERGE_MODE_ARCH, MERGE_MODE_STRUCT, CREATE_CLONES
global FORCE_BREP
global FORCE_BREP, IMPORT_PROPERTIES
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
if FreeCAD.GuiUp and p.GetBool("ifcShowDialog",False):
import FreeCADGui
@ -145,6 +145,7 @@ def getPreferences():
SKIP.append("IfcOpeningElement")
CREATE_CLONES = p.GetBool("ifcCreateClones",True)
FORCE_BREP = p.GetBool("ifcExportAsBrep",False)
IMPORT_PROPERTIES = p.GetBool("ifcImportProperties",False)
def explore(filename=None):
@ -363,7 +364,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
additions = {} # { host:[child,...], ... }
groups = {} # { host:[child,...], ... } # used in structural IFC
subtractions = [] # [ [opening,host], ... ]
properties = {} # { host:[property, ...], ... }
properties = {} # { obj : { cat : [property, ... ], ... }, ... }
colors = {} # { id:(r,g,b) }
shapes = {} # { id:shaoe } only used for merge mode
structshapes = {} # { id:shaoe } only used for merge mode
@ -379,8 +380,14 @@ def insert(filename,docname,skip=[],only=[],root=None):
subtractions.append([r.RelatedOpeningElement.id(), r.RelatingBuildingElement.id()])
for r in ifcfile.by_type("IfcRelDefinesByProperties"):
for obj in r.RelatedObjects:
if not obj.id() in properties :
properties[obj.id()] = {}
prop_by_category = {}
prop = []
if r.RelatingPropertyDefinition.is_a("IfcPropertySet"):
properties.setdefault(obj.id(),[]).extend([e.id() for e in r.RelatingPropertyDefinition.HasProperties])
prop.extend([e.id() for e in r.RelatingPropertyDefinition.HasProperties])
prop_by_category[r.RelatingPropertyDefinition.id()] = prop
properties[obj.id()].update(prop_by_category)
for r in ifcfile.by_type("IfcRelAssociatesMaterial"):
for o in r.RelatedObjects:
mattable[o.id()] = r.RelatingMaterial.id()
@ -614,12 +621,40 @@ def insert(filename,docname,skip=[],only=[],root=None):
# properties
if pid in properties:
if hasattr(obj,"IfcAttributes"):
if IMPORT_PROPERTIES and hasattr(obj,"IfcProperties") :
ifc_spreadsheet = Arch.makeIfcSpreadsheet()
n=2
for c in properties[pid].keys():
o = ifcfile[c]
if DEBUG : print("propertyset Name",o.Name,type(o.Name))
catname = o.Name
for p in properties[pid][c]:
l = ifcfile[p]
if l.is_a("IfcPropertySingleValue"):
if IMPORT_PROPERTIES :
if DEBUG :
print("property name",l.Name,type(l.Name))
print("property NominalValue",l.NominalValue.is_a(),type(l.NominalValue.is_a()))
print("property NominalValue.wrappedValue",l.NominalValue.wrappedValue,type(l.NominalValue.wrappedValue))
#print("l.NominalValue.Unit",l.NominalValue.Unit,type(l.NominalValue.Unit))
ifc_spreadsheet.set(str('A'+str(n)), catname.encode("utf8"))
ifc_spreadsheet.set(str('B'+str(n)), l.Name.encode("utf8"))
ifc_spreadsheet.set(str('C'+str(n)), l.NominalValue.is_a())
if l.NominalValue.is_a() in ['IfcLabel','IfcText','IfcIdentifier']:
ifc_spreadsheet.set(str('D'+str(n)), "'" + str(l.NominalValue.wrappedValue.encode("utf8")))
else :
ifc_spreadsheet.set(str('D'+str(n)), str(l.NominalValue.wrappedValue))
if hasattr(l.NominalValue,'Unit') :
ifc_spreadsheet.set(str('E'+str(n)), str(l.NominalValue.Unit))
n += 1
obj.IfcProperties = ifc_spreadsheet
elif hasattr(obj,"IfcAttributes"):
a = obj.IfcAttributes
for p in properties[pid]:
o = ifcfile[p]
if o.is_a("IfcPropertySingleValue"):
a[o.Name.encode("utf8")] = str(o.NominalValue)
for c in properties[pid].keys():
for p in properties[pid][c]:
l = ifcfile[p]
if l.is_a("IfcPropertySingleValue"):
a[l.Name.encode("utf8")] = str(l.NominalValue)
obj.IfcAttributes = a
# color
@ -944,35 +979,91 @@ def export(exportList,filename):
ifcfile.createIfcRelVoidsElement(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'Subtraction','',product,prod2)
# properties
if hasattr(obj,"IfcAttributes"):
props = []
for key in obj.IfcAttributes:
if not (key in ["IfcUID","FlagForceBrep"]):
r = obj.IfcAttributes[key].strip(")").split("(")
if len(r) == 1:
tp = "IfcText"
val = r[0]
else:
tp = r[0]
val = "(".join(r[1:])
val = val.strip("'")
val = val.strip('"')
if DEBUG: print " property ",key," : ",val.encode("utf8"), " (", str(tp), ")"
if tp in ["IfcLabel","IfcText","IfcIdentifier"]:
val = val.encode("utf8")
elif tp == "IfcBoolean":
if val == ".T.":
val = True
if hasattr(obj,"IfcProperties") or hasattr(obj,"IfcAttributes"):
if DEBUG : print(" add ifc properties")
if obj.IfcProperties:
if obj.IfcProperties.TypeId == 'Spreadsheet::Sheet':
sheet = obj.IfcProperties
propertiesDic = {}
categories = []
n=2
cell = True
while cell == True :
if hasattr(sheet,'A'+str(n)):
cat = sheet.get('A'+str(n))
key = sheet.get('B'+str(n))
tp = sheet.get('C'+str(n))
if hasattr(sheet,'D'+str(n)):
val = sheet.get('D'+str(n))
else:
val = False
elif tp == "IfcInteger":
val = int(val)
val = ''
if isinstance(key, unicode):
key = key.encode("utf8")
else :
key = str(key)
tp = tp.encode("utf8")
if tp in ["IfcLabel","IfcText","IfcIdentifier"]:
val = val.encode("utf8")
elif tp == "IfcBoolean":
if val == 'True':
val = True
else:
val = False
elif tp == "IfcInteger":
val = int(val)
else:
val = float(val)
unit = None
#unit = sheet.get('E'+str(n))
if cat in categories :
propertiesDic[cat].append({"key":key,"tp":tp,"val":val,"unit":unit})
else:
propertiesDic[cat] = [{"key":key,"tp":tp,"val":val,"unit":unit}]
categories.append(cat)
n += 1
else:
val = float(val)
props.append(ifcfile.createIfcPropertySingleValue(str(key),None,ifcfile.create_entity(str(tp),val),None))
if props:
pset = ifcfile.createIfcPropertySet(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'PropertySet',None,props)
ifcfile.createIfcRelDefinesByProperties(ifcopenshell.guid.compress(uuid.uuid1().hex),history,None,None,[product],pset)
cell = False
for cat in propertiesDic:
props = []
for prop in propertiesDic[cat] :
if DEBUG :
print("key",prop["key"],type(prop["key"]))
print("tp",prop["tp"],type(prop["tp"]))
print("val",prop["val"],type(prop["val"]))
props.append(ifcfile.createIfcPropertySingleValue(prop["key"],None,ifcfile.create_entity(prop["tp"],prop["val"]),None))
pset = ifcfile.createIfcPropertySet(ifcopenshell.guid.compress(uuid.uuid1().hex),history,cat,None,props)
ifcfile.createIfcRelDefinesByProperties(ifcopenshell.guid.compress(uuid.uuid1().hex),history,None,None,[product],pset)
elif obj.IfcAttributes:
props = []
for key in obj.IfcAttributes:
if not (key in ["IfcUID","FlagForceBrep"]):
r = obj.IfcAttributes[key].strip(")").split("(")
if len(r) == 1:
tp = "IfcText"
val = r[0]
else:
tp = r[0]
val = "(".join(r[1:])
val = val.strip("'")
val = val.strip('"')
if DEBUG: print " property ",key," : ",val.encode("utf8"), " (", str(tp), ")"
if tp in ["IfcLabel","IfcText","IfcIdentifier"]:
val = val.encode("utf8")
elif tp == "IfcBoolean":
if val == ".T.":
val = True
else:
val = False
elif tp == "IfcInteger":
val = int(val)
else:
val = float(val)
props.append(ifcfile.createIfcPropertySingleValue(str(key),None,ifcfile.create_entity(str(tp),val),None))
if props:
pset = ifcfile.createIfcPropertySet(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'PropertySet',None,props)
ifcfile.createIfcRelDefinesByProperties(ifcopenshell.guid.compress(uuid.uuid1().hex),history,None,None,[product],pset)
else:
if DEBUG : print("no ifc properties to export")
count += 1