예제 #1
0
 def testAdd(self):
     FreeCAD.Console.PrintLog('Checking Arch Add...\n')
     l = Draft.makeLine(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(2, 0, 0))
     w = Arch.makeWall(l, width=0.2, height=2)
     sb = Part.makeBox(1, 1, 1)
     b = FreeCAD.ActiveDocument.addObject('Part::Feature', 'Box')
     b.Shape = sb
     FreeCAD.ActiveDocument.recompute()
     Arch.addComponents(b, w)
     FreeCAD.ActiveDocument.recompute()
     r = (w.Shape.Volume > 1.5)
     self.failUnless(r, "Arch Add failed")
예제 #2
0
 def testAdd(self):
     FreeCAD.Console.PrintLog ('Checking Arch Add...\n')
     l=Draft.makeLine(FreeCAD.Vector(0,0,0),FreeCAD.Vector(2,0,0))
     w = Arch.makeWall(l,width=0.2,height=2)
     sb = Part.makeBox(1,1,1)
     b = FreeCAD.ActiveDocument.addObject('Part::Feature','Box')
     b.Shape = sb
     FreeCAD.ActiveDocument.recompute()
     Arch.addComponents(b,w)
     FreeCAD.ActiveDocument.recompute()
     r = (w.Shape.Volume > 1.5)
     self.failUnless(r,"Arch Add failed")
예제 #3
0
def insert(filename, docname, skip=[]):
    "imports the contents of an IFC file"

    p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
    DEBUG = p.GetBool("ifcDebug", False)
    PREFIX_NUMBERS = p.GetBool("ifcPrefixNumbers", False)
    SKIP = p.GetString("ifcSkip", "")
    SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings", False)
    SCALE = p.GetFloat("IfcScalingFactor", 1.0)

    try:
        import ifcopenshell
    except:
        if DEBUG: print "using legacy importer"
        import importIFClegacy
        return importIFClegacy.insert(filename, docname, skip)

    if DEBUG: print "opening ", filename, "..."
    try:
        doc = FreeCAD.getDocument(docname)
    except:
        doc = FreeCAD.newDocument(docname)
    FreeCAD.ActiveDocument = doc

    global ifcfile  # keeping global for debugging purposes
    ifcopenshell.clean()
    if isinstance(filename, unicode):
        import sys  #workaround since ifcopenshell currently can't handle unicode filenames
        filename = filename.encode(sys.getfilesystemencoding())
    ifcfile = ifcopenshell.open(filename)
    shape_attributes = ifcopenshell.SEW_SHELLS
    if SEPARATE_OPENINGS:
        shape_attributes += ifcopenshell.DISABLE_OPENING_SUBTRACTIONS
    sites = ifcfile.by_type("IfcSite")
    buildings = ifcfile.by_type("IfcBuilding")
    floors = ifcfile.by_type("IfcBuildingStorey")
    products = ifcfile.by_type("IfcProduct")
    openings = ifcfile.by_type("IfcOpeningElement")

    # building relations tables
    objects = {}  # { id:object, ... }
    additions = {}  # { host:[child,...], ... }
    subtractions = []  # [ [opening,host], ... ]
    properties = {}  # { host:[property, ...], ... }
    for r in ifcfile.by_type("IfcRelContainedInSpatialStructure"):
        additions.setdefault(r.RelatingStructure.id(),
                             []).extend([e.id() for e in r.RelatedElements])
    for r in ifcfile.by_type("IfcRelAggregates"):
        additions.setdefault(r.RelatingObject.id(),
                             []).extend([e.id() for e in r.RelatedObjects])
    for r in ifcfile.by_type("IfcRelVoidsElement"):
        subtractions.append(
            [r.RelatedOpeningElement.id(),
             r.RelatingBuildingElement.id()])
    for r in ifcfile.by_type("IfcRelDefinesByProperties"):
        for obj in r.RelatedObjects:
            properties.setdefault(obj.id(), []).extend(
                [e.id() for e in r.RelatingPropertyDefinition.HasProperties])

    # products
    for product in products:
        pid = product.id()
        guid = product.GlobalId
        ptype = product.is_a()
        name = product.Name or str(ptype[3:])
        if PREFIX_NUMBERS: name = "ID" + str(pid) + " " + name
        obj = None
        baseobj = None

        if (ptype == "IfcOpeningElement") and (not SEPARATE_OPENINGS): continue
        if pid in skip: continue
        if ptype in SKIP: continue

        brep = ifcopenshell.create_shape(product, shape_attributes)
        if brep:
            shape = Part.Shape()
            shape.importBrepFromString(brep)
            if SCALE != 1:
                shape.scale(SCALE)
            if not shape.isNull():
                baseobj = FreeCAD.ActiveDocument.addObject(
                    "Part::Feature", name + "_body")
                baseobj.Shape = shape
        for freecadtype, ifctypes in typesmap.iteritems():
            if ptype in ifctypes:
                obj = getattr(Arch, "make" + freecadtype)(baseobj=baseobj,
                                                          name=name)
                obj.Label = name
                # setting role
                try:
                    r = ptype[3:]
                    tr = dict((v, k) for k, v in translationtable.iteritems())
                    if r in tr.keys():
                        r = tr[r]
                    obj.Role = r
                except:
                    pass
                # setting uid
                if hasattr(obj, "IfcAttributes"):
                    a = obj.IfcAttributes
                    a["IfcUID"] = str(guid)
                    obj.IfcAttributes = a
                break
        if not obj:
            obj = baseobj
        if obj:
            sh = baseobj.Shape.ShapeType if hasattr(baseobj,
                                                    "Shape") else "None"
            sols = str(baseobj.Shape.Solids) if hasattr(baseobj,
                                                        "Shape") else ""
            if DEBUG:
                print "creating object ", pid, " : ", ptype, " with shape: ", sh, " ", sols
            objects[pid] = obj

        # properties
        if pid in properties:
            if hasattr(obj, "IfcAttributes"):
                a = obj.IfcAttributes
                for p in properties[pid]:
                    o = ifcfile[p]
                    a[o.Name] = str(o.NominalValue)
                obj.IfcAttributes = a

    # subtractions
    if SEPARATE_OPENINGS:
        for subtraction in subtractions:
            if (subtraction[0] in objects.keys()) and (subtraction[1]
                                                       in objects.keys()):
                Arch.removeComponents(objects[subtraction[0]],
                                      objects[subtraction[1]])

    # additions
    for host, children in additions.iteritems():
        if host in objects.keys():
            cobs = [
                objects[child] for child in children
                if child in objects.keys()
            ]
            if cobs:
                Arch.addComponents(cobs, objects[host])

    FreeCAD.ActiveDocument.recompute()

    # cleaning bad shapes
    for obj in objects.values():
        if obj.isDerivedFrom("Part::Feature"):
            if obj.Shape.isNull():
                Arch.rebuildArchShape(obj)
    FreeCAD.ActiveDocument.recompute()

    if FreeCAD.GuiUp:
        import FreeCADGui
        FreeCADGui.SendMsgToActiveView("ViewFit")
    return doc
