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:
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
or from the vertices of a shape. Scale can indicate a scale factor"""
import Part
@ -630,6 +630,7 @@ def getTuples(data,scale=1,placement=None,normal=None):
if placement:
pt = placement.multVec(pt)
t.append((pt.x*scale,pt.y*scale,pt.z*scale))
if close:
t.append(t[0]) # for IFC verts lists must be closed
else:
print "Arch.getTuples(): Wrong profile data"
@ -669,10 +670,10 @@ def getBrepFacesData(obj,scale=1):
s = []
for face in obj.Shape.Faces:
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:
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)
sols.append(s)
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"""
if not placement:
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]])
wal = create(ifcdoc,"IfcWallStandardCase",[uid(),owner,name,description,
None,placement,prd,None])
@ -375,6 +375,9 @@ class IfcDocument(object):
elif "FILE_NAME" in l:
# bug 4: incomplete file name entry
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)
f.close()
f = open(path,"wb")
@ -441,7 +444,11 @@ class IfcDocument(object):
placement = self.addPlacement()
if not isinstance(shapes,list):
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])
if standard:
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)
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
from the given representation shape(s). Ifctype is the type of structural object (IfcBeam, IfcColumn, etc)"""
if not placement:
placement = self.addPlacement()
if not isinstance(shapes,list):
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])
if ifctype in ["IfcSlab","IfcFooting"]:
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()
if not isinstance(shapes,list):
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])
win = create(self._fileobject,ifctype,[uid(),self._owner,name,description,None,placement,prd,None,float(height),float(width)])
self.BuildingProducts.append(win)

View File

@ -30,8 +30,10 @@ __url__ = "http://www.freecadweb.org"
# config
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
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
if open.__module__ == '__builtin__':
@ -60,11 +62,9 @@ def insert(filename,docname,skip=None):
def getConfig():
"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
IMPORT_IFC_FURNITURE = False
DEBUG = False
SKIP = ["IfcBuildingElementProxy","IfcFlowTerminal","IfcFurnishingElement"]
ASMESH = ["IfcFurnishingElement"]
PREFIX_NUMBERS = False
FORCE_PYTHON_PARSER = False
@ -318,12 +318,12 @@ def read(filename,skip=None):
else:
# creating parent if needed
if IFCOPENSHELL5:
parent_ifcobj = ifc.by_id(parent_id)
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:
parent_ifcobj = IfcImport.GetObject(parent_id)
obj = IfcImport.GetObject(parent_id)
parentid = obj.id
parentname = obj.name
parenttype = obj.type
@ -343,6 +343,8 @@ def read(filename,skip=None):
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
@ -677,7 +679,7 @@ def getShape(obj,objid):
else:
sh.importBrepFromString(brep_data)
except:
print "Error: malformed shape"
print " error: malformed shape"
return None
else:
if IFCOPENSHELL5 and SEPARATE_PLACEMENTS:
@ -688,7 +690,7 @@ def getShape(obj,objid):
# try to extract a solid shape
if sh.Faces:
try:
if DEBUG: print "Malformed solid. Attempting to fix..."
if DEBUG: print " malformed solid. Attempting to fix..."
shell = Part.makeShell(sh.Faces)
if 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 )
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
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:
fdata = Arch.getBrepFacesData(obj,scaling)
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":
if parent:
p = ifc.findByName("IfcWallStandardCase",str(parent.Label))
if not p:
p = ifc.findByName("IfcWall",str(parent.Label))
if not p:
p = ifc.findByName("IfcColumn",str(parent.Label))
if not p: