예제 #1
0
def test_sub_faces_invalid_face_type():
    """Test the adding of a sub-face to a face with invalid face type."""
    face_face3d = Face3D.from_rectangle(10, 10, Plane(o=Point3D(0, 0, 3)))
    ap_face3d = Face3D.from_rectangle(2, 2, Plane(o=Point3D(2, 2, 3)))
    dr_face3d = Face3D.from_rectangle(2, 2, Plane(o=Point3D(7, 7, 3)))

    face = Face('Test_Roof', face_face3d, face_types.air_wall)
    aperture = Aperture('Test_Skylight', ap_face3d)
    door = Door('Test_Trap_Door', dr_face3d)

    with pytest.raises(AssertionError):
        face.add_aperture(aperture)
    with pytest.raises(AssertionError):
        face.add_door(door)
예제 #2
0
def test_add_remove_aperture():
    """Test the adding and removing of an aperture to a Face."""
    face_face3d = Face3D.from_rectangle(10, 10, Plane(o=Point3D(0, 0, 3)))
    ap_face3d = Face3D.from_rectangle(2, 2, Plane(o=Point3D(2, 2, 3)))
    face = Face('Test_Roof', face_face3d)
    aperture = Aperture('Test_Skylight', ap_face3d)
    face.add_aperture(aperture)

    assert len(face.apertures) == 1
    assert len(face.apertures[0].geometry.vertices) == 4
    assert face.apertures[0].area == pytest.approx(4, rel=1e-2)
    assert face.apertures[0].parent is face
    assert len(face.punched_vertices) == 10
    assert face.punched_geometry.area == 96
    assert face.check_apertures_valid(0.01, 1)

    face.remove_apertures()
    assert len(face.apertures) == 0
    assert len(face.punched_vertices) == 4
    assert face.punched_geometry.area == 100
예제 #3
0
def test_sub_faces_invalid():
    """Test the adding and removing of invalid sub-faces."""
    face_face3d = Face3D.from_rectangle(10, 10, Plane(o=Point3D(0, 0, 3)))
    ap_face3d = Face3D.from_rectangle(2, 2, Plane(o=Point3D(2, 2, 3)))
    dr_face3d = Face3D.from_rectangle(2, 2, Plane(o=Point3D(7, 7, 3)))
    dr_face3d_invalid_1 = Face3D.from_rectangle(2, 2,
                                                Plane(o=Point3D(7, 7, 1)))
    dr_face3d_invalid_2 = \
        Face3D([Point3D(0, 0, 0), Point3D(0, 1, 0), Point3D(0, 1, 3), Point3D(0, 0, 3)])

    face = Face('Test_Roof', face_face3d)
    aperture = Aperture('Test_Skylight', ap_face3d)
    door = Door('Test_Trap_Door', dr_face3d)
    invalid_aperture_1 = Aperture('Test_Skylight', dr_face3d_invalid_1)
    invalid_aperture_2 = Aperture('Test_Skylight', dr_face3d_invalid_2)

    with pytest.raises(AssertionError):
        face.add_aperture(door)
    with pytest.raises(AssertionError):
        face.add_door(aperture)

    face.add_aperture(invalid_aperture_1)
    with pytest.raises(ValueError):
        face.check_apertures_valid(0.01, 1)
    face.remove_apertures()

    face.add_aperture(invalid_aperture_2)
    with pytest.raises(ValueError):
        face.check_apertures_valid(0.01, 1)
예제 #4
0
def test_add_remove_sub_faces():
    """Test the adding and removing of an aperture and a door to a Face."""
    face_face3d = Face3D.from_rectangle(10, 10, Plane(o=Point3D(0, 0, 3)))
    ap_face3d = Face3D.from_rectangle(2, 2, Plane(o=Point3D(2, 2, 3)))
    dr_face3d = Face3D.from_rectangle(2, 2, Plane(o=Point3D(7, 7, 3)))
    face = Face('Test_Roof', face_face3d)
    aperture = Aperture('Test_Skylight', ap_face3d)
    door = Door('Test_Trap_Door', dr_face3d)
    face.add_aperture(aperture)
    face.add_door(door)

    assert len(face.apertures) == 1
    assert len(face.doors) == 1
    assert face.apertures[0].parent is face
    assert face.doors[0].parent is face
    assert len(face.punched_vertices) == 16
    assert face.punched_geometry.area == 92
    assert face.check_sub_faces_valid(0.01, 1)

    face.remove_sub_faces()
    assert len(face.apertures) == 0
    assert len(face.punched_vertices) == 4
    assert face.punched_geometry.area == 100
