Skip to content

Commit

Permalink
fix: several fixes to import models generated from Revit
Browse files Browse the repository at this point in the history
Here is the shortlist:

1. Catch the case when both `floor_height` and `floor_to_floor_height` are set to 0. I'm using the Room properties to get them instead.
2. Remove the holes from story polygon. We we removing it from the rooms already but not from the story floorplate.
3. Caught a few cases where names where not inside double quotes.
4. Shorten the name for floor space with index
5. Purge duplicate window constructions
  • Loading branch information
mostaphaRoudsari committed Mar 17, 2022
1 parent d88ff01 commit 50b762c
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 18 deletions.
25 changes: 18 additions & 7 deletions dragonfly_doe2/doe/floor_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class Window:

def to_inp(self):
shortened_name = short_name(f'{self.name}_w{self.location}', 32)
return f'{shortened_name} = WINDOW\n ' \
return f'"{shortened_name}" = WINDOW\n ' \
f'X = {self.x}\n ' \
f'Y = {self.y}\n ' \
f'WIDTH = {self.width}\n ' \
Expand Down Expand Up @@ -213,15 +213,17 @@ class Wall:
location: int
construction: str
windows: RectangularWindows = None
window_constr: window_constr = None
window_constr: WindowConstruction = None

@classmethod
def from_room_seg(cls, name: str, location: int, construction: str,
windows: None, window_constr: None):
indexed_id = location + 1
return cls(
f'{name}_Wall_{indexed_id}', indexed_id, construction, windows,
window_constr)

# 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)

def to_inp(self):
wallstr = f'"{self.name}" = EXTERIOR-WALL\n' \
Expand Down Expand Up @@ -375,9 +377,18 @@ def from_story(cls, story: Story):
'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, story.floor_height,
story.floor_to_floor_height, spaces
story.display_name, floor_height,
floor_to_floor_height, spaces
)
# TODO: Add the clustering features into here

Expand Down
2 changes: 1 addition & 1 deletion dragonfly_doe2/doe/hvac.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def to_inp(self):
f'DESIGN-HEAT-T = {self.heating_setpoint}\n ' \
f'DESIGN-COOL-T = {self.cooling_setpoint}\n ' \
'SIZING-OPTION = ADJUST-LOADS\n ' \
f'SPACE = {self.name}\n ..\n'
f'SPACE = "{self.name}"\n ..\n'
return inp_str

def __repr__(self) -> str:
Expand Down
11 changes: 11 additions & 0 deletions dragonfly_doe2/doe/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ def __init__(self, title, run_period=None, compliance_data=None,

@classmethod
def from_df_model(cls, df_model: DFModel, run_period=None):
# Make model windows rectangular to be INP friendly
df_model.to_rectangular_windows()

# Check model units, ensure units in feet
df_model.convert_to_units(units='Feet')
df_model.properties.energy.construction_sets.append(generic_construction_set)
Expand All @@ -57,8 +60,15 @@ def from_df_model(cls, df_model: DFModel, run_period=None):

for con_set in df_model.properties.energy.construction_sets:
window_constructions.append(con_set.aperture_set.window_construction)

# purge duplicate window constructions
window_constructions = list(set(window_constructions))

for building in df_model.buildings:
for story in building.all_stories():
# enforce a recompute of floor to floor height
if story.floor_to_floor_height == 0:
story.floor_to_floor_height = None

story.solve_room_2d_adjacency(df_model.tolerance, intersect=True)

Expand Down Expand Up @@ -90,6 +100,7 @@ def from_df_model(cls, df_model: DFModel, run_period=None):

constructions = ConstructionCollection.from_hb_constructions(
df_envelope_constrs)

glass_types = [GlassType.from_hb_window_constr(
w_con) for w_con in window_constructions]

Expand Down
21 changes: 13 additions & 8 deletions dragonfly_doe2/doe/polygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,32 @@ def __init__(self, name, vertices):
def from_room(cls, room: Room2D, tolerace=0.01):
"""
Note: Shouldn't we ensure the points are in 2D. I'm not sure how it works.
#TF: ooohhhhhhhhhh good catch!! Though is there not already built into DF somthhing
#TF: ooohhhhhhhhhh good catch!! Though is there not already built into DF something
of the sort for room.floor_geom? was operating off the *assumption* that obj.prop
would be good to go as is? or am I misunderstanding the specifics in which should
do check: raise exeption if issue?
do check: raise exception if issue?
"""
room.remove_duplicate_vertices()
# TODO: on refactor, need to minimize the disconnect between the poly and 'space' room
vertices = lower_left_properties(room)[0]
return cls(room.display_name, vertices)

@classmethod
def from_story(cls, story: Story, tolerace=0.01):
def from_story(cls, story: Story, tolerance=0.01):
"""
Note: I'm not sure if this is correct - shouldn't we create a polygon per face?
This is based on the initial code by Trevor so I didn't change it.
"""
geo = story.footprint(tolerance=tolerace)
vertices = []
for face in geo:
vertices.extend(face.lower_left_counter_clockwise_vertices)
return cls(story.display_name, vertices)
geo = story.footprint(tolerance=tolerance)[0]
#
b_pts = geo.boundary
# remove duplicate vertices if any
new_bound = []
b_pts = b_pts[1:] + (b_pts[0],)
for i, vert in enumerate(b_pts):
if not vert.is_equivalent(b_pts[i - 1], tolerance):
new_bound.append(b_pts[i - 1])
return cls(story.display_name, new_bound)

def to_inp(self) -> str:
"""Return Room Polygons block input"""
Expand Down
2 changes: 1 addition & 1 deletion dragonfly_doe2/doe/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from ladybug.datatype import UNITS as lbt_units, TYPESDICT as lbt_td


def short_name(name, max_length):
def short_name(name, max_length=32):
if len(name) <= max_length:
return name

Expand Down
1 change: 0 additions & 1 deletion dragonfly_doe2/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ def model_to_inp(
"""

# TODO: add all the other arguments that one might to pass to the model
model.to_rectangular_windows()
inp_model = Model.from_df_model(model)

# write to inp
Expand Down

0 comments on commit 50b762c

Please sign in to comment.