예제 #4
0
def insert(filename,docname,skip=[]):
    "imports the contents of an IFC file"
    
    try:
        import ifcopenshell
    except:
        if DEBUG: print "using legacy importer"
        import importIFClegacy
        return importIFClegacy.insert(filename,docname,skip)

    p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
    DEBUG = p.GetBool("ifcDebug",False)
    PREFIX_NUMBERS = p.GetBool("ifcPrefixNumbers",False)
    SKIP = p.GetString("ifcSkip","")
    SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings",False)
    SCALE = p.GetFloat("IfcScalingFactor",1.0)

    if DEBUG: print "opening ",filename,"..."
    try:
        doc = FreeCAD.getDocument(docname)
    except:
        doc = FreeCAD.newDocument(docname)
    FreeCAD.ActiveDocument = doc
    
    global ifcfile # keeping global for debugging purposes
    ifcopenshell.clean()
    ifcfile = ifcopenshell.open(filename)
    shape_attributes = ifcopenshell.SEW_SHELLS
    if SEPARATE_OPENINGS: shape_attributes += ifcopenshell.DISABLE_OPENING_SUBTRACTIONS
    sites = ifcfile.by_type("IfcSite")
    buildings = ifcfile.by_type("IfcBuilding")
    floors = ifcfile.by_type("IfcBuildingStorey")
    products = ifcfile.by_type("IfcProduct")
    openings = ifcfile.by_type("IfcOpeningElement")

    # building relations tables
    objects = {} # { id:object, ... }
    additions = {} # { host:[child,...], ... }
    subtractions = [] # [ [opening,host], ... ]
    for r in ifcfile.by_type("IfcRelContainedInSpatialStructure"):
        additions.setdefault(r.RelatingStructure.id(),[]).extend([e.id() for e in r.RelatedElements])
    for r in ifcfile.by_type("IfcRelAggregates"):
        additions.setdefault(r.RelatingObject.id(),[]).extend([e.id() for e in r.RelatedObjects])
    for r in ifcfile.by_type("IfcRelVoidsElement"):
        subtractions.append([r.RelatedOpeningElement.id(), r.RelatingBuildingElement.id()])

    # products
    for product in products:
        pid = product.id()
        guid = product.GlobalId
        ptype = product.is_a()
        name = product.Name or str(ptype[3:])
        if PREFIX_NUMBERS: name = "ID" + str(pid) + " " + name
        obj = None
        baseobj = None
        
        if (ptype == "IfcOpeningElement") and (not SEPARATE_OPENINGS): continue
        if pid in skip: continue
        if ptype in SKIP: continue
        
        brep = ifcopenshell.create_shape(product,shape_attributes)
        if brep:
            shape = Part.Shape()
            shape.importBrepFromString(brep)
            if SCALE != 1:
                shape.scale(SCALE)
            if not shape.isNull():
                baseobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
                baseobj.Shape = shape
        for freecadtype,ifctypes in typesmap.iteritems():
            if ptype in ifctypes:
                obj = getattr(Arch,"make"+freecadtype)(baseobj=baseobj,name=name)
                obj.Label = name
                # setting uid
                if hasattr(obj,"IfcAttributes"):
                    a = obj.IfcAttributes
                    a["IfcUID"] = str(guid)
                    obj.IfcAttributes = a
                break
        if not obj:
            obj = baseobj
        if obj:
            sh = baseobj.Shape.ShapeType if hasattr(baseobj,"Shape") else "None"
            sols = str(baseobj.Shape.Solids) if hasattr(baseobj,"Shape") else ""
            if DEBUG: print "creating object ",pid," : ",ptype, " with shape: ",sh," ",sols
            objects[pid] = obj

    # subtractions
    if SEPARATE_OPENINGS:
        for subtraction in subtractions:
            if (subtraction[0] in objects.keys()) and (subtraction[1] in objects.keys()):
                    Arch.removeComponents(objects[subtraction[0]],objects[subtraction[1]])

    # additions
    for host,children in additions.iteritems():
        if host in objects.keys():
            cobs = [objects[child] for child in children if child in objects.keys()]
            if cobs:
                Arch.addComponents(cobs,objects[host])

    FreeCAD.ActiveDocument.recompute()
    
    # cleaning bad shapes
    for obj in objects.values():
        if obj.isDerivedFrom("Part::Feature"):
            if obj.Shape.isNull():
                Arch.rebuildArchShape(obj)
    FreeCAD.ActiveDocument.recompute()
    
    if FreeCAD.GuiUp:
        import FreeCADGui
        FreeCADGui.SendMsgToActiveView("ViewFit")
    return doc
