Source code for dragonfly_doe2.doe.floor_space

from dragonfly.room2d import Room2D
from dragonfly.story import Story
from dataclasses import dataclass
from typing import List
from .utils import short_name, lower_left_properties
from dragonfly.windowparameter import RectangularWindows
from honeybee_energy.construction.window import WindowConstruction


[docs]@dataclass class Slab: """Object for 'floor' surface. Init method(s): 1. from_room(name, construction, type_adjacency). note: temp naming conv: intent is for at space class level to check if is_ground_contact == True; do SpaceFloor init. Args: name: space name. (is joined with _floor_{n}). construction: display_name of the floor's construction type_adjacency: for now 'BOTTOM' only. Example: .. code-block:: f# "Flr (G.1.U1)" = UNDERGROUND-WALL CONSTRUCTION = "UFCons (G.1.U2)" LOCATION = BOTTOM .. """ name: str construction: str type_adjacency: str = 'BOTTOM'
[docs] @classmethod def from_room( cls, name: str, construction: str, type_adjacency: str = 'BOTTOM'): return cls(name=name, construction=construction, type_adjacency=type_adjacency)
[docs] def to_inp(self): return f'"{self.name}_grnd_flr" = UNDERGROUND-WALL\n' \ f' CONSTRUCTION = "{self.construction}_c"\n' \ f' LOCATION = {self.type_adjacency}\n ..'
def __repr__(self) -> str: return self.to_inp()
[docs]@dataclass class RoofCeiling: # TODO: Need to add "what's on the other side" for interior adj ceilings. # TODO: refer to df intesect/solve adj's adj info # ! Currently will only provide exterior roof for roofs with no internal adj's # ? if not needed full interior detailing: Need to add to solve adj: story<->story solve adj """Object for roof/ceiling inputs. Init method(s): 1. from_room(name, construction, type_adjacency, next_to=None) Args: name: space name. (is joind with _roof_{n}). construction: display_name of roof_ceiling's constr. next_to: *optional* WIP for interior ceilings adjacent space ID#!WIP Example: .. code-block:: f# "Roof (G.2.E9)" = EXTERIOR-WALL CONSTRUCTION = "Roof Construction" LOCATION = TOP .. "Ceiling (G.1.I1)" = INTERIOR-WALL NEXT-TO = "Plnm (G.2)" CONSTRUCTION = "Ceilg Construction" LOCATION = TOP .. """ name: str construction: str next_to: str = None
[docs] @classmethod def from_room(cls, room: Room2D): name = room.display_name construction = room.properties.energy.construction_set.roof_ceiling_set.exterior_construction.display_name return cls(name, construction)
[docs] def to_inp(self): return f'"{self.name}_roof" = EXTERIOR-WALL\n' \ f' CONSTRUCTION = "{self.construction}_c"\n' \ f' LOCATION = TOP\n ..'
def __repr__(self) -> str: return self.to_inp()
[docs]@dataclass class Window: """*.inp Window object. Args: name: display name of the room2d, to be added to, creating a unique displayname. location: the index/n of the window in the set of windows hosted by the wall segment. x: window origin pt.x coord. y: window origin pt.y coord. width: window width. height: window height. Example: .. code-block:: f# rmOne_wndw_0_wall1 = WINDOW X = 0.6830601092896195 Y = 2.6229508196721314 WIDTH = 9.562841530054643 HEIGHT = 6.557377049180327 GLASS-TYPE = WT1 .. """ name: str location: int x: float y: float width: float height: float glass_type: str
[docs] def to_inp(self): shortened_name = short_name(f'{self.name}_w{self.location}', 32) return f'"{shortened_name}" = WINDOW\n ' \ f'X = {self.x}\n ' \ f'Y = {self.y}\n ' \ f'WIDTH = {self.width}\n ' \ f'HEIGHT = {self.height}\n '\ f'GLASS-TYPE = "{short_name(self.glass_type, 32)}"\n ..\n'
def __repr__(self) -> str: return self.to_inp()
[docs]@dataclass class WindowSet: """ An internal object comprising all of the windows hosted by a wall segment. Init methods(s): from_params(name, location, rectangular_window_params). Args: name: the display name of the room2d hosting the wall the windowset belongs to. location: the index of the room2D's wall segment hosting the window set. for use on creating unique identifier name for each window. windows: list of Window objects comprising the window set. """ name: str location: int windows: List[Window] glass_type: None
[docs] @classmethod def from_params(cls, name: str, location: int, rectangular_window_params: list, glass_type): origins = [(orig.x, orig.y) for orig in rectangular_window_params.origins] widths = rectangular_window_params.widths heights = rectangular_window_params.heights glass_type = short_name(glass_type, 32) windows = [] for i, (org, w, h) in enumerate(zip(origins, widths, heights)): windows.append( Window( f'{name}_wndw_{i}', location + 1, org[0], org[1], w, h, glass_type)) return cls(name=name, location=location + 1, windows=windows, glass_type=glass_type)
[docs] def to_inp(self): return '\n'.join([wndw.to_inp() for wndw in self.windows])
def __repr__(self) -> str: return self.to_inp()
[docs]@dataclass class Wall: """*.inp Wall object. Init method(s): 1. from_room_seg(name, location, construction) Args: name: space name. (is joined with _wall_{n}). location: vertice of space poly anchoring the wall. construction: display_name of construction wall is comprised of. Example: .. code-block:: f# "simple_example_dfb_Floor1_Room1 Wall_1" = EXTERIOR-WALL CONSTRUCTION = "EWall Construction" LOCATION = SPACE-V1 .. """ name: str location: int construction: str windows: RectangularWindows = None window_constr: WindowConstruction = None
[docs] @classmethod def from_room_seg(cls, name: str, location: int, construction: str, windows: None, window_constr: None): indexed_id = location + 1 # shorten the name to ensure we don't create duplicate names with truncated id name = short_name(f'{name}_Wall_{indexed_id}', 32) return cls(name, indexed_id, construction, windows, window_constr)
[docs] def to_inp(self): wallstr = f'"{self.name}" = EXTERIOR-WALL\n' \ f' CONSTRUCTION = "{self.construction}_c"\n' \ f' LOCATION = SPACE-V{self.location}\n ..' if self.windows is not None: window_set = WindowSet.from_params( self.name, self.location, self.windows, self.window_constr) wall_set = [wallstr] wall_set.append(window_set.to_inp()) return '\n'.join(wall_set) else: return wallstr
def __repr__(self) -> str: return self.to_inp()
[docs]@dataclass class Space: """The Space Object. Each Room2D has a Space obj. This obj contains windows, walls, doors data. Init method(s): 1. from_room(room: Room2D) Args: name: room.display_name. activity: room program.display_name. walls: List[of Wall(objects)] Example: .. code-block:: f# "simple_example_dfb_Floor1_Room1" = SPACE SHAPE = POLYGON POLYGON = "simple_example_dfb_Floor1_Room1 Plg" C-ACTIVITY-DESC = *Generic Office Program* .. "simple_example_dfb_Floor1_Room1 Wall_1" = EXTERIOR-WALL CONSTRUCTION = "EWall Construction" LOCATION = SPACE-V1 .. "simple_example_dfb_Floor1_Room1 Wall_2" = EXTERIOR-WALL CONSTRUCTION = "EWall Construction" LOCATION = SPACE-V2 .. """ name: str activity: str walls: List[Wall] slab: Slab = None roof: RoofCeiling = None
[docs] @classmethod def from_room(cls, room: Room2D): if not isinstance(room, Room2D): raise ValueError( f'Unsupported Type: {type(room)}.\n' 'Expected dragonfly.room2d.Room2D' ) wall_constr_name = short_name( room.properties.energy.construction_set.wall_set.exterior_construction.display_name, 30) name = room.display_name low_l_props = lower_left_properties(room) bcs = low_l_props[1] wndw_paras = low_l_props[2] wndw_constr = low_l_props[3] walls = [] for i, (bc, window_param) in enumerate(zip(bcs, wndw_paras)): if str(bc) in list(['Outdoors', 'Ground']): walls.append( Wall.from_room_seg( name, i, wall_constr_name, window_param, wndw_constr)) slab = None if room.is_ground_contact != True else Slab.from_room(name, short_name( room.properties.energy.construction_set.floor_set.ground_construction.display_name, 30)) roof = None if room.is_top_exposed != True else RoofCeiling.from_room(room) return cls( name=room.display_name, activity=room.properties.energy.program_type.display_name, walls=walls, slab=slab, roof=roof)
[docs] def to_inp(self): space_walls = '\n'.join(wall.to_inp() for wall in self.walls) space_block = f'"{self.name}" = SPACE\n' \ f' SHAPE = POLYGON\n' \ f' POLYGON = "{self.name} Plg"\n' \ f' C-ACTIVITY-DESC = *{self.activity}*\n ..\n' blocks = [space_block, space_walls] if self.slab: blocks.append(self.slab.to_inp()) if self.roof: blocks.append(self.roof.to_inp()) return '\n'.join(blocks)
def __repr__(self) -> str: return self.to_inp()
[docs]@dataclass class Floor: """The *.inp 'Floor' object, contains spaces and space meta-data. Init method(s): 1. from_story(story: Story). Args: name: Story display_name. floor_z: the height of the floor poly centroid from ground level. floor_height: the floor-to-floor height of the rooms within the story. This is a single input for eQuest, all rooms in story share this value. Example: .. code-block:: f# "simple_example_dfb_Floor1" = FLOOR Z = 0.0 POLYGON = "simple_example_dfb_Floor1 Floor Plg" SHAPE = POLYGON FLOOR-HEIGHT = 10.0 C-DIAGRAM-DATA = *simple_example_dfb_Floor1 UI DiagData* .. "simple_example_dfb_Floor1_Room1" = SPACE SHAPE = POLYGON POLYGON = "simple_example_dfb_Floor1_Room1 Plg" C-ACTIVITY-DESC = *Generic Office Program* .. "simple_example_dfb_Floor1_Room1 Wall_1" = EXTERIOR-WALL CONSTRUCTION = "EWall Construction" LOCATION = SPACE-V1 .. """ name: str floor_z: float floor_height: float spaces: List[Space]
[docs] @classmethod def from_story(cls, story: Story): if not isinstance(story, Story): raise ValueError( f'Unsupported type: {type(story)}\n' 'Expected dragonfly.story.Story' ) spaces = [Space.from_room(room) for room in story.room_2ds] # a hack to handle cases that floor height is not set for a floor # this will not work for stories that have rooms in different levels floor_height = story.floor_height or story.room_2ds[0].floor_height floor_to_floor_height = story.floor_to_floor_height if floor_height != story.floor_height: # this is file coming from Revit and we need to adjust the floor_to_floor # height that is calculated by Dragonfly floor_to_floor_height -= floor_height return cls( story.display_name, floor_height, floor_to_floor_height, spaces )
# TODO: Add the clustering features into here
[docs] def to_inp(self): flr_str = f'"{self.name}" = FLOOR\n' \ f' Z = {self.floor_z}\n' \ f' POLYGON = "{self.name} Plg"\n' \ f' SHAPE = POLYGON\n' \ f' FLOOR-HEIGHT = {self.floor_height}\n' \ f' C-DIAGRAM-DATA = *{self.name} UI DiagData*\n ..\n' flr_spcs = '\n'.join(spc.to_inp() for spc in self.spaces) return '\n'.join([flr_str, flr_spcs])
def __repr__(self) -> str: return self.to_inp()