Arch: Better sticking to standards in IFC import/export

This commit is contained in:
Yorik van Havre 2014-04-21 23:06:44 -03:00
parent 8609337d6f
commit cd7c1f2307
3 changed files with 60 additions and 44 deletions

View File

@ -602,7 +602,7 @@ def addFixture(fixture,baseobject):
else: else:
FreeCAD.Console.PrintMessage(translate("Arch","This object has no support for fixtures")) FreeCAD.Console.PrintMessage(translate("Arch","This object has no support for fixtures"))
def getTuples(data,scale=1,placement=None,normal=None): def getTuples(data,scale=1,placement=None,normal=None,close=True):
"""getTuples(data,[scale,placement,normal]): returns a tuple or a list of tuples from a vector """getTuples(data,[scale,placement,normal]): returns a tuple or a list of tuples from a vector
or from the vertices of a shape. Scale can indicate a scale factor""" or from the vertices of a shape. Scale can indicate a scale factor"""
import Part import Part
@ -630,6 +630,7 @@ def getTuples(data,scale=1,placement=None,normal=None):
if placement: if placement:
pt = placement.multVec(pt) pt = placement.multVec(pt)
t.append((pt.x*scale,pt.y*scale,pt.z*scale)) t.append((pt.x*scale,pt.y*scale,pt.z*scale))
if close:
t.append(t[0]) # for IFC verts lists must be closed t.append(t[0]) # for IFC verts lists must be closed
else: else:
print "Arch.getTuples(): Wrong profile data" print "Arch.getTuples(): Wrong profile data"
@ -669,10 +670,10 @@ def getBrepFacesData(obj,scale=1):
s = [] s = []
for face in obj.Shape.Faces: for face in obj.Shape.Faces:
f = [] f = []
f.append(getTuples(face.OuterWire,scale,normal=face.normalAt(0,0))) f.append(getTuples(face.OuterWire,scale,normal=face.normalAt(0,0),close=False))
for wire in face.Wires: for wire in face.Wires:
if wire.hashCode() != face.OuterWire.hashCode(): if wire.hashCode() != face.OuterWire.hashCode():
f.append(getTuples(wire,scale,normal=DraftVecUtils.neg(face.normalAt(0,0)))) f.append(getTuples(wire,scale,normal=DraftVecUtils.neg(face.normalAt(0,0)),close=False))
s.append(f) s.append(f)
sols.append(s) sols.append(s)
return sols return sols

View File