예제 #5
0
def calculate_raumflaechen():

    # TODO fix ifc export of faces, to be able to export result to ifc

    import os

    import Arch
    import Part
    import Draft
    import FreeCAD

    mydoc = FreeCAD.ActiveDocument

    # the ifc container
    raumflaechen_site = Arch.makeSite([], name="ETH-Reihenhaus")
    raumflaechen_build = Arch.makeBuilding([], name="Reihenhaus_Raumflaechen")
    Arch.addComponents(raumflaechen_build, raumflaechen_site)
    textgrp = mydoc.addObject("App::DocumentObjectGroup", "Texte")

    # save the raumflaechen area
    areas = []

    #
    for o in mydoc.Objects:
        if hasattr(o, "IfcType") and o.IfcType == 'Space':
            print('We found the Space object: {}'.format(o.Label))
            sh = o.Shape
            if sh.ShapeType == 'Solid':
                for face in o.Shape.Faces:
                    # print('\n')
                    nv = face.normalAt(50, 50)  # normalen vector
                    # print(nv)
                    # Seitenflaeche, z-koord des normalen vektors is null
                    # if -0.001 < f.normalAt(50, 50).z < 0.001:  
                    # Bottomflaeche, z-koord des normalen vektors is -1 und x und y sind null
                    
                    if -0.001 < nv.x < 0.001 and -0.001 < nv.y < 0.001 and -1.001 < nv.z < -0.999:
                        print('Found Bottomflaeche')
                        raumflaeche_partobj = mydoc.addObject(
                            "Part::Feature", "Flaeche"
                        )
                        raumflaeche_partobj.Shape = face
                        raumflaeche_obj = Arch.makeComponent(
                            baseobj=raumflaeche_partobj,
                            name="Raumflaeche_" + o.Label
                        )
                        raumflaeche_obj.ViewObject.ShapeColor = (0.33 , 0.67 , 1.0 , 0.0)
                        Arch.addComponents(raumflaeche_obj, raumflaechen_build)
                        rf_name = raumflaeche_obj.Label
                        rf_area = round(raumflaeche_obj.Shape.Area * 1E-6, 2)  # TODO use unit system
                        rftext_vec = face.CenterOfMass + FreeCAD.Vector(0, 0, 10)  # to be above face
                        rftext_vec = rftext_vec + FreeCAD.Vector(-1000, 0, 0)  # haaack
                        rftext_obj = Draft.makeText(str(rf_area) + ' m2', rftext_vec)
                        rftext_obj.ViewObject.FontSize = 1000
                        textgrp.addObject(rftext_obj)
                        areas.append((rf_name, rf_area))

    mydoc.recompute()
    # print(areas)

    export_file = os.path.join(os.path.expanduser('~'), 'Desktop', 'raumflaechen')
    write_areas2csv(areas, export_file)
    write_areas2yaml(areas, export_file)

    return True
