forked from ladybug-tools/honeybee-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathorientation.py
132 lines (104 loc) · 4.93 KB
/
orientation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""Collection of utilities for assigning different properties based on orientation.
The functions here are meant to be adaptable to splitting up the compass based on
however many bins the user desires, though the most common arrangement is likely
to be a list of 4 values for North, East South, and West.
Usage:
.. code-block:: python
# list of constructions + materials to apply to faces of different orientations
ep_constructions = [constr_north, constr_east, constr_south, constr_west]
rad_materials = [mat_north, mat_east, mat_south, mat_west]
# check that the inputs align with one another
all_inputs = [ep_constructions, rad_materials]
all_inputs, num_orient = check_matching_inputs(all_inputs)
# assign properties based on orientation
angles = angles_from_num_orient(num_orient)
for face in hb_faces:
orient_i = face_orient_index(face, angles)
if orient_i is not None:
constr, mat = inputs_by_index(orient_i, all_inputs)
face.properties.energy.construction = constr
face.properties.radiance.modifier = mat
"""
from ladybug_geometry.geometry2d.pointvector import Vector2D
def angles_from_num_orient(num_subdivisions=4):
"""Get a list of angles based on the number of compass subdivisions.
Args:
num_subdivisions: An integer for the number of times that the compass
should be subdivided. Default: 4, which will yield angles for North,
East South, and West.
Returns:
A list of angles in degrees with a length of the num_subdivisions, which
denote the boundaries of each orientation category.
"""
step = 360.0 / num_subdivisions
start = step / 2.0
angles = []
while start < 360:
angles.append(start)
start += step
return angles
def face_orient_index(face, angles, north_vector=Vector2D(0, 1)):
"""Get the index to be used for a given face/aperture orientation from an angle list.
Args:
face: A honeybee Face or Aperture object.
angles: A list of angles that denote the boundaries of each orientation
category.
north_vector: An optional ladybug_geometry Vector2D for the north direction.
Default is the Y-axis (0, 1).
Returns:
An integer for the index used to assign properties to the object of the
input orientation. Will be None if the input Face or Aperture is perfectly
horizontal.
"""
try:
return orient_index(face.horizontal_orientation(north_vector), angles)
except ZeroDivisionError: # input face is perfectly horizontal
return None
def orient_index(orientation, angles):
"""Get the index to be used for a given face/aperture orientation from an angle list.
Args:
orientation: The horizontal cardinal orientation of the Face or Aperture
in degrees.
angles: A list of angles that denote the boundaries of each orientation
category.
Returns:
An integer for the index used to assign properties to the object of the
input orientation.
"""
for i, ang in enumerate(angles):
if orientation < ang:
return i
return 0
def inputs_by_index(orientation_index, all_inputs):
"""Get all of the inputs of a certain index from a list of all_inputs.
This is useful for getting the set of all inputs that should be assigned to
a given Face or Aperture using its orientation_index.
"""
return [inp[orientation_index] for inp in all_inputs]
def check_matching_inputs(all_inputs, num_orient=None):
"""Check that all orientation-specific inputs are coordinated.
This means that each input is either a array of values to be applied to each
orientation, which is has the same length as other orientation-specific arrays,
or it is a single value to be used for all orientations.
Args:
all_inputs: An array of arrays where each sub-array corresponds to an
orientation-specific input.
num_orient: An optional integer for the number of orientation categories
to be used. If None, the length of the longest input list in the
all_inputs will be used.
Returns:
A tuple with two elements
- all_inputs -- The input all_inputs with all sub-arrays having the same length.
- num_orient -- An integer for the number of orientations used in the check.
"""
num_orient = max([len(inp) for inp in all_inputs]) if num_orient is None \
else num_orient
for i, param_list in enumerate(all_inputs):
if len(param_list) == 1:
all_inputs[i] = param_list * num_orient
else:
assert len(param_list) == num_orient, \
'The number of items in one of the inputs lists does not match the ' \
'others.\nPlease ensure that either the lists match or you put in '\
'a single value for all orientations.'
return all_inputs, num_orient