importIFC.py

Go to the documentation of this file.
00001 #***************************************************************************
00002 #*                                                                         *
00003 #*   Copyright (c) 2011                                                    *  
00004 #*   Yorik van Havre <yorik@uncreated.net>                                 *  
00005 #*                                                                         *
00006 #*   This program is free software; you can redistribute it and/or modify  *
00007 #*   it under the terms of the GNU General Public License (GPL)            *
00008 #*   as published by the Free Software Foundation; either version 2 of     *
00009 #*   the License, or (at your option) any later version.                   *
00010 #*   for detail see the LICENCE text file.                                 *
00011 #*                                                                         *
00012 #*   This program is distributed in the hope that it will be useful,       *
00013 #*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014 #*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015 #*   GNU Library General Public License for more details.                  *
00016 #*                                                                         *
00017 #*   You should have received a copy of the GNU Library General Public     *
00018 #*   License along with this program; if not, write to the Free Software   *
00019 #*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
00020 #*   USA                                                                   *
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     # getting walls
00066     for w in ifc.getEnt("IFCWALLSTANDARDCASE"):
00067         makeWall(w)
00068     # getting floors
00069     for f in ifc.getEnt("IFCBUILDINGSTOREY"):
00070         makeCell(f,"Floor")
00071     # getting buildings
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

Generated on Wed Nov 23 19:00:18 2011 for FreeCAD by  doxygen 1.6.1