예제 #5
0
def test_face_add_prefix():
    """Test the face add_prefix method."""
    face_face3d = Face3D.from_rectangle(10, 10, Plane(o=Point3D(0, 0, 3)))
    ap_face3d = Face3D.from_rectangle(2, 2, Plane(o=Point3D(2, 2, 3)))
    face = Face('Test_Roof', face_face3d)
    aperture = Aperture('Test_Skylight', ap_face3d)
    face.add_aperture(aperture)
    prefix = 'New'
    face.add_prefix(prefix)

    assert face.identifier.startswith(prefix)
    for ap in face.apertures:
        assert ap.identifier.startswith(prefix)

    face_face3d = Face3D.from_rectangle(10, 10, Plane(o=Point3D(0, 0, 3)))
    ap_face3d = Face3D.from_rectangle(2, 2, Plane(o=Point3D(2, 2, 3)))
    face = Face('Test_Roof', face_face3d)
    door = Door('Test_Trap_Door', ap_face3d)
    face.add_door(door)
    face.add_prefix(prefix)

    for dr in face.doors:
        assert dr.identifier.startswith(prefix)
예제 #6
0
  def process(self):
    if not any(socket.is_linked for socket in self.outputs):
      return

    ifc_files = self.inputs['IFC'].sv_get(deepcopy=False)[0]
    offsets = self.inputs['Offset'].sv_get(deepcopy=False)[0]
    file_paths = self.inputs['File path'].sv_get(deepcopy=False)[0]

    hbjsons = []
    for idx, ifc_file in enumerate(ifc_files):
      file_path = file_paths[idx]
      offset = offsets[idx]

      unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
      id2hb = {}
      hb_model = Model("Model")

      for ifc_material_layer in ifc_file.by_type('IfcMaterialLayer'):
        if not ifc_material_layer.ToMaterialLayerSet:
          continue

        material_id = ifc_material_layer.id()
        thickness = float(ifc_material_layer.LayerThickness)
        hb_material = EnergyMaterial(str(material_id), thickness, 0.1, 0.1, 1400)
        hb_material.display_name = ifc_material_layer.Material.Name + " - " + str(ifc_material_layer.LayerThickness)
        id2hb[material_id] = hb_material

      for ifc_material_layer_set in ifc_file.by_type('IfcMaterialLayerSet'):
        construction_id = ifc_material_layer_set.id()
        layers = [ id2hb[ifc_material_layer.id()] for ifc_material_layer in ifc_material_layer_set.MaterialLayers ]
        hb_construction = OpaqueConstruction(str(construction_id), layers)
        hb_construction.display_name = ifc_material_layer_set.LayerSetName
        id2hb[construction_id] = hb_construction

      for ifc_building_storey in ifc_file.by_type('IfcBuildingStorey'):
        if not ifc_building_storey.IsDecomposedBy:
          continue

        ifc_spaces = [ x for x in ifc_building_storey.IsDecomposedBy[0].RelatedObjects if x.is_a("IfcSpace") ]
        if not ifc_spaces:
          continue

        for ifc_space in ifc_spaces:
          space_matrix = ifcopenshell.util.placement.get_local_placement(ifc_space.ObjectPlacement)
          space_matrix[:3,3] *= unit_scale

          faces = []
          for ifc_rel_space_boundary in ifc_space.BoundedBy:
            if ifc_rel_space_boundary.ParentBoundary is not None:
              continue

            surface_id = ifc_rel_space_boundary.id()
            vertices = [ (space_matrix @ np.append(v,1))[:-1] for v in ifc_topologic.getLocalVertices(ifc_rel_space_boundary, unit_scale, 0.0) ]
            geom = Face3D([ Point3D.from_array(v) for v in vertices ])
            hb_face = Face(str(surface_id), geom)
            hb_face.display_name = ifc_rel_space_boundary.Name

            ifc_building_element = ifc_rel_space_boundary.RelatedBuildingElement
            if ifc_building_element is not None:
              for ifc_rel_associates in ifc_building_element.HasAssociations:
                if not ifc_rel_associates.is_a("IfcRelAssociatesMaterial"):
                  continue

                ifc_material = ifc_rel_associates.RelatingMaterial
                if ifc_material.is_a('IfcMaterialLayerSetUsage'):
                  ifc_material = ifc_material.ForLayerSet
                elif not ifc_material.is_a('IfcMaterialLayerSet'):
                  continue

                hb_face.properties.energy.construction = id2hb[ifc_material.id()]
                break

            for ifc_inner_boundary in ifc_rel_space_boundary.InnerBoundaries:
              if ifc_inner_boundary.ParentBoundary != ifc_rel_space_boundary:
                continue

              sub_surface_id = ifc_inner_boundary.id()
              name = ifc_inner_boundary.Name
              vertices = [ (space_matrix @ np.append(v,1))[:-1] for v in ifc_topologic.getLocalVertices(ifc_inner_boundary, unit_scale, offset) ]
              geom = Face3D([ Point3D.from_array(v) for v in vertices ])
              if ifc_inner_boundary.RelatedBuildingElement.is_a("IfcWindow"):
                hb_aperture = Aperture(str(sub_surface_id), geom)
                hb_face.add_aperture(hb_aperture)
                id2hb[sub_surface_id] = hb_aperture
              elif ifc_inner_boundary.RelatedBuildingElement.is_a("IfcDoor"):
                hb_door = Door(str(sub_surface_id), geom)
                hb_face.add_door(hb_door)
                id2hb[sub_surface_id] = hb_door
              id2hb[sub_surface_id].display_name = ifc_inner_boundary.Name

            faces.append(hb_face)
            id2hb[surface_id] = hb_face

          space_id = ifc_space.id()
          hb_room = Room(str(space_id), faces)
          hb_room.display_name = ifc_space.Name
          hb_room.story = ifc_building_storey.Name

          for hb_face in hb_room.faces:
            ifc_rel_space_boundary = ifc_file.by_id(int(hb_face.identifier))

            if ifc_rel_space_boundary.CorrespondingBoundary is None:
              if ifc_rel_space_boundary.Description == "2a":
                hb_face.boundary_condition = boundary_conditions.outdoors
              elif ifc_rel_space_boundary.Description == "2b":
                hb_face.boundary_condition = boundary_conditions.adiabatic
            else:
              adjacent_surface_id = ifc_rel_space_boundary.CorrespondingBoundary.id()
              if adjacent_surface_id in id2hb:
                hb_face.boundary_condition = boundary_conditions.surface(id2hb[adjacent_surface_id])
                id2hb[adjacent_surface_id].boundary_condition = boundary_conditions.surface(hb_face)

                for ifc_inner_boundary in ifc_rel_space_boundary.InnerBoundaries:
                  if ifc_inner_boundary.ParentBoundary != ifc_rel_space_boundary:
                    continue

                  hb_sub_surface = id2hb[ifc_inner_boundary.id()]
                  hb_adjacent_sub_surface = id2hb[ifc_inner_boundary.CorrespondingBoundary.id()]
                  hb_sub_surface.boundary_condition = boundary_conditions.surface(hb_adjacent_sub_surface, True)
                  hb_adjacent_sub_surface.boundary_condition = boundary_conditions.surface(hb_sub_surface, True)
              else:
                hb_face.boundary_condition = boundary_conditions.outdoors

          hb_model.add_room(hb_room)

      f = open(file_path, "w")
      json.dump(hb_model.to_dict(), f, indent=4)
      f.close()

      hbjsons.append(hb_model)

    self.outputs['HBJSON'].sv_set([hbjsons])
예제 #7
0
def processItem(item):
    osModel = item[0]
    weatherFilePath = item[1]
    designDayFilePath = item[2]
    tpBuilding = item[3]
    tpShadingSurfacesCluster = item[4]
    floorLevels = item[5]
    buildingName = item[6]
    buildingType = item[7]
    defaultSpaceType = item[8]
    northAxis = item[9]
    glazingRatio = item[10]
    coolingTemp = item[11]
    heatingTemp = item[12]

    rooms = []
    tpCells = []
    _ = tpBuilding.Cells(None, tpCells)
    # Sort cells by Z Levels
    tpCells.sort(key=lambda c: c.CenterOfMass().Z(), reverse=False)
    for spaceNumber, tpCell in enumerate(tpCells):
        tpDictionary = tpCell.GetDictionary()
        tpCellName = None
        tpCellStory = None
        if tpDictionary:
            tpCellName = valueAtKey(tpDictionary, 'name')
            tpCellStory = valueAtKey(tpDictionary, 'story')
        tpCellFaces = []
        _ = tpCell.Faces(None, tpCellFaces)
        if tpCellFaces:
            hbRoomFaces = []
            for tpFaceNumber, tpCellFace in enumerate(tpCellFaces):
                hbRoomFacePoints = []
                tpFaceVertices = []
                _ = tpCellFace.ExternalBoundary().Vertices(
                    None, tpFaceVertices)
                for tpVertex in tpFaceVertices:
                    hbRoomFacePoints.append(
                        Point3D(tpVertex.X(), tpVertex.Y(), tpVertex.Z()))
                hbRoomFace = Face(
                    tpCellName + '_Face_' + str(tpFaceNumber + 1),
                    Face3D(hbRoomFacePoints))
                faceNormal = topologic.FaceUtility.NormalAtParameters(
                    tpFace, 0.5, 0.5)
                ang = math.degrees(math.acos(faceNormal.dot([0, 0, 1])))
                print("HBJSONByTopology: Angle between face normal and UP",
                      ang)
                if ang > 175:
                    hbRoomFace.type = "floor"
                tpFaceApertures = []
                _ = tpCellFace.Apertures(tpFaceApertures)
                if tpFaceApertures:
                    for tpFaceApertureNumber, tpFaceAperture in enumerate(
                            tpFaceApertures):
                        apertureTopology = topologic.Aperture.Topology(
                            tpFaceAperture)
                        tpFaceApertureDictionary = apertureTopology.GetDictionary(
                        )
                        if tpFaceApertureDictionary:
                            tpFaceApertureType = valueAtKey(
                                tpFaceApertureDictionary, 'type')
                        hbFaceAperturePoints = []
                        tpFaceApertureVertices = []
                        _ = apertureTopology.ExternalBoundary().Vertices(
                            None, tpFaceApertureVertices)
                        for tpFaceApertureVertex in tpFaceApertureVertices:
                            hbFaceAperturePoints.append(
                                Point3D(tpFaceApertureVertex.X(),
                                        tpFaceApertureVertex.Y(),
                                        tpFaceApertureVertex.Z()))
                        if (tpFaceApertureType):
                            if ("door" in tpFaceApertureType.lower()):
                                hbFaceAperture = Door(
                                    tpCellName + '_Face_' +
                                    str(tpFaceNumber + 1) + '_Door_' +
                                    str(tpFaceApertureNumber),
                                    Face3D(hbFaceAperturePoints))
                            else:
                                hbFaceAperture = Aperture(
                                    tpCellName + '_Face_' +
                                    str(tpFaceNumber + 1) + '_Window_' +
                                    str(tpFaceApertureNumber),
                                    Face3D(hbFaceAperturePoints))
                        else:
                            hbFaceAperture = Aperture(
                                tpCellName + '_Face_' + str(tpFaceNumber + 1) +
                                '_Window_' + str(tpFaceApertureNumber),
                                Face3D(hbFaceAperturePoints))
                        hbRoomFace.add_aperture(hbFaceAperture)
                hbRoomFaces.append(hbRoomFace)
            if tpCellName == None:
                tpCellName = "GENERICROOM_" + (str(spaceNumber + 1))
            room = Room(tpCellName, hbRoomFaces, 0.01,
                        1)  #ToDo: Figure out how to add Story number
            heat_setpt = ScheduleRuleset.from_constant_value(
                'Room Heating', heatingTemp, schedule_types.temperature)
            cool_setpt = ScheduleRuleset.from_constant_value(
                'Room Cooling', coolingTemp, schedule_types.temperature)
            humidify_setpt = ScheduleRuleset.from_constant_value(
                'Room Humidifying', 30,
                schedule_types.humidity)  #Todo: Remove hardwired number
            dehumidify_setpt = ScheduleRuleset.from_constant_value(
                'Room Dehumidifying', 55,
                schedule_types.humidity)  #Todo: Remove hardwired number
            setpoint = Setpoint('Room Setpoint', heat_setpt, cool_setpt,
                                humidify_setpt, dehumidify_setpt)
            simple_office = ScheduleDay(
                'Simple Weekday', [0, 1, 0],
                [Time(0, 0), Time(9, 0), Time(17, 0)])
            schedule = ScheduleRuleset('Office Water Use', simple_office, None,
                                       schedule_types.fractional)
            shw = ServiceHotWater('Office Hot Water', 0.1, schedule)
            room.properties.energy.program_type = prog_type_lib.office_program  #Default Office Program
            room.properties.energy.add_default_ideal_air()  #Ideal Air Exchange
            room.properties.energy.setpoint = setpoint  #Heating/Cooling/Humidifying/Dehumidifying
            room.properties.energy.service_hot_water = shw  #Service Hot Water
            if tpCellStory:
                room.story = tpCellStory
            rooms.append(room)
    Room.solve_adjacency(rooms, 0.01)
    Room.stories_by_floor_height(rooms, min_difference=2.0)

    hbShades = []
    shadingFaces = []
    _ = tpShadingSurfacesCluster.Faces(None, shadingFaces)
    for faceIndex, shadingFace in enumerate(shadingFaces):
        faceVertices = []
        _ = shadingFace.ExternalBoundary().Vertices(None, faceVertices)
        facePoints = []
        for aVertex in faceVertices:
            facePoints.append(Point3D(aVertex.X(), aVertex.Y(), aVertex.Z()))
        hbShadingFace = Face3D(facePoints, None, [])
        hbShade = Shade("SHADINGSURFACE_" + str(faceIndex), hbShadingFace)
        hbShades.append(hbShade)
    model = Model('TopologicModel', rooms, orphaned_shades=hbShades)
    return model.to_dict()
