diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index a36012cf43..1fd72f352e 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -28,10 +28,20 @@ __author__ = "Yorik van Havre","Jonathan Wiedemann" __url__ = "http://www.freecadweb.org" import six +import os +import time +import tempfile +import uuid +import math +import sys -import os,time,tempfile,uuid,FreeCAD,Part,Draft,Arch,math,DraftVecUtils,sys -from DraftGeomUtils import vec +import FreeCAD +import Part +import Draft +import Arch +import DraftVecUtils import ArchIFCSchema +from DraftGeomUtils import vec ## @package importIFC # \ingroup ARCH @@ -46,31 +56,88 @@ ZOOMOUT = True # Set to False to not zoom extents after import if open.__module__ in ['__builtin__','io']: pyopen = open # because we'll redefine open below + +# ************************************************************************************************ +# ********** templates and other definitions **** # which IFC type must create which FreeCAD type typesmap = { - "Site": ["IfcSite"], - "Building": ["IfcBuilding"], - "Floor": ["IfcBuildingStorey"], - "Structure": ["IfcBeam", "IfcBeamStandardCase", "IfcColumn", "IfcColumnStandardCase", "IfcSlab", "IfcFooting", "IfcPile", "IfcTendon"], - "Wall": ["IfcWall", "IfcWallStandardCase", "IfcCurtainWall"], - "Window": ["IfcWindow", "IfcWindowStandardCase", "IfcDoor", "IfcDoorStandardCase"], - "Roof": ["IfcRoof"], - "Stairs": ["IfcStair", "IfcStairFlight", "IfcRamp", "IfcRampFlight"], - "Space": ["IfcSpace"], - "Rebar": ["IfcReinforcingBar"], - "Panel": ["IfcPlate"], - "Equipment": ["IfcFurnishingElement","IfcSanitaryTerminal","IfcFlowTerminal","IfcElectricAppliance"], - "Pipe": ["IfcPipeSegment"], - "PipeConnector":["IfcPipeFitting"], - "BuildingPart": ["IfcElementAssembly"] + "Site": [ + "IfcSite" + ], + "Building": [ + "IfcBuilding" + ], + "Floor": [ + "IfcBuildingStorey" + ], + "Structure": [ + "IfcBeam", + "IfcBeamStandardCase", + "IfcColumn", + "IfcColumnStandardCase", + "IfcSlab", + "IfcFooting", + "IfcPile", + "IfcTendon" + ], + "Wall": [ + "IfcWall", + "IfcWallStandardCase", + "IfcCurtainWall" + ], + "Window": [ + "IfcWindow", + "IfcWindowStandardCase", + "IfcDoor", + "IfcDoorStandardCase" + ], + "Roof": [ + "IfcRoof" + ], + "Stairs": [ + "IfcStair", + "IfcStairFlight", + "IfcRamp", + "IfcRampFlight" + ], + "Space": [ + "IfcSpace" + ], + "Rebar": [ + "IfcReinforcingBar" + ], + "Panel": [ + "IfcPlate" + ], + "Equipment": [ + "IfcFurnishingElement", + "IfcSanitaryTerminal", + "IfcFlowTerminal", + "IfcElectricAppliance" + ], + "Pipe": [ + "IfcPipeSegment" + ], + "PipeConnector": [ + "IfcPipeFitting" + ], + "BuildingPart":[ + "IfcElementAssembly" + ] } # which IFC entity (product) is a structural object structuralifcobjects = ( - "IfcStructuralCurveMember", "IfcStructuralSurfaceMember", - "IfcStructuralPointConnection", "IfcStructuralCurveConnection", "IfcStructuralSurfaceConnection", - "IfcStructuralAction", "IfcStructuralPointAction", - "IfcStructuralLinearAction", "IfcStructuralLinearActionVarying", "IfcStructuralPlanarAction" + "IfcStructuralCurveMember", + "IfcStructuralSurfaceMember", + "IfcStructuralPointConnection", + "IfcStructuralCurveConnection", + "IfcStructuralSurfaceConnection", + "IfcStructuralAction", + "IfcStructuralPointAction", + "IfcStructuralLinearAction", + "IfcStructuralLinearActionVarying", + "IfcStructuralPlanarAction" ) # specific FreeCAD <-> IFC slang translations @@ -120,6 +187,8 @@ END-ISO-10303-21; """ +# ************************************************************************************************ +# ********** some helper, used in import and export and exploerer def decode(filename,utf=False): "turns unicodes into strings" @@ -202,6 +271,8 @@ def getPreferences(): FITVIEW_ONIMPORT = p.GetBool("ifcFitViewOnImport",False) +# ************************************************************************************************ +# ********** IFC explorer *********************** def explore(filename=None): """explore([filename]): opens a dialog showing @@ -296,7 +367,7 @@ def explore(filename=None): elif entity.is_a() in ["IfcReinforcingBar"]: item.setIcon(1,QtGui.QIcon(":icons/Arch_Rebar.svg")) item.setText(2,str(entity.is_a())) - item.setFont(2,bold); + item.setFont(2,bold) i = 0 while True: @@ -362,6 +433,8 @@ def explore(filename=None): return +# ************************************************************************************************ +# ********** open and import IFC **************** def open(filename,skip=[],only=[],root=None): "opens an IFC file in a new document" @@ -838,7 +911,7 @@ def insert(filename,docname,skip=[],only=[],root=None): a = obj.IfcData a["IfcUID"] = str(guid) obj.IfcData = a - + # setting IFC attributes for attribute in ArchIFCSchema.IfcProducts[product.is_a()]["attributes"]: @@ -846,7 +919,7 @@ def insert(filename,docname,skip=[],only=[],root=None): if hasattr(product, attribute["name"]) and getattr(product, attribute["name"]) and hasattr(obj,attribute["name"]): #print("Setting attribute",attribute["name"],"to",getattr(product, attribute["name"])) setattr(obj, attribute["name"], getattr(product, attribute["name"])) - # TODO: ArchIFCSchema.IfcProducts uses the IFC version from the FreeCAD prefs. + # TODO: ArchIFCSchema.IfcProducts uses the IFC version from the FreeCAD prefs. # This might not coincide with the file being opened, hence some attributes are not properly read. if obj: @@ -1357,6 +1430,8 @@ def insert(filename,docname,skip=[],only=[],root=None): return doc +# ************************************************************************************************ +# ********** helper for import IFC ************** class recycler: "the compression engine - a mechanism to reuse ifc entities if needed" @@ -1546,6 +1621,9 @@ class recycler: self.psas[key] = c return c + +# ************************************************************************************************ +# ********** export IFC **************** def export(exportList,filename): "exports FreeCAD contents to an IFC file" @@ -1764,14 +1842,22 @@ def export(exportList,filename): # setting the arguments - kwargs = {"GlobalId": uid, "OwnerHistory": history, "Name": name, - "Description": description, "ObjectPlacement": placement, "Representation": representation} + kwargs = { + "GlobalId": uid, + "OwnerHistory": history, + "Name": name, + "Description": description, + "ObjectPlacement": placement, + "Representation": representation + } if ifctype == "IfcSite": - kwargs.update({"RefLatitude":dd2dms(obj.Latitude), - "RefLongitude":dd2dms(obj.Longitude), - "RefElevation":obj.Elevation.Value/1000.0, - "SiteAddress":buildAddress(obj,ifcfile), - "CompositionType": "ELEMENT"}) + kwargs.update({ + "RefLatitude":dd2dms(obj.Latitude), + "RefLongitude":dd2dms(obj.Longitude), + "RefElevation":obj.Elevation.Value/1000.0, + "SiteAddress":buildAddress(obj,ifcfile), + "CompositionType": "ELEMENT" + }) if schema == "IFC2X3": kwargs = exportIFC2X3Attributes(obj, kwargs) else: @@ -1794,9 +1880,26 @@ def export(exportList,filename): l = o.Label if six.PY2: l = l.encode("utf8") - prod2 = ifcfile.createIfcBuildingElementProxy(ifcopenshell.guid.compress(uuid.uuid1().hex),history,l,None,None,p2,r2,None,"ELEMENT") + prod2 = ifcfile.createIfcBuildingElementProxy( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + l, + None, + None, + p2, + r2, + None, + "ELEMENT" + ) subproducts[o.Name] = prod2 - ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'Addition','',product,[prod2]) + ifcfile.createIfcRelAggregates( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'Addition', + '', + product, + [prod2] + ) # subtractions @@ -1814,9 +1917,25 @@ def export(exportList,filename): l = o.Label if six.PY2: l = l.encode("utf8") - prod2 = ifcfile.createIfcOpeningElement(ifcopenshell.guid.compress(uuid.uuid1().hex),history,l,None,None,p2,r2,None) + prod2 = ifcfile.createIfcOpeningElement( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + l, + None, + None, + p2, + r2, + None + ) subproducts[o.Name] = prod2 - ifcfile.createIfcRelVoidsElement(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'Subtraction','',product,prod2) + ifcfile.createIfcRelVoidsElement( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'Subtraction', + '', + product, + prod2 + ) # properties @@ -1885,8 +2004,21 @@ def export(exportList,filename): p = ifcbin.createIfcPropertySingleValue(str(pname),str(ptype),pvalue) psets.setdefault(pset,[]).append(p) for pname,props in psets.items(): - pset = ifcfile.createIfcPropertySet(ifcopenshell.guid.compress(uuid.uuid1().hex),history,pname,None,props) - ifcfile.createIfcRelDefinesByProperties(ifcopenshell.guid.compress(uuid.uuid1().hex),history,None,None,[product],pset) + pset = ifcfile.createIfcPropertySet( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + pname, + None, + props + ) + ifcfile.createIfcRelDefinesByProperties( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + None, + None, + [product], + pset + ) elif obj.IfcProperties.TypeId == 'Spreadsheet::Sheet': @@ -1948,8 +2080,20 @@ def export(exportList,filename): else: print("Unable to create a property of type:",tp) if props: - 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) + 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 + ) if hasattr(obj,"IfcData"): @@ -1986,8 +2130,21 @@ def export(exportList,filename): val = float(val) props.append(ifcbin.createIfcPropertySingleValue(str(key),str(tp),val)) 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) + 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 + ) if not ifcprop: #if DEBUG : print("no ifc properties to export") @@ -2010,8 +2167,20 @@ def export(exportList,filename): if ("ExportVolume" in obj.IfcData) and obj.IfcData["ExportVolume"] and obj.isDerivedFrom("Part::Feature"): quantities.append(ifcfile.createIfcQuantityVolume('Volume',None,None,obj.Shape.Volume/1000000000.0)) if quantities: - eltq = ifcfile.createIfcElementQuantity(ifcopenshell.guid.compress(uuid.uuid1().hex),history,"ElementQuantities",None,"FreeCAD",quantities) - ifcfile.createIfcRelDefinesByProperties(ifcopenshell.guid.compress(uuid.uuid1().hex),history,None,None,[product],eltq) + eltq = ifcfile.createIfcElementQuantity( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + "ElementQuantities", + None, + "FreeCAD",quantities + ) + ifcfile.createIfcRelDefinesByProperties( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + None, + None, + [product],eltq + ) if FULL_PARAMETRIC: @@ -2030,7 +2199,13 @@ def export(exportList,filename): sets.append(("Gui",obj.ViewObject)) if hasattr(obj.ViewObject,"Proxy"): if obj.ViewObject.Proxy: - FreeCADGuiProps.append(ifcbin.createIfcPropertySingleValue("FreeCADGuiObject","IfcText",str(obj.ViewObject.Proxy.__class__))) + FreeCADGuiProps.append( + ifcbin.createIfcPropertySingleValue( + "FreeCADGuiObject", + "IfcText", + str(obj.ViewObject.Proxy.__class__) + ) + ) for realm,ctx in sets: if ctx: for prop in ctx.PropertiesList: @@ -2076,11 +2251,36 @@ def export(exportList,filename): else: FreeCADProps.append(ifcbin.createIfcPropertySingleValue("FreeCAD_"+prop,itype,ivalue)) if FreeCADProps: - pset = ifcfile.createIfcPropertySet(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'FreeCADPropertySet',None,FreeCADProps) - ifcfile.createIfcRelDefinesByProperties(ifcopenshell.guid.compress(uuid.uuid1().hex),history,None,None,[product],pset) + pset = ifcfile.createIfcPropertySet( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history,'FreeCADPropertySet', + None, + FreeCADProps + ) + ifcfile.createIfcRelDefinesByProperties( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + None, + None, + [product], + pset + ) if FreeCADGuiProps: - pset = ifcfile.createIfcPropertySet(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'FreeCADGuiPropertySet',None,FreeCADGuiProps) - ifcfile.createIfcRelDefinesByProperties(ifcopenshell.guid.compress(uuid.uuid1().hex),history,None,None,[product],pset) + pset = ifcfile.createIfcPropertySet( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'FreeCADGuiPropertySet', + None, + FreeCADGuiProps + ) + ifcfile.createIfcRelDefinesByProperties( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + None, + None, + [product], + pset + ) count += 1 @@ -2103,7 +2303,14 @@ def export(exportList,filename): subs.append(products[c.Name]) treated.append(c.Name) if subs: - ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'Assembly','',products[bp.Name],subs) + ifcfile.createIfcRelAggregates( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'Assembly', + '', + products[bp.Name], + subs + ) # floors/buildingparts @@ -2120,7 +2327,14 @@ def export(exportList,filename): treated.append(c.Name) f = products[floor.Name] if children: - ifcfile.createIfcRelContainedInSpatialStructure(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'StoreyLink','',children,f) + ifcfile.createIfcRelContainedInSpatialStructure( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'StoreyLink', + '', + children, + f + ) floors.append(f) defaulthost = f @@ -2144,9 +2358,23 @@ def export(exportList,filename): treated.append(c.Name) b = products[building.Name] if children: - ifcfile.createIfcRelContainedInSpatialStructure(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'BuildingLink','',children,b) + ifcfile.createIfcRelContainedInSpatialStructure( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'BuildingLink', + '', + children, + b + ) if childfloors: - ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'BuildingLink','',b,childfloors) + ifcfile.createIfcRelAggregates( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'BuildingLink', + '', + b, + childfloors + ) buildings.append(b) if not defaulthost and not ADDDEFAULTSTOREY: defaulthost = b @@ -2169,14 +2397,60 @@ def export(exportList,filename): if not sites: if DEBUG: print("No site found. Adding default site") - sites = [ifcfile.createIfcSite(ifcopenshell.guid.compress(uuid.uuid1().hex),history,"Default Site",'',None,None,None,None,"ELEMENT",None,None,None,None,None)] - ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'ProjectLink','',project,sites) + sites = [ifcfile.createIfcSite( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history,"Default Site", + '', + None, + None, + None, + None, + "ELEMENT", + None, + None, + None, + None, + None + )] + ifcfile.createIfcRelAggregates( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'ProjectLink', + '', + project,sites + ) if not buildings: if DEBUG: print("No building found. Adding default building") - buildings = [ifcfile.createIfcBuilding(ifcopenshell.guid.compress(uuid.uuid1().hex),history,"Default Building",'',None,None,None,None,"ELEMENT",None,None,None)] + buildings = [ifcfile.createIfcBuilding( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + "Default Building", + '', + None, + None, + None, + None, + "ELEMENT", + None, + None, + None + )] if floors: - ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'BuildingLink','',buildings[0],floors) - ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'SiteLink','',sites[0],buildings) + ifcfile.createIfcRelAggregates( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'BuildingLink', + '', + buildings[0],floors + ) + ifcfile.createIfcRelAggregates( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'SiteLink', + '', + sites[0], + buildings + ) untreated = [] for k,v in products.items(): if not(k in treated): @@ -2188,9 +2462,34 @@ def export(exportList,filename): untreated.append(v) if untreated: if not defaulthost: - defaulthost = ifcfile.createIfcBuildingStorey(ifcopenshell.guid.compress(uuid.uuid1().hex),history,"Default Storey",'',None,None,None,None,"ELEMENT",None) - ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'DefaultStoreyLink','',buildings[0],[defaulthost]) - ifcfile.createIfcRelContainedInSpatialStructure(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'UnassignedObjectsLink','',untreated,defaulthost) + defaulthost = ifcfile.createIfcBuildingStorey( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + "Default Storey", + '', + None, + None, + None, + None, + "ELEMENT", + None + ) + ifcfile.createIfcRelAggregates( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'DefaultStoreyLink', + '', + buildings[0], + [defaulthost] + ) + ifcfile.createIfcRelContainedInSpatialStructure( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'UnassignedObjectsLink', + '', + untreated, + defaulthost + ) # materials @@ -2228,7 +2527,14 @@ def export(exportList,filename): isi = ifcfile.createIfcStyledItem(None,[psa],None) isr = ifcfile.createIfcStyledRepresentation(context,"Style","Material",[isi]) imd = ifcfile.createIfcMaterialDefinitionRepresentation(None,None,[isr],mat) - ifcfile.createIfcRelAssociatesMaterial(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'MaterialLink','',relobjs,mat) + ifcfile.createIfcRelAssociatesMaterial( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'MaterialLink', + '', + relobjs, + mat + ) # 2D objects @@ -2301,7 +2607,14 @@ def export(exportList,filename): l = anno.Label if six.PY2: l = l.encode("utf8") - ann = ifcfile.createIfcAnnotation(ifcopenshell.guid.compress(uuid.uuid1().hex),history,l,'',None,gpl,rep) + ann = ifcfile.createIfcAnnotation( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history,l, + '', + None, + gpl, + rep + ) annos[anno.Name] = ann # groups @@ -2337,10 +2650,24 @@ def export(exportList,filename): name = FreeCAD.ActiveDocument.getObject(g[0]).Label if six.PY2: name = name.encode("utf8") - grp = ifcfile.createIfcGroup(ifcopenshell.guid.compress(uuid.uuid1().hex),history,name,'',None) + grp = ifcfile.createIfcGroup( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + name, + '', + None + ) products[g[0]] = grp spatialelements[g[0]] = grp - ass = ifcfile.createIfcRelAssignsToGroup(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'GroupLink','',children,None,grp) + ass = ifcfile.createIfcRelAssignsToGroup( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'GroupLink', + '', + children, + None, + grp + ) # stack groups inside containers @@ -2352,7 +2679,14 @@ def export(exportList,filename): if (parent.Name in spatialelements) and (g[0] in spatialelements): stack.setdefault(parent.Name,[]).append(spatialelements[g[0]]) for k,v in stack.items(): - ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'GroupStackLink','',spatialelements[k],v) + ifcfile.createIfcRelAggregates( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'GroupStackLink', + '', + spatialelements[k], + v + ) # add remaining 2D objects to default host @@ -2360,9 +2694,34 @@ def export(exportList,filename): remaining = [anno for anno in annos.values() if anno not in swallowed] if remaining: if not defaulthost: - defaulthost = ifcfile.createIfcBuildingStorey(ifcopenshell.guid.compress(uuid.uuid1().hex),history,"Default Storey",'',None,None,None,None,"ELEMENT",None) - ifcfile.createIfcRelAggregates(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'DefaultStoreyLink','',buildings[0],[defaulthost]) - ifcfile.createIfcRelContainedInSpatialStructure(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'AnnotationsLink','',remaining,defaulthost) + defaulthost = ifcfile.createIfcBuildingStorey( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + "Default Storey", + '', + None, + None, + None, + None, + "ELEMENT", + None + ) + ifcfile.createIfcRelAggregates( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'DefaultStoreyLink', + '', + buildings[0], + [defaulthost] + ) + ifcfile.createIfcRelContainedInSpatialStructure( + ifcopenshell.guid.compress(uuid.uuid1().hex), + history, + 'AnnotationsLink', + '', + remaining, + defaulthost + ) if DEBUG: print("writing ",filename,"...") @@ -2384,14 +2743,17 @@ def export(exportList,filename): del ifcbin +# ************************************************************************************************ +# ********** helper for export IFC ************** def isStandardCase(obj,ifctype): - + if ifctype.endswith("StandardCase"): return False # type is already standard case, return False so "StandardCase" is not added twice if hasattr(obj,"Proxy") and hasattr(obj.Proxy,"isStandardCase"): return obj.Proxy.isStandardCase(obj) return False + def getIfcTypeFromObj(obj): if (Draft.getType(obj) == "BuildingPart") and hasattr(obj,"IfcType") and (obj.IfcType == "Undefined"): @@ -2427,12 +2789,16 @@ def exportIFC2X3Attributes(obj, kwargs): internal = "INTERNAL" else: internal = "EXTERNAL" - kwargs.update({"CompositionType": "ELEMENT", + kwargs.update({ + "CompositionType": "ELEMENT", "InteriorOrExteriorSpace": internal, - "ElevationWithFlooring": obj.Shape.BoundBox.ZMin/1000.0}) + "ElevationWithFlooring": obj.Shape.BoundBox.ZMin/1000.0 + }) elif ifctype == "IfcReinforcingBar": - kwargs.update({"NominalDiameter": obj.Diameter.Value, - "BarLength": obj.Length.Value}) + kwargs.update({ + "NominalDiameter": obj.Diameter.Value, + "BarLength": obj.Length.Value + }) elif ifctype == "IfcBuildingStorey": kwargs.update({"Elevation": obj.Placement.Base.z/1000.0}) return kwargs @@ -2447,7 +2813,7 @@ def exportIfcAttributes(obj, kwargs): value = float(value) if property in ["ElevationWithFlooring","Elevation"]: value = value/1000 # some properties must be changed to meters - kwargs.update({ property: value }) + kwargs.update({property: value}) return kwargs @@ -2607,7 +2973,13 @@ def createCurve(ifcfile,wire): xvc = ifcbin.createIfcDirection(tuple(xaxis)) plc = ifcbin.createIfcAxis2Placement3D(ovc,zvc,xvc) cir = ifcfile.createIfcCircle(plc,e.Curve.Radius) - curve = ifcfile.createIfcTrimmedCurve(cir,[ifcfile.createIfcParameterValue(p1)],[ifcfile.createIfcParameterValue(p2)],follow,"PARAMETER") + curve = ifcfile.createIfcTrimmedCurve( + cir, + [ifcfile.createIfcParameterValue(p1)], + [ifcfile.createIfcParameterValue(p2)], + follow, + "PARAMETER" + ) else: verts = [vertex.Point for vertex in e.Vertexes] if last: @@ -2649,8 +3021,11 @@ def checkRectangle(edges): return False if len(edges) != 4: return False - angles = [round(getEdgesAngle(edges[0], edges[1])), round(getEdgesAngle(edges[0], edges[2])), - round(getEdgesAngle(edges[0], edges[3]))] + angles = [ + round(getEdgesAngle(edges[0], edges[1])), + round(getEdgesAngle(edges[0], edges[2])), + round(getEdgesAngle(edges[0], edges[3])) + ] if angles.count(90) == 2 and (angles.count(180) == 1 or angles.count(0) == 1): return True return False @@ -2660,7 +3035,8 @@ def getProfile(ifcfile,p): """returns an IFC profile definition from a shape""" - import Part,DraftGeomUtils + import Part + import DraftGeomUtils profile = None if len(p.Edges) == 1: pxvc = ifcbin.createIfcDirection((1.0,0.0)) @@ -2722,7 +3098,9 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess """returns an IfcShapeRepresentation object or None""" - import Part,math,DraftGeomUtils,DraftVecUtils + import Part + import DraftGeomUtils + import DraftVecUtils shapes = [] placement = None productdef = None @@ -2830,7 +3208,11 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess # check if we keep a null shape (additions-only object) - if (hasattr(obj,"Base") and hasattr(obj,"Width") and hasattr(obj,"Height")) and (not obj.Base) and obj.Additions and (not obj.Width.Value) and (not obj.Height.Value): + if (hasattr(obj,"Base") and hasattr(obj,"Width") and hasattr(obj,"Height")) \ + and (not obj.Base) \ + and obj.Additions \ + and (not obj.Width.Value) \ + and (not obj.Height.Value): shapes = None else: @@ -2845,8 +3227,8 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess fcshape = obj.Proxy.getSubVolume(obj) if not fcshape: if obj.isDerivedFrom("Part::Feature"): - if False: # below is buggy. No way to duplicate shapes that way? #if hasattr(obj,"Base") and hasattr(obj,"Additions")and hasattr(obj,"Subtractions"): + if False: # above is buggy. No way to duplicate shapes that way? if obj.Base and (not obj.Additions) and not(obj.Subtractions): if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape: @@ -3014,9 +3396,9 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess key = None rgbt = [obj.ViewObject.ShapeColor[:3]+(obj.ViewObject.Transparency/100.0,) for shape in shapes] if hasattr(obj.ViewObject,"DiffuseColor") \ - and obj.ViewObject.DiffuseColor \ - and (len(obj.ViewObject.DiffuseColor) == len(obj.Shape.Faces)) \ - and (len(obj.Shape.Solids) == len(shapes)): + and obj.ViewObject.DiffuseColor \ + and (len(obj.ViewObject.DiffuseColor) == len(obj.Shape.Faces)) \ + and (len(obj.Shape.Solids) == len(shapes)): i = 0 rgbt = [] for sol in obj.Shape.Solids: