Arch: Added IFC export to the GUI + using new ifcopenshell for import - fixes #1005

This commit is contained in:
Yorik van Havre 2013-12-26 11:38:30 -02:00
parent a2cba17d3f
commit 7ceef577a2
4 changed files with 318 additions and 176 deletions

View File

@ -146,6 +146,7 @@ FreeCADGui.addWorkbench(ArchWorkbench)
# add import/export types # add import/export types
FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC") FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC")
FreeCAD.addExportType("Industry Foundation Classes (*.ifc)","importIFC")
FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ") FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ")
FreeCAD.addExportType("WebGL file (*.html)","importWebGL") FreeCAD.addExportType("WebGL file (*.html)","importWebGL")
FreeCAD.addImportType("Collada (*.dae)","importDAE") FreeCAD.addImportType("Collada (*.dae)","importDAE")

View File

@ -30,15 +30,18 @@
import sys, uuid, time, math import sys, uuid, time, math
# if you already have another version of IfcOpenShell:
# adding here the path to the ifcwrap folder of the ifcopenshell build. That # adding here the path to the ifcwrap folder of the ifcopenshell build. That
# folder must also contain an __init__.py file. This is to differentiate with # folder must also contain an __init__.py file. This is to differentiate with
# systemwide-installed IfcOpenShell, which has the same name. # systemwide-installed IfcOpenShell, which has the same name.
# if you have such setup, uncomment the following 2 lines and comment out the
sys.path.append("/home/yorik/Sources/build/ifcopenshell-dev") # third one.
from ifcwrap import IfcImport as IfcExport #sys.path.append("/home/yorik/Sources/build/ifcopenshell-dev")
#from ifcwrap import IfcImport
import IfcImport
# checking that we got the right importer, with export capabilities # checking that we got the right importer, with export capabilities
if not hasattr(IfcExport,"IfcFile"): if not hasattr(IfcImport,"IfcFile"):
print "Wrong version of IfcOpenShell" print "Wrong version of IfcOpenShell"
sys.exit() sys.exit()
@ -57,7 +60,7 @@ holder = _tempEntityHolder()
def new(): def new():
"""new(): returns a new empty ifc file holder""" """new(): returns a new empty ifc file holder"""
fil = IfcExport.IfcFile() fil = IfcImport.IfcFile()
return fil return fil
def uid(): def uid():
@ -110,7 +113,7 @@ def create(ifcdoc=None,ifcname=None,arguments=[]):
"""create(ifcdoc,ifcname,[arguments]):creates an entity """create(ifcdoc,ifcname,[arguments]):creates an entity
of the given name in the given document and optionally of the given name in the given document and optionally
gives it an ordered list of arguments""" gives it an ordered list of arguments"""
entity = IfcExport.Entity(ifcname) entity = IfcImport.Entity(ifcname)
if ifcdoc: if ifcdoc:
ifcdoc.add(entity) ifcdoc.add(entity)
# this is a temporary hack while ifcopenshell has no ref counting # this is a temporary hack while ifcopenshell has no ref counting
@ -121,7 +124,7 @@ def create(ifcdoc=None,ifcname=None,arguments=[]):
arg = arguments[i] arg = arguments[i]
if isinstance(arg,tuple): if isinstance(arg,tuple):
if len(arg) == 3: if len(arg) == 3:
arg = IfcExport.Doubles(arg) arg = IfcImport.Doubles(arg)
entity.set_argument(i,arg) entity.set_argument(i,arg)
return entity return entity
@ -280,7 +283,7 @@ class IfcDocument(object):
Creates an empty IFC document.""" Creates an empty IFC document."""
def __init__(self,filepath="",name="",owner="",organization="",application="Python IFC exporter",version="0.0"): def __init__(self,filepath="",name="",owner="",organization="",application="Python IFC exporter",version="0.0"):
self._fileobject = IfcExport.IfcFile() self._fileobject = IfcImport.IfcFile()
self._person = create(self._fileobject,"IfcPerson",[None,None,"",None,None,None,None,None]) self._person = create(self._fileobject,"IfcPerson",[None,None,"",None,None,None,None,None])
self._org = create(self._fileobject,"IfcOrganization",[None,"",None,None,None]) self._org = create(self._fileobject,"IfcOrganization",[None,"",None,None,None])
pno = create(self._fileobject,"IfcPersonAndOrganization",[self._person,self._org,None]) pno = create(self._fileobject,"IfcPersonAndOrganization",[self._person,self._org,None])

View File

@ -32,6 +32,7 @@ __url__ = "http://www.freecadweb.org"
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"
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
ADDPLACEMENT = False # if True, placements get computed (only for newer ifcopenshell)
# end config # end config
if open.__module__ == '__builtin__': if open.__module__ == '__builtin__':
@ -98,108 +99,176 @@ def read(filename):
# parsing the IFC file # parsing the IFC file
t1 = time.time() t1 = time.time()
num_lines = sum(1 for line in pyopen(filename))
processedIds = [] processedIds = []
if getIfcOpenShell() and not FORCE_PYTHON_PARSER: if getIfcOpenShell() and not FORCE_PYTHON_PARSER:
# use the IfcOpenShell parser # use the IfcOpenShell parser
# check for IFcOpenShellVersion
global IOC_ADVANCED
if hasattr(IfcImport,"IfcFile"):
IOC_ADVANCED = True
else:
IOC_ADVANCED = False
# preparing IfcOpenShell # preparing IfcOpenShell
if DEBUG: global ifcObjects,ifcParents if DEBUG: global ifcObjects,ifcParents
ifcObjects = {} # a table to relate ifc id with freecad object ifcObjects = {} # a table to relate ifc id with freecad object
ifcParents = {} # a table to relate ifc id with parent id ifcParents = {} # a table to relate ifc id with parent id
if hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS") and SEPARATE_OPENINGS: if SEPARATE_OPENINGS:
if hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS"):
IfcImport.Settings(IfcImport.DISABLE_OPENING_SUBTRACTIONS,True) IfcImport.Settings(IfcImport.DISABLE_OPENING_SUBTRACTIONS,True)
else: else:
SKIP.append("IfcOpeningElement") SKIP.append("IfcOpeningElement")
useShapes = False useShapes = False
if hasattr(IfcImport,"USE_BREP_DATA"): if IOC_ADVANCED:
useShapes = True
elif hasattr(IfcImport,"USE_BREP_DATA"):
IfcImport.Settings(IfcImport.USE_BREP_DATA,True) IfcImport.Settings(IfcImport.USE_BREP_DATA,True)
useShapes = True useShapes = True
else: else:
if DEBUG: print "Warning: IfcOpenShell version very old, unable to handle Brep data" if DEBUG: print "Warning: IfcOpenShell version very old, unable to handle Brep data"
# processing geometry # opening file
if IfcImport.Init(filename): if IOC_ADVANCED:
while True: 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:
obj = IfcImport.Get() obj = IfcImport.Get()
if DEBUG: print "["+str(int((float(obj.id)/num_lines)*100))+"%] parsing ",obj.id,": ",obj.name," of type ",obj.type 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 # retrieving name
n = getName(obj) n = getCleanName(objname,objid,objtype)
# skip types # skip types
if obj.type in SKIP: if objtype in SKIP:
if DEBUG: print "skipping because type is in skip list" if DEBUG: print "skipping because type is in skip list"
nobj = None nobj = None
# check if object was already processed, to workaround an ifcopenshell bug # check if object was already processed, to workaround an ifcopenshell bug
elif obj.id in processedIds: elif objid in processedIds:
if DEBUG: print "skipping because this object was already processed" if DEBUG: print "skipping because this object was already processed"
else: else:
# build shape # build shape
shape = None shape = None
if useShapes: if useShapes:
shape = getShape(obj) shape = getShape(obj,objid)
# walls # walls
if obj.type in ["IfcWallStandardCase","IfcWall"]: if objtype in ["IfcWallStandardCase","IfcWall"]:
nobj = makeWall(obj.id,shape,n) nobj = makeWall(objid,shape,n)
# windows # windows
elif obj.type in ["IfcWindow","IfcDoor"]: elif objtype in ["IfcWindow","IfcDoor"]:
nobj = makeWindow(obj.id,shape,n) nobj = makeWindow(objid,shape,n)
# structs # structs
elif obj.type in ["IfcBeam","IfcColumn","IfcSlab","IfcFooting"]: elif objtype in ["IfcBeam","IfcColumn","IfcSlab","IfcFooting"]:
nobj = makeStructure(obj.id,shape,obj.type,n) nobj = makeStructure(objid,shape,objtype,n)
# roofs # roofs
elif obj.type in ["IfcRoof"]: elif objtype in ["IfcRoof"]:
nobj = makeRoof(obj.id,shape,n) nobj = makeRoof(objid,shape,n)
# furniture # furniture
elif obj.type in ["IfcFurnishingElement"]: elif objtype in ["IfcFurnishingElement"]:
nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n)
nobj.Shape = shape nobj.Shape = shape
# sites # sites
elif obj.type in ["IfcSite"]: elif objtype in ["IfcSite"]:
nobj = makeSite(obj.id,shape,n) 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 # spaces
elif obj.type in ["IfcSpace"]: elif objtype in ["IfcSpace"]:
nobj = makeSpace(obj.id,shape,n) nobj = makeSpace(objid,shape,n)
elif shape: elif shape:
# treat as dumb parts # treat as dumb parts
#if DEBUG: print "Fixme: Shape-containing object not handled: ",obj.id, " ", obj.type #if DEBUG: print "Fixme: Shape-containing object not handled: ",obj.id, " ", obj.type
nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n)
nobj.Label = n
nobj.Shape = shape nobj.Shape = shape
else: else:
# treat as meshes # treat as meshes
if DEBUG: print "Warning: Object without shape: ",obj.id, " ", obj.type if DEBUG: print "Warning: Object without shape: ",objid, " ", objtype
me,pl = getMesh(obj) me,pl = getMesh(obj)
nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n) nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n)
nobj.Label = n
nobj.Mesh = me nobj.Mesh = me
nobj.Placement = pl nobj.Placement = pl
# registering object number and parent # registering object number and parent
if obj.parent_id > 0: if objparentid > 0:
ifcParents[obj.id] = [obj.parent_id,not (obj.type in subtractiveTypes)] ifcParents[objid] = [objparentid,not (objtype in subtractiveTypes)]
ifcObjects[obj.id] = nobj ifcObjects[objid] = nobj
processedIds.append(obj.id) processedIds.append(objid)
if IOC_ADVANCED:
if idx >= len(objects):
break
else:
if not IfcImport.Next(): if not IfcImport.Next():
break break
# processing non-geometry and relationships # processing non-geometry and relationships
parents_temp = dict(ifcParents) parents_temp = dict(ifcParents)
import ArchCommands import ArchCommands
#print parents_temp
while parents_temp: while parents_temp:
id, c = parents_temp.popitem() id, c = parents_temp.popitem()
@ -220,41 +289,53 @@ def read(filename):
parent = ifcObjects[grandparent_id] parent = ifcObjects[grandparent_id]
else: else:
# creating parent if needed # 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) 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 parentid = obj.id
n = getName(parent_ifcobj) parentname = obj.name
if parent_ifcobj.id <= 0: 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 parent = None
elif parent_ifcobj.type == "IfcBuildingStorey": elif parenttype == "IfcBuildingStorey":
parent = Arch.makeFloor(name=n) parent = Arch.makeFloor(name=n)
parent.Label = n parent.Label = n
elif parent_ifcobj.type == "IfcBuilding": elif parenttype == "IfcBuilding":
parent = Arch.makeBuilding(name=n) parent = Arch.makeBuilding(name=n)
parent.Label = n parent.Label = n
elif parent_ifcobj.type == "IfcSite": elif parenttype == "IfcSite":
parent = Arch.makeSite(name=n) parent = Arch.makeSite(name=n)
parent.Label = n parent.Label = n
elif parent_ifcobj.type == "IfcWindow": elif parenttype == "IfcWindow":
parent = Arch.makeWindow(name=n) parent = Arch.makeWindow(name=n)
parent.Label = n parent.Label = n
else: else:
if DEBUG: print "Fixme: skipping unhandled parent: ", parent_ifcobj.id, " ", parent_ifcobj.type if DEBUG: print "Fixme: skipping unhandled parent: ", parentid, " ", parenttype
parent = None parent = None
# registering object number and parent # registering object number and parent
if not IOC_ADVANCED:
if parent_ifcobj.parent_id > 0: if parent_ifcobj.parent_id > 0:
ifcParents[parent_ifcobj.id] = [parent_ifcobj.parent_id,True] ifcParents[parentid] = [parent_ifcobj.parent_id,True]
parents_temp[parent_ifcobj.id] = [parent_ifcobj.parent_id,True] parents_temp[parentid] = [parent_ifcobj.parent_id,True]
if parent and (not parent_ifcobj.id in ifcObjects): if parent and (not parentid in ifcObjects):
ifcObjects[parent_ifcobj.id] = parent ifcObjects[parentid] = parent
# attributing parent # attributing parent
if parent and (id in ifcObjects): if parent and (id in ifcObjects):
if ifcObjects[id]: if ifcObjects[id] and (ifcObjects[id].Name != parent.Name):
if additive: if additive:
if DEBUG: print "adding ",ifcObjects[id].Name, " to ",parent.Name
ArchCommands.addComponents(ifcObjects[id],parent) ArchCommands.addComponents(ifcObjects[id],parent)
else: else:
if DEBUG: print "removing ",ifcObjects[id].Name, " from ",parent.Name
ArchCommands.removeComponents(ifcObjects[id],parent) ArchCommands.removeComponents(ifcObjects[id],parent)
if not IOC_ADVANCED:
IfcImport.CleanUp() IfcImport.CleanUp()
else: else:
@ -263,7 +344,6 @@ def read(filename):
FreeCAD.Console.PrintWarning(str(translate("Arch","IfcOpenShell not found or disabled, falling back on internal parser.\n"))) FreeCAD.Console.PrintWarning(str(translate("Arch","IfcOpenShell not found or disabled, falling back on internal parser.\n")))
schema=getSchema() schema=getSchema()
if schema: if schema:
if DEBUG: global ifc
if DEBUG: print "opening",filename,"..." if DEBUG: print "opening",filename,"..."
ifc = ifcReader.IfcDocument(filename,schema=schema,debug=DEBUG) ifc = ifcReader.IfcDocument(filename,schema=schema,debug=DEBUG)
else: else:
@ -304,13 +384,15 @@ def read(filename):
return None return None
def getName(ifcobj):
def getCleanName(name,ifcid,ifctype):
"Get a clean name from an ifc object" "Get a clean name from an ifc object"
n = ifcobj.name #print "getCleanName called",name,ifcid,ifctype
n = name
if not n: if not n:
n = ifcobj.type n = ifctype
if PREFIX_NUMBERS: if PREFIX_NUMBERS:
n = "ID"+str(ifcobj.id)+" "+n n = "ID"+str(ifcid)+" "+n
#for c in ",.!?;:": #for c in ",.!?;:":
# n = n.replace(c,"_") # n = n.replace(c,"_")
return n return n
@ -329,6 +411,8 @@ def makeWall(entity,shape=None,name="Wall"):
body.Mesh = shape body.Mesh = shape
wall = Arch.makeWall(body,name=name) wall = Arch.makeWall(body,name=name)
wall.Label = name wall.Label = name
if IOC_ADVANCED and ADDPLACEMENT:
wall.Placement = getPlacement(getAttr(entity,"ObjectPlacement"))
if DEBUG: print "made wall object ",entity,":",wall if DEBUG: print "made wall object ",entity,":",wall
return wall return wall
@ -375,6 +459,8 @@ def makeWindow(entity,shape=None,name="Window"):
window = Arch.makeWindow(name=name) window = Arch.makeWindow(name=name)
window.Shape = shape window.Shape = shape
window.Label = name window.Label = name
if IOC_ADVANCED and ADDPLACEMENT:
window.Placement = getPlacement(getAttr(entity,"ObjectPlacement"))
if DEBUG: print "made window object ",entity,":",window if DEBUG: print "made window object ",entity,":",window
return window return window
@ -422,6 +508,9 @@ def makeStructure(entity,shape=None,ifctype=None,name="Structure"):
structure.Role = "Slab" structure.Role = "Slab"
elif ifctype == "IfcFooting": elif ifctype == "IfcFooting":
structure.Role = "Foundation" structure.Role = "Foundation"
print "current placement: ",shape.Placement
if IOC_ADVANCED and ADDPLACEMENT:
structure.Placement = getPlacement(getAttr(entity,"ObjectPlacement"))
if DEBUG: print "made structure object ",entity,":",structure," (type: ",ifctype,")" if DEBUG: print "made structure object ",entity,":",structure," (type: ",ifctype,")"
return structure return structure
@ -505,6 +594,9 @@ def makeRoof(entity,shape=None,name="Roof"):
def getMesh(obj): def getMesh(obj):
"gets mesh and placement from an IfcOpenShell object" "gets mesh and placement from an IfcOpenShell object"
if IOC_ADVANCED:
return None,None
print "fixme: mesh data not yet supported" # TODO implement this with OCC tessellate
import Mesh import Mesh
meshdata = [] meshdata = []
print obj.mesh.faces print obj.mesh.faces
@ -528,23 +620,31 @@ def getMesh(obj):
pl = FreeCAD.Placement(mat) pl = FreeCAD.Placement(mat)
return me,pl return me,pl
def getShape(obj): def getShape(obj,objid):
"gets a shape from an IfcOpenShell object" "gets a shape from an IfcOpenShell object"
#print "retrieving shape from obj ",obj.id #print "retrieving shape from obj ",objid
import Part import Part
sh=Part.Shape() 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: try:
if MAKETEMPFILES: if MAKETEMPFILES:
import tempfile import tempfile
tf = tempfile.mkstemp(suffix=".brp")[1] tf = tempfile.mkstemp(suffix=".brp")[1]
of = pyopen(tf,"wb") of = pyopen(tf,"wb")
of.write(obj.mesh.brep_data) of.write(brep_data)
of.close() of.close()
sh = Part.read(tf) sh = Part.read(tf)
os.remove(tf) os.remove(tf)
else: else:
sh.importBrepFromString(obj.mesh.brep_data) sh.importBrepFromString(brep_data)
#sh = Part.makeBox(2,2,2)
except: except:
print "Error: malformed shape" print "Error: malformed shape"
return None return None
@ -559,9 +659,10 @@ def getShape(obj):
if solid: if solid:
sh = solid sh = solid
except: except:
if DEBUG: print "failed to retrieve solid from object ",obj.id if DEBUG: print "failed to retrieve solid from object ",objid
else: else:
if DEBUG: print "object ", obj.id, " doesn't contain any face" if DEBUG: print "object ", objid, " doesn't contain any geometry"
if not IOC_ADVANCED:
m = obj.matrix m = obj.matrix
mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9], mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9],
m[1], m[4], m[7], m[10], m[1], m[4], m[7], m[10],
@ -573,6 +674,75 @@ def getShape(obj):
#for v in sh.Vertexes: print v.Point #for v in sh.Vertexes: print v.Point
return sh return sh
def getPlacement(entity):
"returns a placement from the given entity"
if DEBUG: print " getting placement ",entity
if not entity:
return None
if IOC_ADVANCED:
if isinstance(entity,int):
entity = ifc.by_id(entity)
entitytype = str(entity).split("=")[1].split("(")[0].upper()
entityid = int(str(entity).split("=")[0].strip("#"))
else:
entitytype = entity.type.upper()
entityid = entity.id
pl = None
if entitytype == "IFCAXIS2PLACEMENT3D":
x = getVector(getAttr(entity,"RefDirection"))
z = getVector(getAttr(entity,"Axis"))
y = z.cross(x)
loc = getVector(getAttr(entity,"Location"))
m = DraftVecUtils.getPlaneRotation(x,y,z)
pl = FreeCAD.Placement(m)
pl.move(loc)
elif entitytype == "IFCLOCALPLACEMENT":
pl = getPlacement(getAttr(entity,"PlacementRelTo"))
relpl = getPlacement(getAttr(entity,"RelativePlacement"))
if pl and relpl:
pl = relpl.multiply(pl)
elif relpl:
pl = relpl
elif entitytype == "IFCCARTESIANPOINT":
loc = getVector(entity)
pl = FreeCAD.Placement()
pl.move(loc)
if DEBUG: print " made placement for ",entityid,":",pl
return pl
def getAttr(entity,attr):
"returns the given attribute from the given entity"
if IOC_ADVANCED:
if isinstance(entity,int):
entity = ifc.by_id(entity)
i = entity.get_argument_index(attr)
return entity.get_argument(i)
else:
return getattr(entity,attr)
def getVector(entity):
"returns a vector from the given entity"
if DEBUG: print " getting point from ",entity
if IOC_ADVANCED:
if isinstance(entity,int):
entity = ifc.by_id(entity)
entitytype = str(entity).split("=")[1].split("(")[0].upper()
else:
entitytype = entity.type.upper()
if entitytype == "IFCDIRECTION":
DirectionRatios = getAttr(entity,"DirectionRatios")
if len(DirectionRatios) == 3:
return FreeCAD.Vector(tuple(DirectionRatios))
else:
return FreeCAD.Vector(tuple(DirectionRatios+[0]))
elif entitytype == "IFCCARTESIANPOINT":
Coordinates = getAttr(entity,"Coordinates")
if len(Coordinates) == 3:
return FreeCAD.Vector(tuple(Coordinates))
else:
return FreeCAD.Vector(tuple(Coordinates+[0]))
return None
# below is only used by the internal parser ######################################### # below is only used by the internal parser #########################################
def decode(name): def decode(name):
@ -692,59 +862,25 @@ def getWire(entity,placement=None):
pts.append(getVector(p)) pts.append(getVector(p))
return Draft.getWire(pts,closed=True,placement=placement) return Draft.getWire(pts,closed=True,placement=placement)
def getPlacement(entity):
"returns a placement from the given entity"
# only used by the internal parser
if DEBUG: print "getting placement ",entity
if not entity: return None
pl = None
if entity.type == "IFCAXIS2PLACEMENT3D":
x = getVector(entity.RefDirection)
z = getVector(entity.Axis)
y = z.cross(x)
loc = getVector(entity.Location)
m = DraftVecUtils.getPlaneRotation(x,y,z)
pl = FreeCAD.Placement(m)
pl.move(loc)
elif entity.type == "IFCLOCALPLACEMENT":
pl = getPlacement(entity.PlacementRelTo)
relpl = getPlacement(entity.RelativePlacement)
if pl and relpl:
pl = relpl.multiply(pl)
elif relpl:
pl = relpl
elif entity.type == "IFCCARTESIANPOINT":
loc = getVector(entity)
pl = FreeCAD.Placement()
pl.move(loc)
if DEBUG: print "made placement for",entity.id,":",pl
return pl
def getVector(entity):
"returns a vector from the given entity"
# only used by the internal parser
if DEBUG: print "getting point from",entity
if entity.type == "IFCDIRECTION":
if len(entity.DirectionRatios) == 3:
return FreeCAD.Vector(tuple(entity.DirectionRatios))
else:
return FreeCAD.Vector(tuple(entity.DirectionRatios+[0]))
elif entity.type == "IFCCARTESIANPOINT":
if len(entity.Coordinates) == 3:
return FreeCAD.Vector(tuple(entity.Coordinates))
else:
return FreeCAD.Vector(tuple(entity.Coordinates+[0]))
return None
# EXPORT ########################################################## # EXPORT ##########################################################
def export(exportList,filename): def export(exportList,filename):
"called when freecad exports a file" "called when freecad exports a file"
try: try:
import ifcWriter import IfcImport
except: except:
print "importIFC: ifcWriter not found or unusable. Unable to export." print """importIFC: ifcOpenShell is not installed. IFC export is unavailable.
Note: IFC export currently requires an experimental version of IfcOpenShell
available from https://github.com/aothms/IfcOpenShell"""
return return
else:
if not hasattr(IfcImport,"IfcFile"):
print """importIFC: The version of ifcOpenShell installed on this system doesn't
have IFC export capabilities. IFC export currently requires an experimental
version of IfcOpenShell available from https://github.com/aothms/IfcOpenShell"""
return
import ifcWriter
# creating base IFC project # creating base IFC project
import Arch,Draft import Arch,Draft

View File

@ -200,6 +200,8 @@ def geomType(edge):
def isValidPath(shape): def isValidPath(shape):
"isValidPath(shape): returns True if the shape can be used as an extrusion path" "isValidPath(shape): returns True if the shape can be used as an extrusion path"
if shape.isNull():
return False
if shape.Faces: if shape.Faces:
return False return False
if len(shape.Wires) > 1: if len(shape.Wires) > 1: