Skip to content

Commit

Permalink
feat(writer): Add option --equest-version to translation command
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey authored and Chris Mackey committed Jul 2, 2024
1 parent e788eba commit 9b21185
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 11 deletions.
11 changes: 8 additions & 3 deletions honeybee_doe2/cli/translate.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""honeybee-doe2 translation commands."""
import click
import sys
import os
import json
import logging

Expand Down Expand Up @@ -47,13 +46,18 @@ def translate():
'--include-interior-ceilings/--exclude-interior-ceilings', ' /-xc', help='Flag to '
'note whether interior ceilings should be excluded from the export.',
default=True, show_default=True)
@click.option(
'--equest-version', '-eq', help='optional text string to denote the version '
'of eQuest for which the INP definition will be generated. If unspecified '
'or unrecognized, the latest version of eQuest will be used.',
default='3.65', show_default=True, type=str)
@click.option(
'--output-file', '-o', help='Optional INP file path to output the INP string '
'of the translation. By default this will be printed out to stdout.',
type=click.File('w'), default='-', show_default=True)
def model_to_inp_file(
model_file, sim_par_json, hvac_mapping, include_interior_walls,
include_interior_ceilings, output_file
include_interior_ceilings, equest_version, output_file
):
"""Translate a Model (HBJSON) file to an INP file.
Expand All @@ -74,7 +78,8 @@ def model_to_inp_file(
x_int_c = not include_interior_ceilings

# create the strings for the model
inp_str = model.to.inp(model, sim_par, hvac_mapping, x_int_w, x_int_c)
inp_str = model.to.inp(model, sim_par, hvac_mapping, x_int_w, x_int_c,
equest_version)

# write out the INP file
output_file.write(inp_str)
Expand Down
59 changes: 51 additions & 8 deletions honeybee_doe2/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import math

from ladybug_geometry.geometry2d import Vector2D, Point2D
from ladybug_geometry.geometry3d import Vector3D, Point3D, Plane, Face3D
from ladybug_geometry.geometry3d import Vector3D, Point3D, LineSegment3D, Plane, Face3D
from ladybug_geometry.bounding import bounding_box
from honeybee.typing import clean_doe2_string, clean_string
from honeybee.boundarycondition import Surface
Expand Down Expand Up @@ -144,12 +144,15 @@ def face_3d_to_inp_rectangle(face_3d):
return None


def shade_mesh_to_inp(shade_mesh):
def shade_mesh_to_inp(shade_mesh, equest_version=None):
"""Generate an INP string representation of a ShadeMesh.
Args:
shade_mesh: A honeybee ShadeMesh for which an INP representation
will be returned.
equest_version: An optional text string to denote the version of eQuest
for which the Shade INP definition will be generated. If unspecified
or unrecognized, the latest version of eQuest will be used.
Returns:
A tuple with two elements.
Expand Down Expand Up @@ -180,7 +183,24 @@ def shade_mesh_to_inp(shade_mesh):
shd_geo = f_geo if f_geo.altitude > 0 else f_geo.flip()
clean_geo = shd_geo.remove_colinear_vertices(DOE2_TOLERANCE)
rect_info = face_3d_to_inp_rectangle(clean_geo)
if rect_info is not None: # shade is a rectangle; translate it without POLYGON
if equest_version == '3.64':
shade_polygon = ''
if rect_info is not None:
width, height, origin, tilt, az = rect_info
else: # take the bounding rectangle around the Face3D
min_pt, max_pt = clean_geo.min, clean_geo.max
f_tilt = math.degrees(clean_geo.tilt)
if 90 - DOE2_ANGLE_TOL <= f_tilt <= 90 + DOE2_ANGLE_TOL: # vertical
seg_dir = Vector3D(max_pt.x - min_pt.x, max_pt.y - min_pt.y, 0)
seg = LineSegment3D(min_pt, seg_dir)
ext_dir = Vector3D(0, 0, max_pt.z - min_pt.z)
else: # horizontal or tilted
seg = LineSegment3D(min_pt, Vector3D(max_pt.x - min_pt.x, 0, 0))
ext_dir = Vector3D(0, max_pt.y - min_pt.y, max_pt.z - min_pt.z)
rect_geo = Face3D.from_extrusion(seg, ext_dir)
width, height, origin, tilt, az = face_3d_to_inp_rectangle(rect_geo)
geo_kwd, geo_vals = ['HEIGHT', 'WIDTH'], [height, width]
elif rect_info is not None: # shade is a rectangle; translate it without POLYGON
width, height, origin, tilt, az = rect_info
geo_kwd = ['SHAPE', 'HEIGHT', 'WIDTH']
geo_vals = ['RECTANGLE', height, width]
Expand All @@ -202,11 +222,14 @@ def shade_mesh_to_inp(shade_mesh):
return shade_polygons, shade_defs


def shade_to_inp(shade):
def shade_to_inp(shade, equest_version=None):
"""Generate an INP string representation of a Shade.
Args:
shade: A honeybee Shade for which an INP representation will be returned.
equest_version: An optional text string to denote the version of eQuest
for which the Shade INP definition will be generated. If unspecified
or unrecognized, the latest version of eQuest will be used.
Returns:
A tuple with two elements.
Expand All @@ -229,7 +252,24 @@ def shade_to_inp(shade):
shd_geo = shade.geometry if shade.altitude > 0 else shade.geometry.flip()
clean_geo = shd_geo.remove_colinear_vertices(DOE2_TOLERANCE)
rect_info = face_3d_to_inp_rectangle(clean_geo)
if rect_info is not None: # shade is a rectangle; translate it without POLYGON
if equest_version == '3.64':
shade_polygon = ''
if rect_info is not None:
width, height, origin, tilt, az = rect_info
else: # take the bounding rectangle around the Face3D
min_pt, max_pt = clean_geo.min, clean_geo.max
f_tilt = math.degrees(clean_geo.tilt)
if 90 - DOE2_ANGLE_TOL <= f_tilt <= 90 + DOE2_ANGLE_TOL: # vertical
seg_dir = Vector3D(max_pt.x - min_pt.x, max_pt.y - min_pt.y, 0)
seg = LineSegment3D(min_pt, seg_dir)
ext_dir = Vector3D(0, 0, max_pt.z - min_pt.z)
else: # horizontal or tilted
seg = LineSegment3D(min_pt, Vector3D(max_pt.x - min_pt.x, 0, 0))
ext_dir = Vector3D(0, max_pt.y - min_pt.y, max_pt.z - min_pt.z)
rect_geo = Face3D.from_extrusion(seg, ext_dir)
width, height, origin, tilt, az = face_3d_to_inp_rectangle(rect_geo)
geo_kwd, geo_vals = ['HEIGHT', 'WIDTH'], [height, width]
elif rect_info is not None: # shade is a rectangle; translate it without POLYGON
width, height, origin, tilt, az = rect_info
geo_kwd = ['SHAPE', 'HEIGHT', 'WIDTH']
geo_vals = ['RECTANGLE', height, width]
Expand Down Expand Up @@ -669,7 +709,7 @@ def _is_room_3d_extruded(hb_room):

def model_to_inp(
model, simulation_par=None, hvac_mapping='Story',
exclude_interior_walls=False, exclude_interior_ceilings=False
exclude_interior_walls=False, exclude_interior_ceilings=False, equest_version=None
):
"""Generate an INP string representation of a Model.
Expand Down Expand Up @@ -701,6 +741,9 @@ def model_to_inp(
should be excluded from the resulting string. (Default: False).
exclude_interior_ceilings: Boolean to note whether interior ceiling
Faces should be excluded from the resulting string. (Default: False).
equest_version: An optional text string to denote the version of eQuest
for which the INP definition will be generated. If unspecified
or unrecognized, the latest version of eQuest will be used.
Usage:
Expand Down Expand Up @@ -885,12 +928,12 @@ def model_to_inp(
# loop through the shades and get their definitions and polygons
shade_polygons, shade_geo_defs = [], []
for shade in model.shades:
shade_polygon, shade_def = shade_to_inp(shade)
shade_polygon, shade_def = shade_to_inp(shade, equest_version)
if shade_polygon != '': # shade written with a RECTANGLE
shade_polygons.append(shade_polygon)
shade_geo_defs.append(shade_def)
for shade in model.shade_meshes:
shade_polygon, shade_def = shade_mesh_to_inp(shade)
shade_polygon, shade_def = shade_mesh_to_inp(shade, equest_version)
shade_polygons.extend(shade_polygon)
shade_geo_defs.extend(shade_def)

Expand Down

0 comments on commit 9b21185

Please sign in to comment.