def processItem(item):
    tpBuilding = item[0]
    tpShadingFacesCluster = item[1]
    buildingName = item[2]
    defaultProgramIdentifier = item[3]
    defaultConstructionSetIdentifier = item[4]
    coolingSetpoint = item[5]
    heatingSetpoint = item[6]
    humidifyingSetpoint = item[7]
    dehumidifyingSetpoint = item[8]
    roomNameKey = item[9]
    roomTypeKey = item[10]
    if buildingName:
        buildingName = buildingName.replace(" ","_")
    else:
        buildingName = "GENERICBUILDING"
    rooms = []
    tpCells = []
    _ = tpBuilding.Cells(None, tpCells)
    # Sort cells by Z Levels
    tpCells.sort(key=lambda c: cellFloor(c), reverse=False)
    fl = floorLevels(tpCells, 2)
    spaceNames = []
    for spaceNumber, tpCell in enumerate(tpCells):
        tpDictionary = tpCell.GetDictionary()
        tpCellName = None
        tpCellStory = None
        tpCellProgramIdentifier = None
        tpCellConstructionSetIdentifier = None
        tpCellConditioned = True
        if tpDictionary:
            keyName = getKeyName(tpDictionary, 'Story')
            tpCellStory = DictionaryValueAtKey.processItem(tpDictionary, keyName)
            if tpCellStory:
                tpCellStory = tpCellStory.replace(" ","_")
            else:
                tpCellStory = fl[spaceNumber]
            if roomNameKey:
                keyName = getKeyName(tpDictionary, roomNameKey)
            else:
                keyName = getKeyName(tpDictionary, 'Name')
            tpCellName = DictionaryValueAtKey.processItem(tpDictionary,keyName)
            if tpCellName:
                tpCellName = createUniqueName(tpCellName.replace(" ","_"), spaceNames, 1)
            else:
                tpCellName = tpCellStory+"_SPACE_"+(str(spaceNumber+1))
            if roomTypeKey:
                keyName = getKeyName(tpDictionary, roomTypeKey)
            else:
                keyName = getKeyName(tpDictionary, 'Program')
            tpCellProgramIdentifier = DictionaryValueAtKey.processItem(tpDictionary, keyName)
            if tpCellProgramIdentifier:
                program = prog_type_lib.program_type_by_identifier(tpCellProgramIdentifier)
            elif defaultProgramIdentifier:
                program = prog_type_lib.program_type_by_identifier(defaultProgramIdentifier)
            else:
                program = prog_type_lib.office_program #Default Office Program as a last resort
            keyName = getKeyName(tpDictionary, 'construction_set')
            tpCellConstructionSetIdentifier = DictionaryValueAtKey.processItem(tpDictionary, keyName)
            if tpCellConstructionSetIdentifier:
                constr_set = constr_set_lib.construction_set_by_identifier(tpCellConstructionSetIdentifier)
            elif defaultConstructionSetIdentifier:
                constr_set = constr_set_lib.construction_set_by_identifier(defaultConstructionSetIdentifier)
            else:
                constr_set = constr_set_lib.construction_set_by_identifier("Default Generic Construction Set")
        else:
            tpCellStory = fl[spaceNumber]
            tpCellName = tpCellStory+"_SPACE_"+(str(spaceNumber+1))
            program = prog_type_lib.office_program
            constr_set = constr_set_lib.construction_set_by_identifier("Default Generic Construction Set")
        spaceNames.append(tpCellName)

        tpCellFaces = []
        _ = tpCell.Faces(None, tpCellFaces)
        if tpCellFaces:
            hbRoomFaces = []
            for tpFaceNumber, tpCellFace in enumerate(tpCellFaces):
                tpCellFaceNormal = topologic.FaceUtility.NormalAtParameters(tpCellFace, 0.5, 0.5)
                hbRoomFacePoints = []
                tpFaceVertices = []
                _ = tpCellFace.ExternalBoundary().Vertices(None, tpFaceVertices)
                for tpVertex in tpFaceVertices:
                    hbRoomFacePoints.append(Point3D(tpVertex.X(), tpVertex.Y(), tpVertex.Z()))
                hbRoomFace = Face(tpCellName+'_Face_'+str(tpFaceNumber+1), Face3D(hbRoomFacePoints))
                tpFaceApertures = []
                _ = tpCellFace.Apertures(tpFaceApertures)
                if tpFaceApertures:
                    for tpFaceApertureNumber, tpFaceAperture in enumerate(tpFaceApertures):
                        apertureTopology = topologic.Aperture.Topology(tpFaceAperture)
                        tpFaceApertureDictionary = apertureTopology.GetDictionary()
                        if tpFaceApertureDictionary:
                            tpFaceApertureType = DictionaryValueAtKey.processItem(tpFaceApertureDictionary,'type')
                        hbFaceAperturePoints = []
                        tpFaceApertureVertices = []
                        _ = apertureTopology.ExternalBoundary().Vertices(None, tpFaceApertureVertices)
                        for tpFaceApertureVertex in tpFaceApertureVertices:
                            hbFaceAperturePoints.append(Point3D(tpFaceApertureVertex.X(), tpFaceApertureVertex.Y(), tpFaceApertureVertex.Z()))
                        if(tpFaceApertureType):
                            if ("door" in tpFaceApertureType.lower()):
                                hbFaceAperture = Door(tpCellName+'_Face_'+str(tpFaceNumber+1)+'_Door_'+str(tpFaceApertureNumber), Face3D(hbFaceAperturePoints))
                            else:
                                hbFaceAperture = Aperture(tpCellName+'_Face_'+str(tpFaceNumber+1)+'_Window_'+str(tpFaceApertureNumber), Face3D(hbFaceAperturePoints))
                        else:
                            hbFaceAperture = Aperture(tpCellName+'_Face_'+str(tpFaceNumber+1)+'_Window_'+str(tpFaceApertureNumber), Face3D(hbFaceAperturePoints))
                        hbRoomFace.add_aperture(hbFaceAperture)
                else:
                    tpFaceDictionary = tpCellFace.GetDictionary()
                    if (abs(tpCellFaceNormal[2]) < 1e-6) and tpFaceDictionary: #It is a mostly vertical wall and has a dictionary
                        apertureRatio = DictionaryValueAtKey.processItem(tpFaceDictionary,'apertureRatio')
                        if apertureRatio:
                            hbRoomFace.apertures_by_ratio(apertureRatio, tolerance=0.01)
                fType = honeybee.facetype.get_type_from_normal(Vector3D(tpCellFaceNormal[0],tpCellFaceNormal[1],tpCellFaceNormal[2]), roof_angle=30, floor_angle=150)
                hbRoomFace.type = fType
                hbRoomFaces.append(hbRoomFace)
            room = Room(tpCellName, hbRoomFaces, 0.01, 1)
            heat_setpt = ScheduleRuleset.from_constant_value('Room Heating', heatingSetpoint, schedule_types.temperature)
            cool_setpt = ScheduleRuleset.from_constant_value('Room Cooling', coolingSetpoint, schedule_types.temperature)
            humidify_setpt = ScheduleRuleset.from_constant_value('Room Humidifying', humidifyingSetpoint, schedule_types.humidity)
            dehumidify_setpt = ScheduleRuleset.from_constant_value('Room Dehumidifying', dehumidifyingSetpoint, schedule_types.humidity)
            setpoint = Setpoint('Room Setpoint', heat_setpt, cool_setpt, humidify_setpt, dehumidify_setpt)
            simple_office = ScheduleDay('Simple Weekday', [0, 1, 0], [Time(0, 0), Time(9, 0), Time(17, 0)]) #Todo: Remove hardwired scheduleday
            schedule = ScheduleRuleset('Office Water Use', simple_office, None, schedule_types.fractional) #Todo: Remove hardwired schedule
            shw = ServiceHotWater('Office Hot Water', 0.1, schedule) #Todo: Remove hardwired schedule hot water
            room.properties.energy.program_type = program
            room.properties.energy.construction_set = constr_set
            room.properties.energy.add_default_ideal_air() #Ideal Air Exchange
            room.properties.energy.setpoint = setpoint #Heating/Cooling/Humidifying/Dehumidifying
            room.properties.energy.service_hot_water = shw #Service Hot Water
            if tpCellStory:
                room.story = tpCellStory
            rooms.append(room)
    Room.solve_adjacency(rooms, 0.01)
    #for room in rooms:
        #room.properties.energy.construction_set = constr_set
    #Room.stories_by_floor_height(rooms, min_difference=2.0)

    if(tpShadingFacesCluster):
        hbShades = []
        tpShadingFaces = []
        _ = tpShadingFacesCluster.Faces(None, tpShadingFaces)
        for faceIndex, tpShadingFace in enumerate(tpShadingFaces):
            faceVertices = []
            _ = tpShadingFace.ExternalBoundary().Vertices(None, faceVertices)
            facePoints = []
            for aVertex in faceVertices:
                facePoints.append(Point3D(aVertex.X(), aVertex.Y(), aVertex.Z()))
            hbShadingFace = Face3D(facePoints, None, [])
            hbShade = Shade("SHADINGSURFACE_" + str(faceIndex+1), hbShadingFace)
            hbShades.append(hbShade)
    model = Model(buildingName, rooms, orphaned_shades=hbShades)
    return model