예제 #6
0
파일: importIFC.py 프로젝트: OLGGL/Model
def insert(filename,docname,skip=[]):
    "imports the contents of an IFC file"
    
    p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
    DEBUG = p.GetBool("ifcDebug",False)
    PREFIX_NUMBERS = p.GetBool("ifcPrefixNumbers",False)
    SKIP = p.GetString("ifcSkip","")
    SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings",False)
    
    try:
        import ifcopenshell
    except:
        FreeCAD.Console.PrintError("IfcOpenShell was not found on this system. IFC support is disabled\n")
        return

    if DEBUG: print "opening ",filename,"..."
    try:
        doc = FreeCAD.getDocument(docname)
    except:
        doc = FreeCAD.newDocument(docname)
    FreeCAD.ActiveDocument = doc
    
    global ifcfile # keeping global for debugging purposes
    if isinstance(filename,unicode): 
        import sys #workaround since ifcopenshell currently can't handle unicode filenames
        filename = filename.encode(sys.getfilesystemencoding())
    ifcfile = ifcopenshell.open(filename)
    from ifcopenshell import geom
    settings = ifcopenshell.geom.settings()
    settings.set(settings.USE_BREP_DATA,True)
    settings.set(settings.SEW_SHELLS,True)
    settings.set(settings.USE_WORLD_COORDS,True)
    if SEPARATE_OPENINGS: 
        settings.set(settings.DISABLE_OPENING_SUBTRACTIONS,True)
    sites = ifcfile.by_type("IfcSite")
    buildings = ifcfile.by_type("IfcBuilding")
    floors = ifcfile.by_type("IfcBuildingStorey")
    products = ifcfile.by_type("IfcProduct")
    openings = ifcfile.by_type("IfcOpeningElement")
    annotations = ifcfile.by_type("IfcAnnotation")

    # building relations tables
    objects = {} # { id:object, ... }
    additions = {} # { host:[child,...], ... }
    subtractions = [] # [ [opening,host], ... ]
    properties = {} # { host:[property, ...], ... }
    for r in ifcfile.by_type("IfcRelContainedInSpatialStructure"):
        additions.setdefault(r.RelatingStructure.id(),[]).extend([e.id() for e in r.RelatedElements])
    for r in ifcfile.by_type("IfcRelAggregates"):
        additions.setdefault(r.RelatingObject.id(),[]).extend([e.id() for e in r.RelatedObjects])
    for r in ifcfile.by_type("IfcRelVoidsElement"):
        subtractions.append([r.RelatedOpeningElement.id(), r.RelatingBuildingElement.id()])
    for r in ifcfile.by_type("IfcRelDefinesByProperties"):
        for obj in r.RelatedObjects:
            if r.RelatingPropertyDefinition.is_a("IfcPropertySet"):
                properties.setdefault(obj.id(),[]).extend([e.id() for e in r.RelatingPropertyDefinition.HasProperties])
    count = 0

    # products
    for product in products:
        pid = product.id()
        guid = product.GlobalId
        ptype = product.is_a()
        name = product.Name or str(ptype[3:])
        if PREFIX_NUMBERS: name = "ID" + str(pid) + " " + name
        obj = None
        baseobj = None
        brep = None
        
        if (ptype == "IfcOpeningElement") and (not SEPARATE_OPENINGS): continue
        if pid in skip: continue # user given id skip list
        if ptype in SKIP: continue # preferences-set type skip list
        try:
            cr = ifcopenshell.geom.create_shape(settings,product)
            brep = cr.geometry.brep_data
        except:
            pass
        if brep:
            shape = Part.Shape()
            shape.importBrepFromString(brep)
            shape.scale(1000.0) # IfcOpenShell always outputs in meters
            if not shape.isNull():
                baseobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
                baseobj.Shape = shape
        for freecadtype,ifctypes in typesmap.iteritems():
            if ptype in ifctypes:
                obj = getattr(Arch,"make"+freecadtype)(baseobj=baseobj,name=name)
                obj.Label = name
                # setting role
                try:
                    r = ptype[3:]
                    tr = dict((v,k) for k, v in translationtable.iteritems())
                    if r in tr.keys():
                        r = tr[r]
                    # remove the "StandardCase"
                    if "StandardCase" in r:
                        r = r[:-12]
                    obj.Role = r
                except:
                    pass
                # setting uid
                if hasattr(obj,"IfcAttributes"):
                    a = obj.IfcAttributes
                    a["IfcUID"] = str(guid)
                    obj.IfcAttributes = a
                break
        if not obj:
            obj = baseobj
        if obj:
            sh = baseobj.Shape.ShapeType if hasattr(baseobj,"Shape") else "None"
            sols = str(baseobj.Shape.Solids) if hasattr(baseobj,"Shape") else ""
            pc = str(int((float(count)/(len(products)+len(annotations))*100)))+"% "
            if DEBUG: print pc,"creating object ",pid," : ",ptype, " with shape: ",sh," ",sols
            objects[pid] = obj
            
        # properties
        if pid in properties:
            if hasattr(obj,"IfcAttributes"):
                a = obj.IfcAttributes
                for p in properties[pid]:
                    o = ifcfile[p]
                    if o.is_a("IfcPropertySingleValue"):
                        a[o.Name] = str(o.NominalValue)
                obj.IfcAttributes = a
        count += 1
        
    FreeCAD.ActiveDocument.recompute()
        
    if DEBUG: print "Processing relationships..."
            
    # subtractions
    if SEPARATE_OPENINGS:
        for subtraction in subtractions:
            if (subtraction[0] in objects.keys()) and (subtraction[1] in objects.keys()):
                #print objects[subtraction[0]].Name, objects[subtraction[1]].Name
                Arch.removeComponents(objects[subtraction[0]],objects[subtraction[1]])
                
    # additions
    for host,children in additions.iteritems():
        if host in objects.keys():
            cobs = [objects[child] for child in children if child in objects.keys()]
            if cobs:
                Arch.addComponents(cobs,objects[host])
                
    FreeCAD.ActiveDocument.recompute()
        
    # cleaning bad shapes
    for obj in objects.values():
        if obj.isDerivedFrom("Part::Feature"):
            if obj.Shape.isNull():
                Arch.rebuildArchShape(obj)
                
    FreeCAD.ActiveDocument.recompute()
    
    # 2D elements
    
    if DEBUG and annotations: print "Creating 2D geometry..."
    
    for annotation in annotations:
        aid = annotation.id()
        if aid in skip: continue # user given id skip list
        if "IfcAnnotation" in SKIP: continue # preferences-set type skip list
        name = "Annotation"
        if annotation.Name: name = annotation.Name
        if PREFIX_NUMBERS: name = "ID" + str(aid) + " " + name
        shapes2d = []
        for repres in annotation.Representation.Representations:
            shapes2d.extend(setRepresentation(repres))
        if shapes2d:
            sh = Part.makeCompound(shapes2d)
            pc = str(int((float(count)/(len(products)+len(annotations))*100)))+"% "
            if DEBUG: print pc,"creating object ",aid," : Annotation with shape: ",sh
            o = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
            o.Shape = sh
        count += 1
        
    FreeCAD.ActiveDocument.recompute()
    
    if FreeCAD.GuiUp:
        import FreeCADGui
        FreeCADGui.SendMsgToActiveView("ViewFit")
    return doc
예제 #7
0
def insert(filename,docname,skip=[],only=[],root=None):
    """insert(filename,docname,skip=[],only=[],root=None): imports the contents of an IFC file.
    skip can contain a list of ids of objects to be skipped, only can restrict the import to
    certain object ids (will also get their children) and root can be used to
    import only the derivates of a certain element type (default = ifcProduct)."""
    
    p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
    DEBUG = p.GetBool("ifcDebug",False)
    PREFIX_NUMBERS = p.GetBool("ifcPrefixNumbers",False)
    SKIP = p.GetString("ifcSkip","").split(",")
    SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings",False)
    ROOT_ELEMENT = p.GetString("ifcRootElement","IfcProduct")
    if root:
        ROOT_ELEMENT = root
    MERGE_MODE = p.GetInt("ifcImportMode",0)
    if MERGE_MODE > 0:
        SEPARATE_OPENINGS = False
    READ_COLORS = p.GetBool("ifcReadColors",True)
    if not SEPARATE_OPENINGS:
        SKIP.append("IfcOpeningElement")
    
    try:
        import ifcopenshell
    except:
        FreeCAD.Console.PrintError("IfcOpenShell was not found on this system. IFC support is disabled\n")
        return

    if DEBUG: print "Opening ",filename,"...",
    try:
        doc = FreeCAD.getDocument(docname)
    except:
        doc = FreeCAD.newDocument(docname)
    FreeCAD.ActiveDocument = doc
    
    if DEBUG: print "done."
    
    global ifcfile # keeping global for debugging purposes
    if isinstance(filename,unicode): 
        import sys #workaround since ifcopenshell currently can't handle unicode filenames
        filename = filename.encode(sys.getfilesystemencoding())
    ifcfile = ifcopenshell.open(filename)
    from ifcopenshell import geom
    settings = ifcopenshell.geom.settings()
    settings.set(settings.USE_BREP_DATA,True)
    settings.set(settings.SEW_SHELLS,True)
    settings.set(settings.USE_WORLD_COORDS,True)
    if SEPARATE_OPENINGS: 
        settings.set(settings.DISABLE_OPENING_SUBTRACTIONS,True)
    sites = ifcfile.by_type("IfcSite")
    buildings = ifcfile.by_type("IfcBuilding")
    floors = ifcfile.by_type("IfcBuildingStorey")
    products = ifcfile.by_type(ROOT_ELEMENT)
    openings = ifcfile.by_type("IfcOpeningElement")
    annotations = ifcfile.by_type("IfcAnnotation")
    
    if DEBUG: print "Building relationships table...",

    # building relations tables
    objects = {} # { id:object, ... }
    additions = {} # { host:[child,...], ... }
    subtractions = [] # [ [opening,host], ... ]
    properties = {} # { host:[property, ...], ... }
    colors = {} # { id:(r,g,b) }
    shapes = {} # { id:shaoe } only used for merge mode
    for r in ifcfile.by_type("IfcRelContainedInSpatialStructure"):
        additions.setdefault(r.RelatingStructure.id(),[]).extend([e.id() for e in r.RelatedElements])
    for r in ifcfile.by_type("IfcRelAggregates"):
        additions.setdefault(r.RelatingObject.id(),[]).extend([e.id() for e in r.RelatedObjects])
    for r in ifcfile.by_type("IfcRelVoidsElement"):
        subtractions.append([r.RelatedOpeningElement.id(), r.RelatingBuildingElement.id()])
    for r in ifcfile.by_type("IfcRelDefinesByProperties"):
        for obj in r.RelatedObjects:
            if r.RelatingPropertyDefinition.is_a("IfcPropertySet"):
                properties.setdefault(obj.id(),[]).extend([e.id() for e in r.RelatingPropertyDefinition.HasProperties])
    if READ_COLORS:
        for r in ifcfile.by_type("IfcStyledItem"):
            if r.Item and r.Styles[0].is_a("IfcPresentationStyleAssignment"):
                if r.Styles[0].Styles[0].is_a("IfcSurfaceStyle"):
                    if r.Styles[0].Styles[0].Styles[0].is_a("IfcSurfaceStyleRendering"):
                        if r.Styles[0].Styles[0].Styles[0].SurfaceColour:
                            c = r.Styles[0].Styles[0].Styles[0].SurfaceColour
                            for p in ifcfile.by_type("IfcProduct"):
                                if p.Representation:
                                    for it in p.Representation.Representations:
                                        if it.Items:
                                            if it.Items[0].id() == r.Item.id():
                                                colors[p.id()] = (c.Red,c.Green,c.Blue)
                                            elif it.Items[0].is_a("IfcBooleanResult"):
                                                if (it.Items[0].FirstOperand.id() == r.Item.id()):
                                                    colors[p.id()] = (c.Red,c.Green,c.Blue)
    if only: # only import a list of IDs and their children
        ids = []
        while only:
            currentid = only.pop()
            ids.append(currentid)
            if currentid in additions.keys():
                only.extend(additions[currentid])
        products = [ifcfile[currentid] for currentid in ids]
                    
    if DEBUG: print "done."
        
    count = 0
    from FreeCAD import Base
    progressbar = Base.ProgressIndicator()
    progressbar.start("Importing IFC objects...",len(products))

    # products
    for product in products:
                
        pid = product.id()
        guid = product.GlobalId
        ptype = product.is_a()
        if DEBUG: print count,"/",len(products)," creating object ",pid," : ",ptype,
        name = product.Name or str(ptype[3:])
        if PREFIX_NUMBERS: name = "ID" + str(pid) + " " + name
        obj = None
        baseobj = None
        brep = None

        if pid in skip: # user given id skip list
            if DEBUG: print " skipped."
            continue
        if ptype in SKIP: # preferences-set type skip list
            if DEBUG: print " skipped."
            continue
            
        try:
            cr = ifcopenshell.geom.create_shape(settings,product)
            brep = cr.geometry.brep_data
        except:
            pass # IfcOpenShell will yield an error if a given product has no shape, but we don't care
            
        if brep:
            if DEBUG: print " ",str(len(brep)/1000),"k ",
            
            shape = Part.Shape()
            shape.importBrepFromString(brep)
            
            shape.scale(1000.0) # IfcOpenShell always outputs in meters

            if not shape.isNull():
                if MERGE_MODE > 0:
                    if ptype == "IfcSpace": # do not add spaces to compounds
                        if DEBUG: print "skipping space ",pid
                    else:
                        shapes[pid] = shape
                        if DEBUG: print shape.Solids
                        baseobj = shape
                else:
                    baseobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
                    baseobj.Shape = shape
            else:
                if DEBUG: print  "null shape ",
            if not shape.isValid():
                if DEBUG: print "invalid shape. Skipping"
                continue
                
        else:
            if DEBUG: print " no brep "
            
        if MERGE_MODE == 0:
            
            # full Arch objects
            for freecadtype,ifctypes in typesmap.items():
                if ptype in ifctypes:
                    obj = getattr(Arch,"make"+freecadtype)(baseobj=baseobj,name=name)
                    obj.Label = name
                    # setting role
                    try:
                        r = ptype[3:]
                        tr = dict((v,k) for k, v in translationtable.iteritems())
                        if r in tr.keys():
                            r = tr[r]
                        # remove the "StandardCase"
                        if "StandardCase" in r:
                            r = r[:-12]
                        obj.Role = r
                    except:
                        pass
                    # setting uid
                    if hasattr(obj,"IfcAttributes"):
                        a = obj.IfcAttributes
                        a["IfcUID"] = str(guid)
                        obj.IfcAttributes = a
                    break
            if not obj:
                obj = baseobj
            if obj:
                sols = str(baseobj.Shape.Solids) if hasattr(baseobj,"Shape") else "[]"
                if DEBUG: print sols
                objects[pid] = obj
                        
        elif MERGE_MODE == 1:
            
            # non-parametric Arch objects
            if ptype in ["IfcSite","IfcBuilding","IfcBuildingStorey"]:
                for freecadtype,ifctypes in typesmap.items():
                    if ptype in ifctypes:
                        obj = getattr(Arch,"make"+freecadtype)(baseobj=None,name=name)
                        obj.Label = name
                        objects[pid] = obj
            elif baseobj:
                obj = Arch.makeComponent(baseobj,name=name)
                obj.Label = name
                objects[pid] = obj
                
        elif MERGE_MODE == 2:
            
            # Part shapes
            if ptype in ["IfcSite","IfcBuilding","IfcBuildingStorey"]:
                for freecadtype,ifctypes in typesmap.items():
                    if ptype in ifctypes:
                        obj = getattr(Arch,"make"+freecadtype)(baseobj=None,name=name)
                        obj.Label = name
                        objects[pid] = obj
            elif baseobj:
                obj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
                obj.Label = name
                obj.Shape = shape

                
        if obj:
            
            # properties
            if pid in properties:
                if hasattr(obj,"IfcAttributes"):
                    a = obj.IfcAttributes
                    for p in properties[pid]:
                        o = ifcfile[p]
                        if o.is_a("IfcPropertySingleValue"):
                            a[o.Name] = str(o.NominalValue)
                    obj.IfcAttributes = a
            
            # color
            if FreeCAD.GuiUp and (pid in colors):
                if DEBUG: print "    setting color: ",colors[pid]
                obj.ViewObject.ShapeColor = colors[pid]
        
            # if DEBUG is on, recompute after each shape
            if DEBUG: FreeCAD.ActiveDocument.recompute()
            
        count += 1
        progressbar.next()
    
    progressbar.stop()
    FreeCAD.ActiveDocument.recompute()
        
    if MERGE_MODE == 3:
        
        if DEBUG: print "Joining shapes..."
        
        for host,children in additions.items():
            if ifcfile[host].is_a("IfcBuildingStorey"):
                compound = []
                for c in children:
                    if c in shapes.keys():
                        compound.append(shapes[c])
                        del shapes[c]
                    if c in additions.keys():
                        for c2 in additions[c]:
                            if c2 in shapes.keys():
                                compound.append(shapes[c2])
                                del shapes[c2]
                if compound:
                    name = ifcfile[host].Name or "Floor"
                    if PREFIX_NUMBERS: name = "ID" + str(host) + " " + name
                    obj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
                    obj.Label = name
                    obj.Shape = Part.makeCompound(compound)
        if shapes: # remaining shapes
            obj = FreeCAD.ActiveDocument.addObject("Part::Feature","Unclaimed")
            obj.Shape = Part.makeCompound(shapes.values())
            
    else:
        
        if DEBUG: print "Processing relationships..."
        
        # subtractions
        if SEPARATE_OPENINGS:
            for subtraction in subtractions:
                if (subtraction[0] in objects.keys()) and (subtraction[1] in objects.keys()):
                    if DEBUG: print "subtracting ",objects[subtraction[0]].Name, " from ", objects[subtraction[1]].Name
                    Arch.removeComponents(objects[subtraction[0]],objects[subtraction[1]])
                    if DEBUG: FreeCAD.ActiveDocument.recompute()
                    
        # additions
        for host,children in additions.items():
            if host in objects.keys():
                cobs = [objects[child] for child in children if child in objects.keys()]
                if cobs:
                    if DEBUG and (len(cobs) > 10) and ( not(Draft.getType(objects[host]) in ["Site","Building","Floor"])):
                        # avoid huge fusions
                        print "more than 10 shapes to add: skipping."
                    else:
                        if DEBUG: print "adding ",cobs, " to ", objects[host].Name
                        Arch.addComponents(cobs,objects[host])
                        if DEBUG: FreeCAD.ActiveDocument.recompute()
                    
        FreeCAD.ActiveDocument.recompute()
        
        if DEBUG: print "Cleaning..."
            
        # cleaning bad shapes
        for obj in objects.values():
            if obj.isDerivedFrom("Part::Feature"):
                if obj.Shape.isNull():
                    Arch.rebuildArchShape(obj)
                
    FreeCAD.ActiveDocument.recompute()
    
    # 2D elements
    
    if DEBUG and annotations: print "Creating 2D geometry..."
    
    for annotation in annotations:
        aid = annotation.id()
        if aid in skip: continue # user given id skip list
        if "IfcAnnotation" in SKIP: continue # preferences-set type skip list
        name = "Annotation"
        if annotation.Name: name = annotation.Name
        if PREFIX_NUMBERS: name = "ID" + str(aid) + " " + name
        shapes2d = []
        for repres in annotation.Representation.Representations:
            shapes2d.extend(setRepresentation(repres))
        if shapes2d:
            sh = Part.makeCompound(shapes2d)
            pc = str(int((float(count)/(len(products)+len(annotations))*100)))+"% "
            if DEBUG: print pc,"creating object ",aid," : Annotation with shape: ",sh
            o = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
            o.Shape = sh
        count += 1
        
    FreeCAD.ActiveDocument.recompute()
        
    if FreeCAD.GuiUp:
        import FreeCADGui
        FreeCADGui.SendMsgToActiveView("ViewFit")
    print "Finished importing."
    return doc
haus_summe = haus_anzahl * (haus_b + trennwand_dicke)
reihenhaus_laenge = haus_summe - trennwand_dicke + 2 * seitenwand_dicke
hbase_x = base_x  # local x-base of every house, start with global x-base


# ***************************************************************************
# get doc name and export file name, create a new document
doc_name = os.path.splitext(os.path.basename(str(__file__)))[0]
export_file = os.path.join(os.path.expanduser('~'), 'Desktop', doc_name)
doc_obj = FreeCAD.newDocument(doc_name)

# the container
site = Arch.makeSite([], name="ETH-Reihenhaus")
raeume_site = Arch.makeSite([], name="ETH-Reihenhaus")
raeume_building = Arch.makeBuilding([], name="Reihenhaus_Raeume")
Arch.addComponents(raeume_building, raeume_site)

# the materials, windows, doors and spaces do not get a material
brick = Arch.makeMaterial('Backstein')
concrete = Arch.makeMaterial('Beton')
brick.Color = (1.0, 0.502, 0.0, 0.0)
concrete.Color = (0.439, 1.0, 0.439, 0.0)

# ***************************************************************************
# lets start with geometry creation

# *******************************************
# bodenplatte
bpl_place = FreeCAD.Placement(
    vec(base_x-seitenwand_dicke, base_y, eg_boden_roh),
    FreeCAD.Rotation(vec(0, 0, 1), 0)