@ -240,7 +240,7 @@ def makeWall(ifcdoc,storey,owner,context,shape,placement=None,name="Default wall
in the given ifc document""" in the given ifc document"""
if not placement: if not placement:
placement = makePlacement(ifcdoc) placement = makePlacement(ifcdoc)
rep = create(ifcdoc,"IfcShapeRepresentation",[context,'Body','SweptSolid',[shape]]) rep = create(ifcdoc,"IfcShapeRepresentation",[context,'Body','SolidModel',[shape]])
prd = create(ifcdoc,"IfcProductDefinitionShape",[None,None,[rep]]) prd = create(ifcdoc,"IfcProductDefinitionShape",[None,None,[rep]])
wal = create(ifcdoc,"IfcWallStandardCase",[uid(),owner,name,description, wal = create(ifcdoc,"IfcWallStandardCase",[uid(),owner,name,description,
None,placement,prd,None]) None,placement,prd,None])
@ -375,6 +375,9 @@ class IfcDocument(object):
elif "FILE_NAME" in l: elif "FILE_NAME" in l:
# bug 4: incomplete file name entry # bug 4: incomplete file name entry
l = l.replace("FILE_NAME('','',(''),('',''),'IfcOpenShell','IfcOpenShell','');","FILE_NAME('"+path+"','"+now(string=True)+"',('"+self.Owner+"'),('',''),'IfcOpenShell','IfcOpenShell','');") l = l.replace("FILE_NAME('','',(''),('',''),'IfcOpenShell','IfcOpenShell','');","FILE_NAME('"+path+"','"+now(string=True)+"',('"+self.Owner+"'),('',''),'IfcOpenShell','IfcOpenShell','');")
elif "IFCSIUNIT" in l:
# bug 5: no way to insert * character
l = l.replace("IFCSIUNIT(#13,","IFCSIUNIT(*,")
lines.append(l) lines.append(l)
f.close() f.close()
f = open(path,"wb") f = open(path,"wb")
@ -441,7 +444,11 @@ class IfcDocument(object):
placement = self.addPlacement() placement = self.addPlacement()
if not isinstance(shapes,list): if not isinstance(shapes,list):
shapes = [shapes] shapes = [shapes]
reps = [create(self._fileobject,"IfcShapeRepresentation",[self._repcontext,'Body','SweptSolid',[shape]]) for shape in shapes] if standard:
solidType = "SweptSolid"
else:
solidType = "Brep"
reps = [create(self._fileobject,"IfcShapeRepresentation",[self._repcontext,'Body',solidType,[shape]]) for shape in shapes]
prd = create(self._fileobject,"IfcProductDefinitionShape",[None,None,reps]) prd = create(self._fileobject,"IfcProductDefinitionShape",[None,None,reps])
if standard: if standard:
wal = create(self._fileobject,"IfcWallStandardCase",[uid(),self._owner,name,description,None,placement,prd,None]) wal = create(self._fileobject,"IfcWallStandardCase",[uid(),self._owner,name,description,None,placement,prd,None])
@ -456,14 +463,18 @@ class IfcDocument(object):
self._relate(storey,wal) self._relate(storey,wal)
return wal return wal
def addStructure(self,ifctype,shapes,storey=None,placement=None,name="Default Structure",description=None): def addStructure(self,ifctype,shapes,storey=None,placement=None,name="Default Structure",description=None,standard=False):
"""addStructure(ifctype,shapes,[storey,placement,name,description]): creates a structure """addStructure(ifctype,shapes,[storey,placement,name,description]): creates a structure
from the given representation shape(s). Ifctype is the type of structural object (IfcBeam, IfcColumn, etc)""" from the given representation shape(s). Ifctype is the type of structural object (IfcBeam, IfcColumn, etc)"""
if not placement: if not placement:
placement = self.addPlacement() placement = self.addPlacement()
if not isinstance(shapes,list): if not isinstance(shapes,list):
shapes = [shapes] shapes = [shapes]
reps = [create(self._fileobject,"IfcShapeRepresentation",[self._repcontext,'Body','SweptSolid',[shape]]) for shape in shapes] if standard:
solidType = "SweptSolid"
else:
solidType = "Brep"
reps = [create(self._fileobject,"IfcShapeRepresentation",[self._repcontext,'Body',solidType,[shape]]) for shape in shapes]
prd = create(self._fileobject,"IfcProductDefinitionShape",[None,None,reps]) prd = create(self._fileobject,"IfcProductDefinitionShape",[None,None,reps])
if ifctype in ["IfcSlab","IfcFooting"]: if ifctype in ["IfcSlab","IfcFooting"]:
stt = create(self._fileobject,ifctype,[uid(),self._owner,name,description,None,placement,prd,None,"NOTDEFINED"]) stt = create(self._fileobject,ifctype,[uid(),self._owner,name,description,None,placement,prd,None,"NOTDEFINED"])
@ -485,7 +496,7 @@ class IfcDocument(object):
placement = self.addPlacement() placement = self.addPlacement()
if not isinstance(shapes,list): if not isinstance(shapes,list):
shapes = [shapes] shapes = [shapes]
reps = [create(self._fileobject,"IfcShapeRepresentation",[self._repcontext,'Body','SweptSolid',[shape]]) for shape in shapes] reps = [create(self._fileobject,"IfcShapeRepresentation",[self._repcontext,'Body','SolidModel',[shape]]) for shape in shapes]
prd = create(self._fileobject,"IfcProductDefinitionShape",[None,None,reps]) prd = create(self._fileobject,"IfcProductDefinitionShape",[None,None,reps])
win = create(self._fileobject,ifctype,[uid(),self._owner,name,description,None,placement,prd,None,float(height),float(width)]) win = create(self._fileobject,ifctype,[uid(),self._owner,name,description,None,placement,prd,None,float(height),float(width)])
self.BuildingProducts.append(win) self.BuildingProducts.append(win)

View File

@ -30,8 +30,10 @@ __url__ = "http://www.freecadweb.org"
# config # config
subtractiveTypes = ["IfcOpeningElement"] # elements that must be subtracted from their parents subtractiveTypes = ["IfcOpeningElement"] # elements that must be subtracted from their parents
SCHEMA = "http://www.steptools.com/support/stdev_docs/express/ifc2x3/ifc2x3_tc1.exp" SCHEMA = "http://www.steptools.com/support/stdev_docs/express/ifc2x3/ifc2x3_tc1.exp" # only for internal prser
MAKETEMPFILES = False # if True, shapes are passed from ifcopenshell to freecad through temp files MAKETEMPFILES = False # if True, shapes are passed from ifcopenshell to freecad through temp files
DEBUG = True # this is only for the python console, this value is overridden when importing through the GUI
SKIP = ["IfcBuildingElementProxy","IfcFlowTerminal","IfcFurnishingElement"] # default. overwritten by the GUI options
# end config # end config
if open.__module__ == '__builtin__': if open.__module__ == '__builtin__':
@ -60,11 +62,9 @@ def insert(filename,docname,skip=None):
def getConfig(): def getConfig():
"Gets Arch IFC import preferences" "Gets Arch IFC import preferences"
global CREATE_IFC_GROUPS, ASMESH, DEBUG, SKIP, PREFIX_NUMBERS, FORCE_PYTHON_PARSER, SEPARATE_OPENINGS, SEPARATE_PLACEMENTS global CREATE_IFC_GROUPS, ASMESH, PREFIX_NUMBERS, FORCE_PYTHON_PARSER, SEPARATE_OPENINGS, SEPARATE_PLACEMENTS
CREATE_IFC_GROUPS = False CREATE_IFC_GROUPS = False
IMPORT_IFC_FURNITURE = False IMPORT_IFC_FURNITURE = False
DEBUG = False
SKIP = ["IfcBuildingElementProxy","IfcFlowTerminal","IfcFurnishingElement"]
ASMESH = ["IfcFurnishingElement"] ASMESH = ["IfcFurnishingElement"]
PREFIX_NUMBERS = False PREFIX_NUMBERS = False
FORCE_PYTHON_PARSER = False FORCE_PYTHON_PARSER = False
@ -318,12 +318,12 @@ def read(filename,skip=None):
else: else:
# creating parent if needed # creating parent if needed
if IFCOPENSHELL5: if IFCOPENSHELL5:
parent_ifcobj = ifc.by_id(parent_id) obj = ifc.by_id(parent_id)
parentid = int(str(obj).split("=")[0].strip("#")) parentid = int(str(obj).split("=")[0].strip("#"))
parentname = obj.get_argument(obj.get_argument_index("Name")) parentname = obj.get_argument(obj.get_argument_index("Name"))
parenttype = str(obj).split("=")[1].split("(")[0] parenttype = str(obj).split("=")[1].split("(")[0]
else: else:
parent_ifcobj = IfcImport.GetObject(parent_id) obj = IfcImport.GetObject(parent_id)
parentid = obj.id parentid = obj.id
parentname = obj.name parentname = obj.name
parenttype = obj.type parenttype = obj.type
@ -343,6 +343,8 @@ def read(filename,skip=None):
elif parenttype == "IfcWindow": elif parenttype == "IfcWindow":
parent = Arch.makeWindow(name=n) parent = Arch.makeWindow(name=n)
parent.Label = n parent.Label = n
elif parenttype == "IfcProject":
parent = None
else: else:
if DEBUG: print "Fixme: skipping unhandled parent: ", parentid, " ", parenttype if DEBUG: print "Fixme: skipping unhandled parent: ", parentid, " ", parenttype
parent = None parent = None
@ -677,7 +679,7 @@ def getShape(obj,objid):
else: else:
sh.importBrepFromString(brep_data) sh.importBrepFromString(brep_data)
except: except:
print "Error: malformed shape" print " error: malformed shape"
return None return None
else: else:
if IFCOPENSHELL5 and SEPARATE_PLACEMENTS: if IFCOPENSHELL5 and SEPARATE_PLACEMENTS:
@ -688,7 +690,7 @@ def getShape(obj,objid):
# try to extract a solid shape # try to extract a solid shape
if sh.Faces: if sh.Faces:
try: try:
if DEBUG: print "Malformed solid. Attempting to fix..." if DEBUG: print " malformed solid. Attempting to fix..."
shell = Part.makeShell(sh.Faces) shell = Part.makeShell(sh.Faces)
if shell: if shell:
solid = Part.makeSolid(shell) solid = Part.makeSolid(shell)
@ -1026,7 +1028,7 @@ def export(exportList,filename):
#ifc.addStructure( role, ifc.addExtrudedPolyline(gdata[0],gdata[1]), storey=parent, name=name ) #ifc.addStructure( role, ifc.addExtrudedPolyline(gdata[0],gdata[1]), storey=parent, name=name )
if FreeCAD.Vector(gdata[1]).getAngle(FreeCAD.Vector(0,0,1)) < .01: if FreeCAD.Vector(gdata[1]).getAngle(FreeCAD.Vector(0,0,1)) < .01:
# Workaround for non-Z extrusions, apparently not supported by ifc++ TODO: fix this # Workaround for non-Z extrusions, apparently not supported by ifc++ TODO: fix this
ifc.addStructure( role, ifc.addExtrudedPolyline(gdata[0],gdata[1]), storey=parent, name=name ) ifc.addStructure( role, ifc.addExtrudedPolyline(gdata[0],gdata[1]), storey=parent, name=name, standard=True )
else: else:
fdata = Arch.getBrepFacesData(obj,scaling) fdata = Arch.getBrepFacesData(obj,scaling)
ifc.addStructure( role, [ifc.addFacetedBrep(f) for f in fdata], storey=parent, name=name ) ifc.addStructure( role, [ifc.addFacetedBrep(f) for f in fdata], storey=parent, name=name )
@ -1036,6 +1038,8 @@ def export(exportList,filename):
elif otype == "Window": elif otype == "Window":
if parent: if parent:
p = ifc.findByName("IfcWallStandardCase",str(parent.Label)) p = ifc.findByName("IfcWallStandardCase",str(parent.Label))
if not p:
p = ifc.findByName("IfcWall",str(parent.Label))
if not p: if not p:
p = ifc.findByName("IfcColumn",str(parent.Label)) p = ifc.findByName("IfcColumn",str(parent.Label))
if not p: if not p: