00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 import ifcReader, FreeCAD, Wall, Draft, os, time, Cell, Floor, Building, Site
00025 from draftlibs import fcvec
00026
00027 __title__="FreeCAD IFC importer"
00028 __author__ = "Yorik van Havre"
00029 __url__ = "http://free-cad.sourceforge.net"
00030
00031 DEBUG = True
00032
00033 def open(filename):
00034 "called when freecad opens a file"
00035 docname = os.path.splitext(os.path.basename(filename))[0]
00036 doc = FreeCAD.newDocument(docname)
00037 doc.Label = decode(docname)
00038 FreeCAD.ActiveDocument = doc
00039 read(filename)
00040 return doc
00041
00042 def decode(name):
00043 "decodes encoded strings"
00044 try:
00045 decodedName = (name.decode("utf8"))
00046 except UnicodeDecodeError:
00047 try:
00048 decodedName = (name.decode("latin1"))
00049 except UnicodeDecodeError:
00050 print "ifc: error: couldn't determine character encoding"
00051 decodedName = name
00052 return decodedName
00053
00054 def getSchema(schema):
00055 return os.path.join(FreeCAD.ConfigGet("AppHomePath"),"Mod","Arch",schema+".exp")
00056
00057 def read(filename):
00058 "processes an ifc file and add its objects to the given document"
00059 t1 = time.time()
00060 if DEBUG: global ifc
00061 if DEBUG: print "opening",filename,"..."
00062 ifc = ifcReader.IfcDocument(filename,schema=getSchema("IFC2X3_TC1"),debug=DEBUG)
00063 t2 = time.time()
00064 if DEBUG: print "Successfully loaded",ifc,"in %s s" % ((t2-t1))
00065
00066 for w in ifc.getEnt("IFCWALLSTANDARDCASE"):
00067 makeWall(w)
00068
00069 for f in ifc.getEnt("IFCBUILDINGSTOREY"):
00070 makeCell(f,"Floor")
00071
00072 for b in ifc.getEnt("IFCBUILDING"):
00073 makeCell(b,"Building")
00074 FreeCAD.ActiveDocument.recompute()
00075 t3 = time.time()
00076 if DEBUG: print "done processing",ifc,"in %s s" % ((t3-t1))
00077
00078 def makeCell(entity,mode="Cell"):
00079 "makes a cell in the freecad document"
00080 try:
00081 if DEBUG: print "=====> making cell",entity.id
00082 placement = None
00083 placement = getPlacement(entity.ObjectPlacement)
00084 if DEBUG: print "got cell placement",entity.id,":",placement
00085 subelements = ifc.find("IFCRELCONTAINEDINSPATIALSTRUCTURE","RelatingStructure",entity)
00086 subelements.extend(ifc.find("IFCRELAGGREGATES","RelatingObject",entity))
00087 fcelts = []
00088 for s in subelements:
00089 if hasattr(s,"RelatedElements"):
00090 s = s.RelatedElements
00091 if not isinstance(s,list): s = [s]
00092 for r in s:
00093 if r.type == "IFCWALLSTANDARDCASE":
00094 o = FreeCAD.ActiveDocument.getObject("Wall"+str(r.id))
00095 if o: fcelts.append(o)
00096 elif hasattr(s,"RelatedObjects"):
00097 s = s.RelatedObjects
00098 if not isinstance(s,list): s = [s]
00099 for r in s:
00100 if r.type == "IFCBUILDINGSTOREY":
00101 o = FreeCAD.ActiveDocument.getObject("Floor"+str(r.id))
00102 if o: fcelts.append(o)
00103 name = mode+str(entity.id)
00104 if mode == "Site":
00105 cell = Cell.makeSite(fcelts,name=name)
00106 elif mode == "Floor":
00107 cell = Cell.makeFloor(fcelts,join=True,name=name)
00108 elif mode == "Building":
00109 cell = Cell.makeBuilding(fcelts,name=name)
00110 else:
00111 cell = Cell.makeCell(fcelts,join=True,name=name)
00112 cell.CellType = type
00113 except:
00114 if DEBUG: print "error: skipping cell",entity.id
00115
00116 def makeWall(entity):
00117 "makes a wall in the freecad document"
00118 try:
00119 if DEBUG: print "=====> making wall",entity.id
00120 placement = wall = wire = body = width = height = None
00121 placement = getPlacement(entity.ObjectPlacement)
00122 if DEBUG: print "got wall placement",entity.id,":",placement
00123 width = entity.getProperty("Width")
00124 height = entity.getProperty("Height")
00125 if width and height:
00126 if DEBUG: print "got width, height ",entity.id,":",width,"/",height
00127 for r in entity.Representation.Representations:
00128 if r.RepresentationIdentifier == "Axis":
00129 wire = makeWire(r.Items,placement)
00130 wall = Wall.makeWall(wire,width,height,align="Center",name="Wall"+str(entity.id))
00131 else:
00132 if DEBUG: print "no height or width properties found..."
00133 for r in entity.Representation.Representations:
00134 if r.RepresentationIdentifier == "Body":
00135 for b in r.Items:
00136 if b.type == "IFCEXTRUDEDAREASOLID":
00137 norm = getVector(b.ExtrudedDirection)
00138 norm.normalize()
00139 wire = makeWire(b.SweptArea,placement)
00140 wall = Wall.makeWall(wire,width=0,height=b.Depth,name="Wall"+str(entity.id))
00141 wall.Normal = norm
00142 if wall:
00143 if DEBUG: print "made wall object ",entity.id,":",wall
00144 except:
00145 if DEBUG: print "error: skipping wall",entity.id
00146
00147 def makeWire(entity,placement=None):
00148 "makes a wire in the freecad document"
00149 if DEBUG: print "making Wire from :",entity
00150 if not entity: return None
00151 if entity.type == "IFCPOLYLINE":
00152 pts = []
00153 for p in entity.Points:
00154 pts.append(getVector(p))
00155 return Draft.makeWire(pts,placement=placement)
00156 elif entity.type == "IFCARBITRARYCLOSEDPROFILEDEF":
00157 pts = []
00158 for p in entity.OuterCurve.Points:
00159 pts.append(getVector(p))
00160 return Draft.makeWire(pts,closed=True,placement=placement)
00161
00162 def getPlacement(entity):
00163 "returns a placement from the given entity"
00164 if DEBUG: print "getting placement ",entity
00165 if not entity: return None
00166 pl = None
00167 if entity.type == "IFCAXIS2PLACEMENT3D":
00168 x = getVector(entity.RefDirection)
00169 z = getVector(entity.Axis)
00170 y = z.cross(x)
00171 loc = getVector(entity.Location)
00172 m = fcvec.getPlaneRotation(x,y,z)
00173 pl = FreeCAD.Placement(m)
00174 pl.move(loc)
00175 elif entity.type == "IFCLOCALPLACEMENT":
00176 pl = getPlacement(entity.PlacementRelTo)
00177 relpl = getPlacement(entity.RelativePlacement)
00178 if pl and relpl:
00179 pl = relpl.multiply(pl)
00180 elif relpl:
00181 pl = relpl
00182 elif entity.type == "IFCCARTESIANPOINT":
00183 loc = getVector(entity)
00184 pl = FreeCAD.Placement()
00185 pl.move(loc)
00186 if DEBUG: print "made placement for",entity.id,":",pl
00187 return pl
00188
00189 def getVector(entity):
00190 if DEBUG: print "getting point from",entity
00191 if entity.type == "IFCDIRECTION":
00192 if len(entity.DirectionRatios) == 3:
00193 return FreeCAD.Vector(tuple(entity.DirectionRatios))
00194 else:
00195 return FreeCAD.Vector(tuple(entity.DirectionRatios+[0]))
00196 elif entity.type == "IFCCARTESIANPOINT":
00197 if len(entity.Coordinates) == 3:
00198 return FreeCAD.Vector(tuple(entity.Coordinates))
00199 else:
00200 return FreeCAD.Vector(tuple(entity.Coordinates+[0]))
00201 return None