def addProduct(self,elttype,shapes,storey=None,placement=None,name="Unnamed element",description=None,extra=None): """addProduct(elttype,representations,[storey,placement,name,description,extra]): creates an element of the given type (IfcWall, IfcBeam, etc...) with the given attributes, plus the given extra attributes.""" elttype = str(elttype) if not extra: extra = [] if not description: description = None if not placement: placement = self.addPlacement() representations = self.addRepresentations(shapes) prd = create(self._fileobject,"IfcProductDefinitionShape",[None,None,representations]) try: elt = create(self._fileobject,elttype,[uid(),self._owner,name,description,None,placement,prd,None]+extra) except: print "unable to create an ",elttype, " with attributes: ",[uid(),self._owner,str(name),description,None,placement,prd,None]+extra try: if hasattr(ifcw,"Entity"): o = ifcw.Entity(elttype) else: o = ifcw.entity_instance(elttype) print "supported attributes are: " print getPropertyNames(o) except: print "unable to create an element of type '"+elttype+"'" print "WARNING: skipping object '"+name+"' of type "+elttype return None self.BuildingProducts.append(elt) if not storey: if self.Storeys: storey = self.Storeys[0] else: storey = self.addStorey() self._relate(storey,elt) return elt
def __init__(self,filepath="",name="",owner="",organization="",application="Python IFC exporter",version="0.0"): if hasattr(ifcw,"IfcFile"): self._fileobject = ifcw.IfcFile() else: self._fileobject = ifcw.file() self._person = create(self._fileobject,"IfcPerson",[None,None,"",None,None,None,None,None]) self._org = create(self._fileobject,"IfcOrganization",[None,"",None,None,None]) pno = create(self._fileobject,"IfcPersonAndOrganization",[self._person,self._org,None]) app = create(self._fileobject,"IfcApplication",[self._org,version,application,uid()]) self._owner = create(self._fileobject,"IfcOwnerHistory",[pno,app,None,"ADDED",None,pno,app,now()]) axp = self.addPlacement(local=False) dim0 = create(self._fileobject,"IfcDirection",getTuple((0,1,0))) self._repcontext = create(self._fileobject,"IfcGeometricRepresentationContext",['Plan','Model',3,1.E-05,axp,dim0]) dim1 = create(self._fileobject,"IfcDimensionalExponents",[0,0,0,0,0,0,0]) dim2 = create(self._fileobject,"IfcSIUnit",[dim1,"LENGTHUNIT","MILLI","METRE"]) dim3 = create(self._fileobject,"IfcSIUnit",[dim1,"AREAUNIT",None,"SQUARE_METRE"]) dim4 = create(self._fileobject,"IfcSIUnit",[dim1,"VOLUMEUNIT",None,"CUBIC_METRE"]) dim6 = create(self._fileobject,"IfcSIUnit",[dim1,"PLANEANGLEUNIT",None,"RADIAN"]) dim7 = create(None,"IfcPlaneAngleMeasure",[1.745E-2]) dim8 = create(self._fileobject,"IfcMeasureWithUnit",[dim7,dim6]) dim9 = create(self._fileobject,"IfcConversionBasedUnit",[dim1,"PLANEANGLEUNIT","DEGREE",dim8]) units = create(self._fileobject,"IfcUnitAssignment",[[dim2,dim3,dim4,dim9]]) self.Project = create(self._fileobject,"IfcProject",[uid(),self._owner,None,None,None,None,None,[self._repcontext],units]) self.Site = None self._storeyRelations = {} self.BuildingProducts = [] self.Storeys = [] self.Buildings = [] self.FilePath = filepath self.Owner = owner self.Organization = organization self.Name = name
def readOpenShell(filename, useParser=False): "Parses an IFC file with IfcOpenShell" altifc = None if useParser: altifc = parseFile(filename) if getIfcOpenShell(): USESHAPES = False if hasattr(IfcImport, "USE_BREP_DATA"): IfcImport.Settings(IfcImport.USE_BREP_DATA, True) USESHAPES = True if IfcImport.Init(filename): while True: obj = IfcImport.Get() if DEBUG: print "parsing ", obj.id, ": ", obj.name, " of type ", obj.type meshdata = [] n = obj.name if not n: n = "Unnamed" if obj.type in SKIP: pass elif altifc and (obj.type == "IfcWallStandardCase"): if USESHAPES: makeWall(altifc.Entities[obj.id], shape=getShape(obj)) else: makeWall(altifc.Entities[obj.id]) elif USESHAPES: # treat as Parts sh = getShape(obj) nobj = FreeCAD.ActiveDocument.addObject("Part::Feature", n) nobj.Shape = sh else: # treat as meshes me, pl = getMesh(obj) nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature", n) nobj.Mesh = me nobj.Placement = pl if not IfcImport.Next(): break IfcImport.CleanUp() return None
def create(ifcdoc=None,ifcname=None,arguments=[]): """create(ifcdoc,ifcname,[arguments]):creates an entity of the given name in the given document and optionally gives it an ordered list of arguments""" entity = IfcImport.Entity(ifcname) if ifcdoc: ifcdoc.add(entity) # this is a temporary hack while ifcopenshell has no ref counting holder.refs.append(entity) if not isinstance(arguments,list): arguments = [arguments] for i in range(len(arguments)): arg = arguments[i] if isinstance(arg,tuple): if len(arg) in [2,3]: arg = IfcImport.Doubles(arg) entity.set_argument(i,arg) return entity
def getShape(obj,objid): "gets a shape from an IfcOpenShell object" #print "retrieving shape from obj ",objid import Part sh=Part.Shape() brep_data = None if IFCOPENSHELL5: try: brep_data = IfcImport.create_shape(obj) except: print "Unable to retrieve shape data" else: brep_data = obj.mesh.brep_data if brep_data: try: if MAKETEMPFILES: import tempfile tf = tempfile.mkstemp(suffix=".brp")[1] of = pyopen(tf,"wb") of.write(brep_data) of.close() sh = Part.read(tf) os.remove(tf) else: sh.importBrepFromString(brep_data) except: print "Error: malformed shape" return None else: if IFCOPENSHELL5 and ADDPLACEMENT: sh.Placement = getPlacement(getAttr(obj,"ObjectPlacement")) if not sh.Solids: # try to extract a solid shape if sh.Faces: try: if DEBUG: print "Malformed solid. Attempting to fix..." shell = Part.makeShell(sh.Faces) if shell: solid = Part.makeSolid(shell) if solid: sh = solid except: if DEBUG: print "failed to retrieve solid from object ",objid else: if DEBUG: print "object ", objid, " doesn't contain any geometry" if not IFCOPENSHELL5: m = obj.matrix mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9], m[1], m[4], m[7], m[10], m[2], m[5], m[8], m[11], 0, 0, 0, 1) sh.Placement = FreeCAD.Placement(mat) # if DEBUG: print "getting Shape from ",obj #print "getting shape: ",sh,sh.Solids,sh.Volume,sh.isValid(),sh.isNull() #for v in sh.Vertexes: print v.Point return sh
def getShape(obj,objid): "gets a shape from an IfcOpenShell object" #print "retrieving shape from obj ",objid import Part sh=Part.Shape() brep_data = None if IOC_ADVANCED: try: brep_data = IfcImport.create_shape(obj) except: print "Unable to retrieve shape data" else: brep_data = obj.mesh.brep_data if brep_data: try: if MAKETEMPFILES: import tempfile tf = tempfile.mkstemp(suffix=".brp")[1] of = pyopen(tf,"wb") of.write(brep_data) of.close() sh = Part.read(tf) os.remove(tf) else: sh.importBrepFromString(brep_data) except: print "Error: malformed shape" return None if not sh.Solids: # try to extract a solid shape if sh.Faces: try: if DEBUG: print "Malformed solid. Attempting to fix..." shell = Part.makeShell(sh.Faces) if shell: solid = Part.makeSolid(shell) if solid: sh = solid except: if DEBUG: print "failed to retrieve solid from object ",objid else: if DEBUG: print "object ", objid, " doesn't contain any geometry" if not IOC_ADVANCED: m = obj.matrix mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9], m[1], m[4], m[7], m[10], m[2], m[5], m[8], m[11], 0, 0, 0, 1) sh.Placement = FreeCAD.Placement(mat) # if DEBUG: print "getting Shape from ",obj #print "getting shape: ",sh,sh.Solids,sh.Volume,sh.isValid(),sh.isNull() #for v in sh.Vertexes: print v.Point return sh
def create(ifcdoc=None,ifcname=None,arguments=[]): """create(ifcdoc,ifcname,[arguments]):creates an entity of the given name in the given document and optionally gives it an ordered list of arguments""" if hasattr(ifcw,"Entity"): entity = ifcw.Entity(ifcname) else: entity = ifcw.entity_instance(ifcname) if ifcdoc: ifcdoc.add(entity) # this is a temporary hack while ifcopenshell has no ref counting holder.refs.append(entity) if not isinstance(arguments,list): arguments = [arguments] for i in range(len(arguments)): arg = arguments[i] if isinstance(arg,tuple): if len(arg) in [2,3]: if hasattr(ifcw,"Doubles"): arg = ifcw.Doubles(arg) else: arg = ifcw.doubles(arg) entity.set_argument(i,arg) return entity
def new(): """new(): returns a new empty ifc file holder""" fil = IfcImport.IfcFile() return fil
def read(filename): "Parses an IFC file" # parsing the IFC file t1 = time.time() num_lines = sum(1 for line in pyopen(filename)) if getIfcOpenShell() and not FORCE_PYTHON_PARSER: # use the IfcOpenShell parser # preparing IfcOpenShell if DEBUG: global ifcObjects, ifcParents ifcObjects = {} # a table to relate ifc id with freecad object ifcParents = {} # a table to relate ifc id with parent id if hasattr(IfcImport, "DISABLE_OPENING_SUBTRACTIONS") and SEPARATE_OPENINGS: IfcImport.Settings(IfcImport.DISABLE_OPENING_SUBTRACTIONS, True) else: SKIP.append("IfcOpeningElement") useShapes = False if hasattr(IfcImport, "USE_BREP_DATA"): IfcImport.Settings(IfcImport.USE_BREP_DATA, True) useShapes = True else: if DEBUG: print "Warning: IfcOpenShell version very old, unable to handle Brep data" # processing geometry if IfcImport.Init(filename): while True: obj = IfcImport.Get() if DEBUG: print "[" + str( int((float(obj.id) / num_lines) * 100) ) + "%] parsing ", obj.id, ": ", obj.name, " of type ", obj.type # retrieving name n = getName(obj) # skip types if obj.type in SKIP: if DEBUG: print "skipping because type is in skip list" nobj = None else: # build shape shape = None if useShapes: shape = getShape(obj) # walls if obj.type in ["IfcWallStandardCase", "IfcWall"]: nobj = makeWall(obj.id, shape, n) # windows elif obj.type in ["IfcWindow", "IfcDoor"]: nobj = makeWindow(obj.id, shape, n) # structs elif obj.type in [ "IfcBeam", "IfcColumn", "IfcSlab", "IfcFooting" ]: nobj = makeStructure(obj.id, shape, n) # roofs elif obj.type in ["IfcRoof"]: nobj = makeRoof(obj.id, shape, n) # furniture elif obj.type in ["IfcFurnishingElement"]: nobj = FreeCAD.ActiveDocument.addObject( "Part::Feature", n) nobj.Shape = shape # sites elif obj.type in ["IfcSite"]: nobj = makeSite(obj.id, shape, n) # spaces elif obj.type in ["IfcSpace"]: nobj = makeSpace(obj.id, shape, n) elif shape: # treat as dumb parts #if DEBUG: print "Fixme: Shape-containing object not handled: ",obj.id, " ", obj.type nobj = FreeCAD.ActiveDocument.addObject( "Part::Feature", n) nobj.Shape = shape else: # treat as meshes if DEBUG: print "Warning: Object without shape: ", obj.id, " ", obj.type me, pl = getMesh(obj) nobj = FreeCAD.ActiveDocument.addObject( "Mesh::Feature", n) nobj.Mesh = me nobj.Placement = pl # registering object number and parent if obj.parent_id > 0: ifcParents[obj.id] = [ obj.parent_id, not (obj.type in subtractiveTypes) ] ifcObjects[obj.id] = nobj if not IfcImport.Next(): break # processing non-geometry and relationships parents_temp = dict(ifcParents) import ArchCommands while parents_temp: id, c = parents_temp.popitem() parent_id = c[0] additive = c[1] if (id <= 0) or (parent_id <= 0): # root dummy object parent = None elif parent_id in ifcObjects: parent = ifcObjects[parent_id] # check if parent is a subtraction, if yes parent to grandparent if parent_id in ifcParents: if ifcParents[parent_id][1] == False: grandparent_id = ifcParents[parent_id][0] if grandparent_id in ifcObjects: parent = ifcObjects[grandparent_id] else: # creating parent if needed parent_ifcobj = IfcImport.GetObject(parent_id) if DEBUG: print "[" + str( int((float(parent_ifcobj.id) / num_lines) * 100) ) + "%] parsing ", parent_ifcobj.id, ": ", parent_ifcobj.name, " of type ", parent_ifcobj.type n = getName(parent_ifcobj) if parent_ifcobj.id <= 0: parent = None elif parent_ifcobj.type == "IfcBuildingStorey": parent = Arch.makeFloor(name=n) elif parent_ifcobj.type == "IfcBuilding": parent = Arch.makeBuilding(name=n) elif parent_ifcobj.type == "IfcSite": parent = Arch.makeSite(name=n) elif parent_ifcobj.type == "IfcWindow": parent = Arch.makeWindow(name=n) else: if DEBUG: print "Fixme: skipping unhandled parent: ", parent_ifcobj.id, " ", parent_ifcobj.type parent = None # registering object number and parent if parent_ifcobj.parent_id > 0: ifcParents[parent_ifcobj.id] = [ parent_ifcobj.parent_id, True ] parents_temp[parent_ifcobj.id] = [ parent_ifcobj.parent_id, True ] if parent and (not parent_ifcobj.id in ifcObjects): ifcObjects[parent_ifcobj.id] = parent # attributing parent if parent and (id in ifcObjects): if ifcObjects[id]: if additive: ArchCommands.addComponents(ifcObjects[id], parent) else: ArchCommands.removeComponents(ifcObjects[id], parent) IfcImport.CleanUp() else: # use only the internal python parser FreeCAD.Console.PrintWarning( str( translate( "Arch", "IfcOpenShell not found, falling back on internal parser.\n" ))) schema = getSchema() if schema: if DEBUG: global ifc if DEBUG: print "opening", filename, "..." ifc = ifcReader.IfcDocument(filename, schema=schema, debug=DEBUG) else: FreeCAD.Console.PrintWarning( str( translate("Arch", "IFC Schema not found, IFC import disabled.\n"))) return None t2 = time.time() if DEBUG: print "Successfully loaded", ifc, "in %s s" % ((t2 - t1)) # getting walls for w in ifc.getEnt("IfcWallStandardCase"): nobj = makeWall(w) # getting windows and doors for w in (ifc.getEnt("IfcWindow") + ifc.getEnt("IfcDoor")): nobj = makeWindow(w) # getting structs for w in (ifc.getEnt("IfcSlab") + ifc.getEnt("IfcBeam") + ifc.getEnt("IfcColumn") \ + ifc.getEnt("IfcFooting")): nobj = makeStructure(w) # getting floors for f in ifc.getEnt("IfcBuildingStorey"): group(f, ifc, "Floor") # getting buildings for b in ifc.getEnt("IfcBuilding"): group(b, ifc, "Building") # getting sites for s in ifc.getEnt("IfcSite"): group(s, ifc, "Site") if DEBUG: print "done parsing. Recomputing..." FreeCAD.ActiveDocument.recompute() t3 = time.time() if DEBUG: print "done processing IFC file in %s s" % ((t3 - t1)) return None
def read(filename): "Parses an IFC file" # parsing the IFC file t1 = time.time() schema = getSchema() if schema: if DEBUG: global ifc if DEBUG: print "opening", filename, "..." ifc = ifcReader.IfcDocument(filename, schema=schema, debug=DEBUG) else: FreeCAD.Console.PrintWarning( str( translate("Arch", "IFC Schema not found, IFC import disabled.\n"))) return None t2 = time.time() if DEBUG: print "Successfully loaded", ifc, "in %s s" % ((t2 - t1)) if useIfcOpenShell and getIfcOpenShell(): # use the IfcOpenShell parser useShapes = False if hasattr(IfcImport, "USE_BREP_DATA"): IfcImport.Settings(IfcImport.USE_BREP_DATA, True) useShapes = True if IfcImport.Init(filename): while True: obj = IfcImport.Get() if DEBUG: print "parsing ", obj.id, ": ", obj.name, " of type ", obj.type meshdata = [] # retrieving name n = obj.name if not n: n = "Unnamed" # build shape shape = None if useShapes: shape = getShape(obj) # skip types if obj.type in SKIP: pass # walls elif obj.type == "IfcWallStandardCase": makeWall(ifc.Entities[obj.id], shape) # windows elif obj.type in ["IfcWindow", "IfcDoor"]: makeWindow(ifc.Entities[obj.id], shape) # structs elif obj.type in ["IfcBeam", "IfcColumn", "IfcSlab"]: makeStructure(ifc.Entities[obj.id], shape) # furniture elif obj.type == "IfcFurnishingElement": nobj = FreeCAD.ActiveDocument.addObject( "Part::Feature", "Furniture") nobj.Shape = shape elif shape: # treat as dumb parts nobj = FreeCAD.ActiveDocument.addObject("Part::Feature", n) nobj.Shape = shape else: # treat as meshes me, pl = getMesh(obj) nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature", n) nobj.Mesh = me nobj.Placement = pl if not IfcImport.Next(): break IfcImport.CleanUp() else: # use only the internal python parser # getting walls for w in ifc.getEnt("IfcWallStandardCase"): makeWall(w) # getting windows and doors for w in (ifc.getEnt("IfcWindow") + ifc.getEnt("IfcDoor")): makeWindow(w) # getting structs for w in (ifc.getEnt("IfcSlab") + ifc.getEnt("IfcBeam") + ifc.getEnt("IfcColumn")): makeStructure(w) order(ifc) FreeCAD.ActiveDocument.recompute() t3 = time.time() if DEBUG: print "done processing", ifc, "in %s s" % ((t3 - t1)) return None
def read(filename): "Parses an IFC file" # parsing the IFC file t1 = time.time() processedIds = [] if getIfcOpenShell() and not FORCE_PYTHON_PARSER: # use the IfcOpenShell parser # check for IFcOpenShellVersion global IOC_ADVANCED if hasattr(IfcImport,"IfcFile"): IOC_ADVANCED = True else: IOC_ADVANCED = False # preparing IfcOpenShell if DEBUG: global ifcObjects,ifcParents ifcObjects = {} # a table to relate ifc id with freecad object ifcParents = {} # a table to relate ifc id with parent id if SEPARATE_OPENINGS: if hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS"): IfcImport.Settings(IfcImport.DISABLE_OPENING_SUBTRACTIONS,True) else: SKIP.append("IfcOpeningElement") useShapes = False if IOC_ADVANCED: useShapes = True elif hasattr(IfcImport,"USE_BREP_DATA"): IfcImport.Settings(IfcImport.USE_BREP_DATA,True) useShapes = True else: if DEBUG: print "Warning: IfcOpenShell version very old, unable to handle Brep data" # opening file if IOC_ADVANCED: global ifc ifc = IfcImport.open(filename) objects = ifc.by_type("IfcProduct") num_lines = len(objects) relations = ifc.by_type("IfcRelAggregates") + ifc.by_type("IfcRelContainedInSpatialStructure") + ifc.by_type("IfcRelVoidsElement") if not objects: print "Error opening IFC file" return else: num_lines = sum(1 for line in pyopen(filename)) if not IfcImport.Init(filename): print "Error opening IFC file" return # processing geometry idx = 0 while True: if IOC_ADVANCED: obj = objects[idx] idx += 1 objid = int(str(obj).split("=")[0].strip("#")) objname = obj.get_argument(obj.get_argument_index("Name")) objtype = str(obj).split("=")[1].split("(")[0] objparentid = -1 for r in relations: if r.is_a("IfcRelAggregates"): for c in getAttr(r,"RelatedObjects"): if str(obj) == str(c): objparentid = int(str(getAttr(r,"RelatingObject")).split("=")[0].strip("#")) elif r.is_a("IfcRelContainedInSpatialStructure"): for c in getAttr(r,"RelatedElements"): if str(obj) == str(c): objparentid = int(str(getAttr(r,"RelatingStructure")).split("=")[0].strip("#")) elif r.is_a("IfcRelVoidsElement"): if str(obj) == str(getAttr(r,"RelatedOpeningElement")): objparentid = int(str(getAttr(r,"RelatingBuildingElement")).split("=")[0].strip("#")) else: if hasattr(IfcImport, 'GetBrepData'): obj = IfcImport.GetBrepData() else: obj = IfcImport.Get() objid = obj.id idx = objid objname = obj.name objtype = obj.type objparentid = obj.parent_id if DEBUG: print "["+str(int((float(idx)/num_lines)*100))+"%] parsing ",objid,": ",objname," of type ",objtype # retrieving name n = getCleanName(objname,objid,objtype) # skip types if objtype in SKIP: if DEBUG: print "skipping because type is in skip list" nobj = None # check if object was already processed, to workaround an ifcopenshell bug elif objid in processedIds: if DEBUG: print "skipping because this object was already processed" else: # build shape shape = None if useShapes: shape = getShape(obj,objid) # walls if objtype in ["IfcWallStandardCase","IfcWall"]: nobj = makeWall(objid,shape,n) # windows elif objtype in ["IfcWindow","IfcDoor"]: nobj = makeWindow(objid,shape,n) # structs elif objtype in ["IfcBeam","IfcColumn","IfcSlab","IfcFooting"]: nobj = makeStructure(objid,shape,objtype,n) # roofs elif objtype in ["IfcRoof"]: nobj = makeRoof(objid,shape,n) # furniture elif objtype in ["IfcFurnishingElement"]: nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj.Shape = shape # sites elif objtype in ["IfcSite"]: nobj = makeSite(objid,shape,n) # floors elif objtype in ["IfcBuildingStorey"]: nobj = Arch.makeFloor(name=n) nobj.Label = n # floors elif objtype in ["IfcBuilding"]: nobj = Arch.makeBuilding(name=n) nobj.Label = n # spaces elif objtype in ["IfcSpace"]: nobj = makeSpace(objid,shape,n) elif shape: # treat as dumb parts #if DEBUG: print "Fixme: Shape-containing object not handled: ",obj.id, " ", obj.type nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj.Label = n nobj.Shape = shape else: # treat as meshes if DEBUG: print "Warning: Object without shape: ",objid, " ", objtype if hasattr(obj,"mesh"): if not hasattr(obj.mesh, 'verts'): obj = IfcImport.Get() # Get triangulated rep of same product me,pl = getMesh(obj) nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n) nobj.Label = n nobj.Mesh = me nobj.Placement = pl else: if DEBUG: print "Error: Skipping object without mesh: ",objid, " ", objtype # registering object number and parent if objparentid > 0: ifcParents[objid] = [objparentid,not (objtype in subtractiveTypes)] ifcObjects[objid] = nobj processedIds.append(objid) if IOC_ADVANCED: if idx >= len(objects): break else: if not IfcImport.Next(): break # processing non-geometry and relationships parents_temp = dict(ifcParents) import ArchCommands #print parents_temp while parents_temp: id, c = parents_temp.popitem() parent_id = c[0] additive = c[1] if (id <= 0) or (parent_id <= 0): # root dummy object parent = None elif parent_id in ifcObjects: parent = ifcObjects[parent_id] # check if parent is a subtraction, if yes parent to grandparent if parent_id in ifcParents: if ifcParents[parent_id][1] == False: grandparent_id = ifcParents[parent_id][0] if grandparent_id in ifcObjects: parent = ifcObjects[grandparent_id] else: # creating parent if needed if IOC_ADVANCED: parent_ifcobj = ifc.by_id(parent_id) parentid = int(str(obj).split("=")[0].strip("#")) parentname = obj.get_argument(obj.get_argument_index("Name")) parenttype = str(obj).split("=")[1].split("(")[0] else: parent_ifcobj = IfcImport.GetObject(parent_id) parentid = obj.id parentname = obj.name parenttype = obj.type #if DEBUG: print "["+str(int((float(idx)/num_lines)*100))+"%] parsing ",parentid,": ",parentname," of type ",parenttype n = getCleanName(parentname,parentid,parenttype) if parentid <= 0: parent = None elif parenttype == "IfcBuildingStorey": parent = Arch.makeFloor(name=n) parent.Label = n elif parenttype == "IfcBuilding": parent = Arch.makeBuilding(name=n) parent.Label = n elif parenttype == "IfcSite": parent = Arch.makeSite(name=n) parent.Label = n elif parenttype == "IfcWindow": parent = Arch.makeWindow(name=n) parent.Label = n else: if DEBUG: print "Fixme: skipping unhandled parent: ", parentid, " ", parenttype parent = None # registering object number and parent if not IOC_ADVANCED: if parent_ifcobj.parent_id > 0: ifcParents[parentid] = [parent_ifcobj.parent_id,True] parents_temp[parentid] = [parent_ifcobj.parent_id,True] if parent and (not parentid in ifcObjects): ifcObjects[parentid] = parent # attributing parent if parent and (id in ifcObjects): if ifcObjects[id] and (ifcObjects[id].Name != parent.Name): if additive: if DEBUG: print "adding ",ifcObjects[id].Name, " to ",parent.Name ArchCommands.addComponents(ifcObjects[id],parent) else: if DEBUG: print "removing ",ifcObjects[id].Name, " from ",parent.Name ArchCommands.removeComponents(ifcObjects[id],parent) if not IOC_ADVANCED: IfcImport.CleanUp() else: # use only the internal python parser FreeCAD.Console.PrintWarning(translate("Arch","IfcOpenShell not found or disabled, falling back on internal parser.\n")) schema=getSchema() if schema: if DEBUG: print "opening",filename,"..." ifc = ifcReader.IfcDocument(filename,schema=schema,debug=DEBUG) else: FreeCAD.Console.PrintWarning(translate("Arch","IFC Schema not found, IFC import disabled.\n")) return None t2 = time.time() if DEBUG: print "Successfully loaded",ifc,"in %s s" % ((t2-t1)) # getting walls for w in ifc.getEnt("IfcWallStandardCase"): nobj = makeWall(w) # getting windows and doors for w in (ifc.getEnt("IfcWindow") + ifc.getEnt("IfcDoor")): nobj = makeWindow(w) # getting structs for w in (ifc.getEnt("IfcSlab") + ifc.getEnt("IfcBeam") + ifc.getEnt("IfcColumn") \ + ifc.getEnt("IfcFooting")): nobj = makeStructure(w) # getting floors for f in ifc.getEnt("IfcBuildingStorey"): group(f,ifc,"Floor") # getting buildings for b in ifc.getEnt("IfcBuilding"): group(b,ifc,"Building") # getting sites for s in ifc.getEnt("IfcSite"): group(s,ifc,"Site") if DEBUG: print "done parsing. Recomputing..." FreeCAD.ActiveDocument.recompute() t3 = time.time() if DEBUG: print "done processing IFC file in %s s" % ((t3-t1)) return None
def getShape(obj,objid): "gets a shape from an IfcOpenShell object" #print "retrieving shape from obj ",objid import Part sh=Part.Shape() brep_data = None if IFCOPENSHELL5: try: if SEPARATE_OPENINGS and hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS"): if SEPARATE_PLACEMENTS and hasattr(IfcImport,"DISABLE_OBJECT_PLACEMENT"): brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OPENING_SUBTRACTIONS | IfcImport.DISABLE_OBJECT_PLACEMENT) else: brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OPENING_SUBTRACTIONS) else: if SEPARATE_PLACEMENTS and hasattr(IfcImport,"DISABLE_OBJECT_PLACEMENT"): brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OBJECT_PLACEMENT) else: brep_data = IfcImport.create_shape(obj) except: print "Unable to retrieve shape data" else: brep_data = obj.mesh.brep_data if brep_data: try: if MAKETEMPFILES: import tempfile tf = tempfile.mkstemp(suffix=".brp")[1] of = pyopen(tf,"wb") of.write(brep_data) of.close() sh = Part.read(tf) os.remove(tf) else: sh.importBrepFromString(brep_data) except: print " error: malformed shape" return None else: if IFCOPENSHELL5 and SEPARATE_PLACEMENTS: p = getPlacement(getAttr(obj,"ObjectPlacement")) if p: sh.Placement = p if not sh.Solids: # try to extract a solid shape if sh.Faces: try: if DEBUG: print " malformed solid. Attempting to fix..." shell = Part.makeShell(sh.Faces) if shell: solid = Part.makeSolid(shell) if solid: sh = solid except: if DEBUG: print " failed to retrieve solid from object ",objid else: if DEBUG: print " object ", objid, " doesn't contain any geometry" if not IFCOPENSHELL5: m = obj.matrix mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9], m[1], m[4], m[7], m[10], m[2], m[5], m[8], m[11], 0, 0, 0, 1) sh.Placement = FreeCAD.Placement(mat) # if DEBUG: print "getting Shape from ",obj #print "getting shape: ",sh,sh.Solids,sh.Volume,sh.isValid(),sh.isNull() #for v in sh.Vertexes: print v.Point return sh
def read(filename,skip=None): "Parses an IFC file" # parsing the IFC file t1 = time.time() processedIds = [] skipIds = skip if not skipIds: skipIds = [] elif isinstance(skipIds,int): skipIds = [skipIds] if getIfcOpenShell() and not FORCE_PYTHON_PARSER: # use the IfcOpenShell parser # check for IFcOpenShellVersion global IFCOPENSHELL5 if hasattr(IfcImport,"IfcFile"): IFCOPENSHELL5 = True else: IFCOPENSHELL5 = False # preparing IfcOpenShell if DEBUG: global ifcObjects,ifcParents ifcObjects = {} # a table to relate ifc id with freecad object ifcParents = {} # a table to relate ifc id with parent id if SEPARATE_OPENINGS: if not IFCOPENSHELL5: if hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS"): IfcImport.Settings(IfcImport.DISABLE_OPENING_SUBTRACTIONS,True) else: SKIP.append("IfcOpeningElement") useShapes = False if IFCOPENSHELL5: useShapes = True if hasattr(IfcImport,"clean"): IfcImport.clean() elif hasattr(IfcImport,"USE_BREP_DATA"): IfcImport.Settings(IfcImport.USE_BREP_DATA,True) useShapes = True else: if DEBUG: print "Warning: IfcOpenShell version very old, unable to handle Brep data" # opening file if IFCOPENSHELL5: global ifc ifc = IfcImport.open(filename) objects = ifc.by_type("IfcProduct") num_lines = len(objects) relations = ifc.by_type("IfcRelAggregates") + ifc.by_type("IfcRelContainedInSpatialStructure") + ifc.by_type("IfcRelVoidsElement") if not objects: print "Error opening IFC file" return else: num_lines = sum(1 for line in pyopen(filename)) if not IfcImport.Init(filename): print "Error opening IFC file" return # processing geometry idx = 0 while True: objparentid = [] if IFCOPENSHELL5: obj = objects[idx] idx += 1 objid = int(str(obj).split("=")[0].strip("#")) objname = obj.get_argument(obj.get_argument_index("Name")) objtype = str(obj).split("=")[1].split("(")[0] for r in relations: if r.is_a("IfcRelAggregates"): for c in getAttr(r,"RelatedObjects"): if str(obj) == str(c): objparentid.append(int(str(getAttr(r,"RelatingObject")).split("=")[0].strip("#"))) elif r.is_a("IfcRelContainedInSpatialStructure"): for c in getAttr(r,"RelatedElements"): if str(obj) == str(c): objparentid.append(int(str(getAttr(r,"RelatingStructure")).split("=")[0].strip("#"))) elif r.is_a("IfcRelVoidsElement"): if str(obj) == str(getAttr(r,"RelatedOpeningElement")): objparentid.append(int(str(getAttr(r,"RelatingBuildingElement")).split("=")[0].strip("#"))) else: if hasattr(IfcImport, 'GetBrepData'): obj = IfcImport.GetBrepData() else: obj = IfcImport.Get() objid = obj.id idx = objid objname = obj.name objtype = obj.type objparentid.append(obj.parent_id) if DEBUG: print "["+str(int((float(idx)/num_lines)*100))+"%] parsing ",objid,": ",objname," of type ",objtype # retrieving name n = getCleanName(objname,objid,objtype) # skip IDs if objid in skipIds: if DEBUG: print " skipping because object ID is in skip list" nobj = None # skip types elif objtype in SKIP: if DEBUG: print " skipping because type is in skip list" nobj = None # check if object was already processed, to workaround an ifcopenshell bug elif objid in processedIds: if DEBUG: print " skipping because this object was already processed" else: # build shape shape = None if useShapes: shape = getShape(obj,objid) # walls if objtype in ["IfcWallStandardCase","IfcWall"]: nobj = makeWall(objid,shape,n) # windows elif objtype in ["IfcWindow","IfcDoor"]: nobj = makeWindow(objid,shape,n) # structs elif objtype in ["IfcBeam","IfcColumn","IfcSlab","IfcFooting"]: nobj = makeStructure(objid,shape,objtype,n) # roofs elif objtype in ["IfcRoof"]: nobj = makeRoof(objid,shape,n) # furniture elif objtype in ["IfcFurnishingElement"]: nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj.Shape = shape # sites elif objtype in ["IfcSite"]: nobj = makeSite(objid,shape,n) # floors elif objtype in ["IfcBuildingStorey"]: nobj = Arch.makeFloor(name=n) nobj.Label = n # floors elif objtype in ["IfcBuilding"]: nobj = Arch.makeBuilding(name=n) nobj.Label = n # spaces elif objtype in ["IfcSpace"]: nobj = makeSpace(objid,shape,n) elif shape: # treat as dumb parts if DEBUG: print "Fixme: Shape-containing object not handled: ",objid, " ", objtype nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj.Label = n nobj.Shape = shape else: # treat as meshes if DEBUG: print "Warning: Object without shape: ",objid, " ", objtype if hasattr(obj,"mesh"): if not hasattr(obj.mesh, 'verts'): obj = IfcImport.Get() # Get triangulated rep of same product me,pl = getMesh(obj) nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n) nobj.Label = n nobj.Mesh = me nobj.Placement = pl else: if DEBUG: print "Error: Skipping object without mesh: ",objid, " ", objtype # registering object number and parent if objparentid: ifcParents[objid] = [] for p in objparentid: ifcParents[objid].append([p,not (objtype in subtractiveTypes)]) ifcObjects[objid] = nobj processedIds.append(objid) if IFCOPENSHELL5: if idx >= len(objects): break else: if not IfcImport.Next(): break # processing non-geometry and relationships parents_temp = dict(ifcParents) import ArchCommands #print parents_temp while parents_temp: id, comps = parents_temp.popitem() for c in comps: parent_id = c[0] additive = c[1] if (id <= 0) or (parent_id <= 0): # root dummy object parent = None elif parent_id in ifcObjects: parent = ifcObjects[parent_id] # check if parent is a subtraction, if yes parent to grandparent if parent_id in ifcParents: for p in ifcParents[parent_id]: if p[1] == False: grandparent_id = p[0] if grandparent_id in ifcObjects: parent = ifcObjects[grandparent_id] else: # creating parent if needed if IFCOPENSHELL5: obj = ifc.by_id(parent_id) parentid = int(str(obj).split("=")[0].strip("#")) parentname = obj.get_argument(obj.get_argument_index("Name")) parenttype = str(obj).split("=")[1].split("(")[0] else: obj = IfcImport.GetObject(parent_id) parentid = obj.id parentname = obj.name parenttype = obj.type #if DEBUG: print "["+str(int((float(idx)/num_lines)*100))+"%] parsing ",parentid,": ",parentname," of type ",parenttype n = getCleanName(parentname,parentid,parenttype) if parentid <= 0: parent = None elif parenttype == "IfcBuildingStorey": parent = Arch.makeFloor(name=n) parent.Label = n elif parenttype == "IfcBuilding": parent = Arch.makeBuilding(name=n) parent.Label = n elif parenttype == "IfcSite": parent = Arch.makeSite(name=n) parent.Label = n elif parenttype == "IfcWindow": parent = Arch.makeWindow(name=n) parent.Label = n elif parenttype == "IfcProject": parent = None else: if DEBUG: print "Fixme: skipping unhandled parent: ", parentid, " ", parenttype parent = None # registering object number and parent if not IFCOPENSHELL5: if parent_ifcobj.parent_id > 0: ifcParents[parentid] = [parent_ifcobj.parent_id,True] parents_temp[parentid] = [parent_ifcobj.parent_id,True] if parent and (not parentid in ifcObjects): ifcObjects[parentid] = parent # attributing parent if parent and (id in ifcObjects): if ifcObjects[id] and (ifcObjects[id].Name != parent.Name): if additive: if DEBUG: print "adding ",ifcObjects[id].Name, " to ",parent.Name ArchCommands.addComponents(ifcObjects[id],parent) else: if DEBUG: print "removing ",ifcObjects[id].Name, " from ",parent.Name ArchCommands.removeComponents(ifcObjects[id],parent) if not IFCOPENSHELL5: IfcImport.CleanUp() else: # use only the internal python parser FreeCAD.Console.PrintWarning(translate("Arch","IfcOpenShell not found or disabled, falling back on internal parser.\n")) schema=getSchema() if schema: if DEBUG: print "opening",filename,"..." ifcReader.DEBUG = DEBUG ifc = ifcReader.IfcDocument(filename,schema=schema) else: FreeCAD.Console.PrintWarning(translate("Arch","IFC Schema not found, IFC import disabled.\n")) return None t2 = time.time() if DEBUG: print "Successfully loaded",ifc,"in %s s" % ((t2-t1)) # getting walls for w in ifc.getEnt("IfcWallStandardCase"): nobj = makeWall(w) # getting windows and doors for w in (ifc.getEnt("IfcWindow") + ifc.getEnt("IfcDoor")): nobj = makeWindow(w) # getting structs for w in (ifc.getEnt("IfcSlab") + ifc.getEnt("IfcBeam") + ifc.getEnt("IfcColumn") \ + ifc.getEnt("IfcFooting")): nobj = makeStructure(w) # getting floors for f in ifc.getEnt("IfcBuildingStorey"): group(f,ifc,"Floor") # getting buildings for b in ifc.getEnt("IfcBuilding"): group(b,ifc,"Building") # getting sites for s in ifc.getEnt("IfcSite"): group(s,ifc,"Site") if DEBUG: print "done parsing. Recomputing..." FreeCAD.ActiveDocument.recompute() t3 = time.time() if DEBUG: print "done processing IFC file in %s s" % ((t3-t1)) return None