honeybee-radiance 1.66.190__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of honeybee-radiance might be problematic. Click here for more details.

Files changed (152) hide show
  1. honeybee_radiance/__init__.py +11 -0
  2. honeybee_radiance/__main__.py +4 -0
  3. honeybee_radiance/_extend_honeybee.py +93 -0
  4. honeybee_radiance/cli/__init__.py +88 -0
  5. honeybee_radiance/cli/dc.py +400 -0
  6. honeybee_radiance/cli/edit.py +529 -0
  7. honeybee_radiance/cli/glare.py +118 -0
  8. honeybee_radiance/cli/grid.py +859 -0
  9. honeybee_radiance/cli/lib.py +458 -0
  10. honeybee_radiance/cli/modifier.py +133 -0
  11. honeybee_radiance/cli/mtx.py +226 -0
  12. honeybee_radiance/cli/multiphase.py +1034 -0
  13. honeybee_radiance/cli/octree.py +640 -0
  14. honeybee_radiance/cli/postprocess.py +1186 -0
  15. honeybee_radiance/cli/raytrace.py +219 -0
  16. honeybee_radiance/cli/rpict.py +125 -0
  17. honeybee_radiance/cli/schedule.py +56 -0
  18. honeybee_radiance/cli/setconfig.py +63 -0
  19. honeybee_radiance/cli/sky.py +545 -0
  20. honeybee_radiance/cli/study.py +66 -0
  21. honeybee_radiance/cli/sunpath.py +331 -0
  22. honeybee_radiance/cli/threephase.py +255 -0
  23. honeybee_radiance/cli/translate.py +400 -0
  24. honeybee_radiance/cli/util.py +121 -0
  25. honeybee_radiance/cli/view.py +261 -0
  26. honeybee_radiance/cli/viewfactor.py +347 -0
  27. honeybee_radiance/config.json +6 -0
  28. honeybee_radiance/config.py +427 -0
  29. honeybee_radiance/dictutil.py +50 -0
  30. honeybee_radiance/dynamic/__init__.py +5 -0
  31. honeybee_radiance/dynamic/group.py +479 -0
  32. honeybee_radiance/dynamic/multiphase.py +557 -0
  33. honeybee_radiance/dynamic/state.py +718 -0
  34. honeybee_radiance/dynamic/stategeo.py +352 -0
  35. honeybee_radiance/geometry/__init__.py +13 -0
  36. honeybee_radiance/geometry/bubble.py +42 -0
  37. honeybee_radiance/geometry/cone.py +215 -0
  38. honeybee_radiance/geometry/cup.py +54 -0
  39. honeybee_radiance/geometry/cylinder.py +197 -0
  40. honeybee_radiance/geometry/geometrybase.py +37 -0
  41. honeybee_radiance/geometry/instance.py +40 -0
  42. honeybee_radiance/geometry/mesh.py +38 -0
  43. honeybee_radiance/geometry/polygon.py +174 -0
  44. honeybee_radiance/geometry/ring.py +214 -0
  45. honeybee_radiance/geometry/source.py +182 -0
  46. honeybee_radiance/geometry/sphere.py +178 -0
  47. honeybee_radiance/geometry/tube.py +46 -0
  48. honeybee_radiance/lib/__init__.py +1 -0
  49. honeybee_radiance/lib/_loadmodifiers.py +72 -0
  50. honeybee_radiance/lib/_loadmodifiersets.py +69 -0
  51. honeybee_radiance/lib/modifiers.py +58 -0
  52. honeybee_radiance/lib/modifiersets.py +63 -0
  53. honeybee_radiance/lightpath.py +204 -0
  54. honeybee_radiance/lightsource/__init__.py +1 -0
  55. honeybee_radiance/lightsource/_gendaylit.py +479 -0
  56. honeybee_radiance/lightsource/dictutil.py +49 -0
  57. honeybee_radiance/lightsource/ground.py +160 -0
  58. honeybee_radiance/lightsource/sky/__init__.py +7 -0
  59. honeybee_radiance/lightsource/sky/_skybase.py +177 -0
  60. honeybee_radiance/lightsource/sky/certainirradiance.py +232 -0
  61. honeybee_radiance/lightsource/sky/cie.py +378 -0
  62. honeybee_radiance/lightsource/sky/climatebased.py +501 -0
  63. honeybee_radiance/lightsource/sky/hemisphere.py +160 -0
  64. honeybee_radiance/lightsource/sky/skydome.py +113 -0
  65. honeybee_radiance/lightsource/sky/skymatrix.py +163 -0
  66. honeybee_radiance/lightsource/sky/strutil.py +34 -0
  67. honeybee_radiance/lightsource/sky/sunmatrix.py +212 -0
  68. honeybee_radiance/lightsource/sunpath.py +247 -0
  69. honeybee_radiance/modifier/__init__.py +3 -0
  70. honeybee_radiance/modifier/material/__init__.py +30 -0
  71. honeybee_radiance/modifier/material/absdf.py +477 -0
  72. honeybee_radiance/modifier/material/antimatter.py +54 -0
  73. honeybee_radiance/modifier/material/ashik2.py +51 -0
  74. honeybee_radiance/modifier/material/brtdfunc.py +81 -0
  75. honeybee_radiance/modifier/material/bsdf.py +292 -0
  76. honeybee_radiance/modifier/material/dielectric.py +53 -0
  77. honeybee_radiance/modifier/material/glass.py +431 -0
  78. honeybee_radiance/modifier/material/glow.py +246 -0
  79. honeybee_radiance/modifier/material/illum.py +51 -0
  80. honeybee_radiance/modifier/material/interface.py +49 -0
  81. honeybee_radiance/modifier/material/light.py +206 -0
  82. honeybee_radiance/modifier/material/materialbase.py +36 -0
  83. honeybee_radiance/modifier/material/metal.py +167 -0
  84. honeybee_radiance/modifier/material/metal2.py +41 -0
  85. honeybee_radiance/modifier/material/metdata.py +41 -0
  86. honeybee_radiance/modifier/material/metfunc.py +41 -0
  87. honeybee_radiance/modifier/material/mirror.py +340 -0
  88. honeybee_radiance/modifier/material/mist.py +86 -0
  89. honeybee_radiance/modifier/material/plasdata.py +58 -0
  90. honeybee_radiance/modifier/material/plasfunc.py +59 -0
  91. honeybee_radiance/modifier/material/plastic.py +354 -0
  92. honeybee_radiance/modifier/material/plastic2.py +58 -0
  93. honeybee_radiance/modifier/material/prism1.py +57 -0
  94. honeybee_radiance/modifier/material/prism2.py +48 -0
  95. honeybee_radiance/modifier/material/spotlight.py +50 -0
  96. honeybee_radiance/modifier/material/trans.py +518 -0
  97. honeybee_radiance/modifier/material/trans2.py +49 -0
  98. honeybee_radiance/modifier/material/transdata.py +50 -0
  99. honeybee_radiance/modifier/material/transfunc.py +53 -0
  100. honeybee_radiance/modifier/mixture/__init__.py +6 -0
  101. honeybee_radiance/modifier/mixture/mixdata.py +49 -0
  102. honeybee_radiance/modifier/mixture/mixfunc.py +54 -0
  103. honeybee_radiance/modifier/mixture/mixpict.py +52 -0
  104. honeybee_radiance/modifier/mixture/mixtext.py +66 -0
  105. honeybee_radiance/modifier/mixture/mixturebase.py +28 -0
  106. honeybee_radiance/modifier/modifierbase.py +40 -0
  107. honeybee_radiance/modifier/pattern/__init__.py +9 -0
  108. honeybee_radiance/modifier/pattern/brightdata.py +49 -0
  109. honeybee_radiance/modifier/pattern/brightfunc.py +47 -0
  110. honeybee_radiance/modifier/pattern/brighttext.py +81 -0
  111. honeybee_radiance/modifier/pattern/colordata.py +56 -0
  112. honeybee_radiance/modifier/pattern/colorfunc.py +47 -0
  113. honeybee_radiance/modifier/pattern/colorpict.py +54 -0
  114. honeybee_radiance/modifier/pattern/colortext.py +73 -0
  115. honeybee_radiance/modifier/pattern/patternbase.py +34 -0
  116. honeybee_radiance/modifier/texture/__init__.py +4 -0
  117. honeybee_radiance/modifier/texture/texdata.py +29 -0
  118. honeybee_radiance/modifier/texture/texfunc.py +26 -0
  119. honeybee_radiance/modifier/texture/texturebase.py +27 -0
  120. honeybee_radiance/modifierset.py +1091 -0
  121. honeybee_radiance/mutil.py +60 -0
  122. honeybee_radiance/postprocess/__init__.py +1 -0
  123. honeybee_radiance/postprocess/annual.py +108 -0
  124. honeybee_radiance/postprocess/annualdaylight.py +425 -0
  125. honeybee_radiance/postprocess/annualglare.py +201 -0
  126. honeybee_radiance/postprocess/annualirradiance.py +187 -0
  127. honeybee_radiance/postprocess/electriclight.py +119 -0
  128. honeybee_radiance/postprocess/en17037.py +261 -0
  129. honeybee_radiance/postprocess/leed.py +304 -0
  130. honeybee_radiance/postprocess/solartracking.py +90 -0
  131. honeybee_radiance/primitive.py +554 -0
  132. honeybee_radiance/properties/__init__.py +1 -0
  133. honeybee_radiance/properties/_base.py +390 -0
  134. honeybee_radiance/properties/aperture.py +197 -0
  135. honeybee_radiance/properties/door.py +198 -0
  136. honeybee_radiance/properties/face.py +123 -0
  137. honeybee_radiance/properties/model.py +1291 -0
  138. honeybee_radiance/properties/room.py +490 -0
  139. honeybee_radiance/properties/shade.py +186 -0
  140. honeybee_radiance/properties/shademesh.py +116 -0
  141. honeybee_radiance/putil.py +44 -0
  142. honeybee_radiance/reader.py +214 -0
  143. honeybee_radiance/sensor.py +166 -0
  144. honeybee_radiance/sensorgrid.py +1008 -0
  145. honeybee_radiance/view.py +1101 -0
  146. honeybee_radiance/writer.py +951 -0
  147. honeybee_radiance-1.66.190.dist-info/METADATA +89 -0
  148. honeybee_radiance-1.66.190.dist-info/RECORD +152 -0
  149. honeybee_radiance-1.66.190.dist-info/WHEEL +5 -0
  150. honeybee_radiance-1.66.190.dist-info/entry_points.txt +2 -0
  151. honeybee_radiance-1.66.190.dist-info/licenses/LICENSE +661 -0
  152. honeybee_radiance-1.66.190.dist-info/top_level.txt +1 -0
@@ -0,0 +1,490 @@
1
+ # coding=utf-8
2
+ """Room Radiance Properties."""
3
+ import math
4
+
5
+ from ladybug_geometry.geometry3d.pointvector import Vector3D
6
+ from honeybee.facetype import Floor, Wall
7
+ from honeybee.typing import clean_rad_string
8
+ from honeybee.checkdup import is_equivalent
9
+
10
+ from ..sensorgrid import SensorGrid
11
+ from ..view import View
12
+ from ..modifierset import ModifierSet
13
+ from ..lib.modifiersets import generic_modifier_set_visible
14
+
15
+
16
+ class RoomRadianceProperties(object):
17
+ """Radiance Properties for Honeybee Room.
18
+
19
+ Args:
20
+ host: A honeybee_core Room object that hosts these properties.
21
+ modifier_set: A honeybee ModifierSet object to specify all default
22
+ modifiers for the Faces of the Room. If None, the Room will use
23
+ the honeybee default modifier set, which is only representative
24
+ of typical indoor conditions in the visible spectrum. Default: None.
25
+
26
+ Properties:
27
+ * host
28
+ * modifier_set
29
+ """
30
+
31
+ __slots__ = ('_host', '_modifier_set')
32
+
33
+ def __init__(self, host, modifier_set=None):
34
+ """Initialize Room radiance properties."""
35
+ # set the main properties of the Room
36
+ self._host = host
37
+ self.modifier_set = modifier_set
38
+
39
+ @property
40
+ def host(self):
41
+ """Get the Room object hosting these properties."""
42
+ return self._host
43
+
44
+ @property
45
+ def modifier_set(self):
46
+ """Get or set the Room ModifierSet object.
47
+
48
+ If not set, it will be the Honeybee default generic ModifierSet.
49
+ """
50
+ if self._modifier_set is not None: # set by the user
51
+ return self._modifier_set
52
+ else:
53
+ return generic_modifier_set_visible
54
+
55
+ @modifier_set.setter
56
+ def modifier_set(self, value):
57
+ if value is not None:
58
+ assert isinstance(value, ModifierSet), \
59
+ 'Expected ModifierSet. Got {}'.format(type(value))
60
+ value.lock() # lock in case modifier set has multiple references
61
+ self._modifier_set = value
62
+
63
+ def generate_sensor_grid(
64
+ self, x_dim, y_dim=None, offset=1.0, remove_out=False, wall_offset=0):
65
+ """Get a radiance SensorGrid generated from this Room's floors.
66
+
67
+ The output grid will have this room referenced in its room_identifier
68
+ property. It will also include a Mesh3D object with faces that align
69
+ with the grid positions under the grid's mesh property.
70
+
71
+ Note that the x_dim and y_dim refer to dimensions within the XY coordinate
72
+ system of the floor faces's planes. So rotating the planes of the floor faces
73
+ will result in rotated grid cells.
74
+
75
+ Args:
76
+ x_dim: The x dimension of the grid cells as a number.
77
+ y_dim: The y dimension of the grid cells as a number. If None,
78
+ the y dimension will be assumed to be the same as the x
79
+ dimension. (Default: None).
80
+ offset: A number for how far to offset the grid from the base face.
81
+ (Default is 1.0, which will not offset the grid to be 1 unit above
82
+ the floor).
83
+ remove_out: Boolean to note whether an extra check should be run to remove
84
+ sensor points that lie outside the Room volume. Note that this can
85
+ add significantly to runtime and this check is not necessary
86
+ in the case that all walls are vertical and all floors are
87
+ horizontal (Default: False).
88
+ wall_offset: A number for the distance at which sensors close to walls
89
+ should be removed. Note that this option has no effect unless the
90
+ value is more than half of the x_dim or y_dim. (Default: 0).
91
+
92
+ Returns:
93
+ A honeybee_radiance SensorGrid generated from the floors of the room.
94
+ Will be None if the Room has no floors or the criteria for wall_offset
95
+ and/or remove_out results in all sensors being removed.
96
+
97
+ Usage:
98
+
99
+ .. code-block:: python
100
+
101
+ from honeybee.room import Room
102
+ room = Room.from_box(3.0, 6.0, 3.2, 180)
103
+ south_face = room[3]
104
+ south_face.apertures_by_ratio(0.4, 0.01)
105
+ sensor_grid = room.properties.radiance.generate_grid(0.5, 0.5, 1)
106
+ """
107
+ # generate the mesh grid from the floor Faces
108
+ floor_grid = self._base_sensor_mesh(
109
+ x_dim, y_dim, offset, remove_out, wall_offset)
110
+ if floor_grid is None: # no valid mesh could be generated
111
+ return None
112
+
113
+ # create the sensor grid from the mesh
114
+ sensor_grid = SensorGrid.from_mesh3d(
115
+ clean_rad_string(self.host.display_name), floor_grid)
116
+ sensor_grid.room_identifier = self.host.identifier
117
+ sensor_grid.display_name = self.host.display_name
118
+ sensor_grid.base_geometry = \
119
+ tuple(face.geometry.move(face.normal.reverse() * offset)
120
+ for face in self.host.faces if isinstance(face.type, Floor))
121
+ return sensor_grid
122
+
123
+ def generate_sensor_grid_radial(
124
+ self, x_dim, y_dim=None, offset=1.0, remove_out=False, wall_offset=0,
125
+ dir_count=8, start_vector=Vector3D(0, -1, 0), mesh_radius=None):
126
+ """Get a SensorGrid of radial directions around positions from the floors.
127
+
128
+ This type of sensor grid is particularly helpful for studies of multiple view
129
+ directions, such as imageless glare studies.
130
+
131
+ The output grid will have this room referenced in its room_identifier
132
+ property. It will also include a Mesh3D of radial faces around each position
133
+ under the grid's mesh property. Note that the x_dim and y_dim refer to
134
+ dimensions within the XY coordinate system of the floor faces's planes.
135
+ So rotating the planes of the floor faces will result in rotated grid cells.
136
+
137
+ Args:
138
+ x_dim: The x dimension of the grid cells as a number.
139
+ y_dim: The y dimension of the grid cells as a number. If None,
140
+ the y dimension will be assumed to be the same as the x
141
+ dimension. (Default: None).
142
+ offset: A number for how far to offset the grid from the base face.
143
+ (Default: 1.0, which will not offset the grid to be 1 unit above
144
+ the floor).
145
+ remove_out: Boolean to note whether an extra check should be run to remove
146
+ sensor points that lie outside the Room volume. Note that this can
147
+ add significantly to runtime and this check is not necessary
148
+ in the case that all walls are vertical and all floors are
149
+ horizontal (Default: False).
150
+ wall_offset: A number for the distance at which sensors close to walls
151
+ should be removed. Note that this option has no effect unless the
152
+ value is more than half of the x_dim or y_dim. (Default: 0).
153
+ dir_count: A positive integer for the number of radial directions
154
+ to be generated around each position. (Default: 8).
155
+ start_vector: A Vector3D to set the start direction of the generated
156
+ directions. This can be used to orient the resulting sensors to
157
+ specific parts of the scene. It can also change the elevation of the
158
+ resulting directions since this start vector will always be rotated in
159
+ the XY plane to generate the resulting directions. (Default: (0, -1, 0)).
160
+ mesh_radius: An optional number to override the radius of the meshes
161
+ generated around each sensor. If None, it will be equal to 45%
162
+ of the x_dim or y_dim (whichever is smaller). Set to zero to ensure
163
+ no mesh is added to the resulting sensor grids. (Default: None).
164
+
165
+ Returns:
166
+ A honeybee_radiance SensorGrid generated from the floors of the room.
167
+ Will be None if the Room has no floors or the criteria for wall_offset
168
+ and/or remove_out results in all sensors being removed.
169
+ """
170
+ # generate the mesh grid from the floor Faces
171
+ floor_grid = self._base_sensor_mesh(
172
+ x_dim, y_dim, offset, remove_out, wall_offset)
173
+ if floor_grid is None: # no valid mesh could be generated
174
+ return None
175
+
176
+ # create the sensor grid from the mesh
177
+ if mesh_radius is None:
178
+ small_dim = x_dim if y_dim is None else min((x_dim, y_dim))
179
+ mesh_radius = small_dim * 0.45
180
+ grid_name = '{}_Radial'.format(clean_rad_string(self.host.display_name))
181
+ sensor_grid = SensorGrid.from_mesh3d_radial(
182
+ grid_name, floor_grid, dir_count, start_vector, mesh_radius)
183
+ sensor_grid.room_identifier = self.host.identifier
184
+ sensor_grid.display_name = self.host.display_name
185
+ sensor_grid.base_geometry = \
186
+ tuple(face.geometry.move(face.normal.reverse() * offset)
187
+ for face in self.host.faces if isinstance(face.type, Floor))
188
+ return sensor_grid
189
+
190
+ def generate_exterior_face_sensor_grid(
191
+ self, dimension, offset=0.1, face_type='Wall', punched_geometry=False):
192
+ """Get a radiance SensorGrid generated from the exterior Faces of this room.
193
+
194
+ This will be None if the Room has no exterior Faces.
195
+
196
+ The output grid will have this room referenced in its room_identifier
197
+ property. It will also include a Mesh3D object with faces that align
198
+ with the grid positions under the grid's mesh property.
199
+
200
+ Args:
201
+ dimension: The dimension of the grid cells as a number.
202
+ offset: A number for how far to offset the grid from the base face.
203
+ Positive numbers indicate an offset towards the exterior. (Default
204
+ is 0.1, which will offset the grid to be 0.1 unit from the faces).
205
+ face_type: Text to specify the type of face that will be used to
206
+ generate grids. Note that only Faces with Outdoors boundary
207
+ conditions will be used, meaning that most Floors will typically
208
+ be excluded unless they represent the underside of a cantilever.
209
+ Choose from the following. (Default: Wall).
210
+
211
+ * Wall
212
+ * Roof
213
+ * Floor
214
+ * All
215
+
216
+ punched_geometry: Boolean to note whether the punched_geometry of the faces
217
+ should be used (True) with the areas of sub-faces removed from the grid
218
+ or the full geometry should be used (False). (Default:False).
219
+
220
+ Returns:
221
+ A honeybee_radiance SensorGrid generated from the exterior Faces
222
+ of the room. Will be None if the Room has no exterior Faces.
223
+
224
+ Usage:
225
+
226
+ .. code-block:: python
227
+
228
+ from honeybee.room import Room
229
+ room = Room.from_box(3.0, 6.0, 3.2, 180)
230
+ s_grid = room.properties.radiance.generate_exterior_face_sensor_grid(0.5)
231
+ """
232
+ # generate the mesh grid from the exterior Faces
233
+ face_grid = self.host.generate_exterior_face_grid(
234
+ dimension, offset, face_type, punched_geometry)
235
+ if face_grid is None: # no valid mesh could be generated
236
+ return None
237
+ # create the sensor grid from the mesh
238
+ f_nm = 'Faces' if face_type.title() == 'All' else face_type.title()
239
+ grid_name = '{}_Exterior{}'.format(self.host.display_name, f_nm)
240
+ sensor_grid = SensorGrid.from_mesh3d(clean_rad_string(grid_name), face_grid)
241
+ sensor_grid.room_identifier = self.host.identifier
242
+ sensor_grid.display_name = self.host.display_name
243
+ return sensor_grid
244
+
245
+ def generate_exterior_aperture_sensor_grid(
246
+ self, dimension, offset=0.1, aperture_type='All'):
247
+ """Get a radiance SensorGrid generated from the exterior Apertures of this room.
248
+
249
+ Will be None if the Room has no exterior Apertures.
250
+
251
+ The output grid will have this room referenced in its room_identifier
252
+ property. It will also include a Mesh3D object with faces that align
253
+ with the grid positions under the grid's mesh property.
254
+
255
+ Args:
256
+ dimension: The dimension of the grid cells as a number.
257
+ offset: A number for how far to offset the grid from the base face.
258
+ Positive numbers indicate an offset towards the exterior while
259
+ negative numbers indicate an offset towards the interior, essentially
260
+ modeling the value of sun on the building interior. (Default
261
+ is 0.1, which will offset the grid to be 0.1 unit from the faces).
262
+ aperture_type: Text to specify the type of Aperture that will be used to
263
+ generate grids. Window indicates Apertures in Walls. Skylights
264
+ are in parent Roof faces. Choose from the following. (Default: All).
265
+
266
+ * Window
267
+ * Skylight
268
+ * All
269
+
270
+ Returns:
271
+ A honeybee_radiance SensorGrid generated from the exterior Apertures
272
+ of the room. Will be None if the Room has no exterior Apertures or
273
+ if the grid size is too large for the Apertures.
274
+
275
+ Usage:
276
+
277
+ .. code-block:: python
278
+
279
+ from honeybee.room import Room
280
+ room = Room.from_box(3.0, 6.0, 3.2, 180)
281
+ room[3].apertures_by_ratio(0.4)
282
+ s_grid = room.properties.radiance.generate_exterior_aperture_sensor_grid(0.5)
283
+ """
284
+ # generate the mesh grid from the exterior Apertures
285
+ ap_grid = self.host.generate_exterior_aperture_grid(
286
+ dimension, offset, aperture_type)
287
+ if ap_grid is None: # no valid mesh could be generated
288
+ return None
289
+ # create the sensor grid from the mesh
290
+ f_nm = 'Apertures' if aperture_type.title() == 'All' else aperture_type.title()
291
+ grid_name = '{}_Exterior{}'.format(self.host.display_name, f_nm)
292
+ sensor_grid = SensorGrid.from_mesh3d(clean_rad_string(grid_name), ap_grid)
293
+ sensor_grid.room_identifier = self.host.identifier
294
+ sensor_grid.display_name = self.host.display_name
295
+ return sensor_grid
296
+
297
+ def generate_view(self, direction, up_vector=(0, 0, 1), type='v', h_size=60,
298
+ v_size=60, shift=None, lift=None):
299
+ """Get a single view in the center of the room facing a given direction.
300
+
301
+ Note that the view will be located at the center of the bounding box
302
+ around the room geometry and not the volume centroid. Also note that
303
+ the view may not lie inside the room if the room is highly concave.
304
+
305
+ The output view will have this room referenced in their room_identifier
306
+ property.
307
+
308
+ Args:
309
+ direction: Set the view direction (-vd) vector to (x, y, z). The
310
+ length of this vector indicates the focal distance as needed by
311
+ the pixel depth of field (-pd) in rpict.
312
+ up_vector: Set the view up (-vu) vector (vertical direction) to
313
+ (x, y, z) default: (0, 0, 1).
314
+ type: A single character for the view type (-vt). Choose from the following.
315
+
316
+ * v - Perspective
317
+ * h - Hemispherical fisheye
318
+ * l - Parallel
319
+ * c - Cylindrical panorama
320
+ * a - Angular fisheye
321
+ * s - Planisphere [stereographic] projection
322
+
323
+ For more detailed description about view types check rpict manual
324
+ page: (http://radsite.lbl.gov/radiance/man_html/rpict.1.html)
325
+ h_size: Set the view horizontal size (-vh). For a perspective
326
+ projection (including fisheye views), val is the horizontal field
327
+ of view (in degrees). For a parallel projection, val is the view
328
+ width in world coordinates.
329
+ v_size: Set the view vertical size (-vv). For a perspective
330
+ projection (including fisheye views), val is the horizontal field
331
+ of view (in degrees). For a parallel projection, val is the view
332
+ width in world coordinates.
333
+ shift: Set the view shift (-vs). This is the amount the actual
334
+ image will be shifted to the right of the specified view. This
335
+ option is useful for generating skewed perspectives or rendering
336
+ an image a piece at a time. A value of 1 means that the rendered
337
+ image starts just to the right of the normal view. A value of -1
338
+ would be to the left. Larger or fractional values are permitted
339
+ as well.
340
+ lift: Set the view lift (-vl) to a value. This is the amount the
341
+ actual image will be lifted up from the specified view.
342
+
343
+ Returns:
344
+ A honeybee_radiance View generated in the center of the Room.
345
+
346
+ Usage:
347
+
348
+ .. code-block:: python
349
+
350
+ from honeybee.room import Room
351
+ room = Room.from_box(3.0, 6.0, 3.2, 180)
352
+ south_face = room[3]
353
+ south_face.apertures_by_ratio(0.4, 0.01)
354
+ view = room.properties.radiance.generate_view((0, -1, 0))
355
+ """
356
+ pos = (self.host.center.x, self.host.center.y, self.host.center.z)
357
+ view = View(self.host.identifier, pos, direction, up_vector, type,
358
+ h_size, v_size, shift, lift)
359
+ view.room_identifier = self.host.identifier
360
+ view.display_name = self.host.display_name
361
+ return view
362
+
363
+ @classmethod
364
+ def from_dict(cls, data, host):
365
+ """Create RoomRadianceProperties from a dictionary.
366
+
367
+ Note that the dictionary must be a non-abridged version for this
368
+ classmethod to work.
369
+
370
+ Args:
371
+ data: A dictionary representation of RoomRadianceProperties with the
372
+ format below.
373
+ host: A Room object that hosts these properties.
374
+
375
+ .. code-block:: python
376
+
377
+ {
378
+ 'type': 'RoomRadianceProperties',
379
+ 'modifier_set': {}, # ModifierSet dictionary
380
+ }
381
+ """
382
+ assert data['type'] == 'RoomRadianceProperties', \
383
+ 'Expected RoomRadianceProperties. Got {}.'.format(data['type'])
384
+
385
+ new_prop = cls(host)
386
+ if 'modifier_set' in data and data['modifier_set'] is not None:
387
+ new_prop.modifier_set = ModifierSet.from_dict(data['modifier_set'])
388
+ return new_prop
389
+
390
+ def apply_properties_from_dict(self, abridged_data, modifier_sets):
391
+ """Apply properties from a RoomRadiancePropertiesAbridged dictionary.
392
+
393
+ Args:
394
+ abridged_data: A RoomRadiancePropertiesAbridged dictionary (typically
395
+ coming from a Model) with the format below.
396
+ modifier_sets: A dictionary of ModifierSets with identifiers of the sets
397
+ as keys, which will be used to re-assign modifier_sets.
398
+
399
+ .. code-block:: python
400
+
401
+ {
402
+ 'type': 'RoomRadiancePropertiesAbridged',
403
+ 'modifier_set': str, # ModifierSet identifier
404
+ }
405
+ """
406
+ if 'modifier_set' in abridged_data and abridged_data['modifier_set'] is not None:
407
+ self.modifier_set = modifier_sets[abridged_data['modifier_set']]
408
+
409
+ def to_dict(self, abridged=False):
410
+ """Return Room radiance properties as a dictionary.
411
+
412
+ Args:
413
+ abridged: Boolean for whether the full dictionary of the Room should
414
+ be written (False) or just the identifier of the the individual
415
+ properties (True). Default: False.
416
+ """
417
+ base = {'radiance': {}}
418
+ base['radiance']['type'] = 'RoomRadianceProperties' if not \
419
+ abridged else 'RoomRadiancePropertiesAbridged'
420
+
421
+ # write the ModifierSet into the dictionary
422
+ if self._modifier_set is not None:
423
+ base['radiance']['modifier_set'] = \
424
+ self._modifier_set.identifier if abridged else \
425
+ self._modifier_set.to_dict()
426
+
427
+ return base
428
+
429
+ def duplicate(self, new_host=None):
430
+ """Get a copy of this object.
431
+
432
+ Args:
433
+ new_host: A new Room object that hosts these properties.
434
+ If None, the properties will be duplicated with the same host.
435
+ """
436
+ _host = new_host or self._host
437
+ new_room = RoomRadianceProperties(_host, self._modifier_set)
438
+ return new_room
439
+
440
+ def is_equivalent(self, other):
441
+ """Check to see if these Radiance properties are equivalent to another object.
442
+ """
443
+ if not is_equivalent(self._modifier_set, other._modifier_set):
444
+ return False
445
+ return True
446
+
447
+ def _base_sensor_mesh(self, x_dim, y_dim, offset, remove_out, wall_offset):
448
+ """Get a base Mesh3D from the Room floors to be used for sensor girds."""
449
+ # generate the mesh grid from the floor Faces
450
+ floor_grid = self.host.generate_grid(x_dim, y_dim, offset)
451
+ if floor_grid is None: # no floors in the host Room
452
+ return None
453
+
454
+ # remove any outdoor sensors if this has been requested
455
+ if remove_out:
456
+ geo = self.host.geometry
457
+ pattern = [geo.is_point_inside(pt) for pt in floor_grid.face_centroids]
458
+ try:
459
+ floor_grid, vertex_pattern = floor_grid.remove_faces(pattern)
460
+ except AssertionError: # the grid lies completely outside of the room
461
+ return None
462
+
463
+ # remove any sensors within a certain distance of the walls, if requested
464
+ if wall_offset >= x_dim / 2 or (y_dim is not None and wall_offset >= y_dim / 2):
465
+ wall_geos = [f.geometry for f in self.host.faces if isinstance(f.type, Wall)]
466
+ pattern = []
467
+ for pt in floor_grid.face_centroids:
468
+ for wg in wall_geos:
469
+ close_pt = wg.plane.closest_point(pt)
470
+ p_dist = pt.distance_to_point(close_pt)
471
+ if p_dist <= wall_offset:
472
+ close_pt_2d = wg.plane.xyz_to_xy(close_pt)
473
+ g_dist = wg.polygon2d.distance_to_point(close_pt_2d)
474
+ f_dist = math.sqrt(p_dist ** 2 + g_dist ** 2)
475
+ if f_dist <= wall_offset:
476
+ pattern.append(False)
477
+ break
478
+ else:
479
+ pattern.append(True)
480
+ try:
481
+ floor_grid, vertex_pattern = floor_grid.remove_faces(pattern)
482
+ except AssertionError: # the grid lies completely outside of the room
483
+ return None
484
+ return floor_grid
485
+
486
+ def ToString(self):
487
+ return self.__repr__()
488
+
489
+ def __repr__(self):
490
+ return 'Room Radiance Properties: [host: {}]'.format(self.host.display_name)
@@ -0,0 +1,186 @@
1
+ # coding=utf-8
2
+ """Shade Radiance Properties."""
3
+ from ._base import _DynamicRadianceProperties
4
+ from ..modifier import Modifier
5
+ from ..dynamic.state import RadianceShadeState
6
+ from ..lib.modifiers import generic_context
7
+ from ..lib.modifiersets import generic_modifier_set_visible
8
+
9
+
10
+ class ShadeRadianceProperties(_DynamicRadianceProperties):
11
+ """Radiance Properties for Honeybee Shade.
12
+
13
+ Args:
14
+ host: A honeybee_core Shade object that hosts these properties.
15
+ modifier: A Honeybee Radiance Modifier object for the shade. If None,
16
+ it will be set by the parent Room ModifierSet or the Honeybee
17
+ default generic ModifierSet.
18
+ modifier_blk: A Honeybee Radiance Modifier object to be used for this
19
+ shade in direct solar simulations and in isolation studies (assessing
20
+ the contribution of individual Apertures). If None, this will be
21
+ a completely black material if the Shade's modifier is opaque and
22
+ will be equal to the modifier if the Shade's modifier is non-opaque.
23
+ dynamic_group_identifier: An optional string to note the dynamic group
24
+ to which the Shade is a part of. Shades sharing the same
25
+ dynamic_group_identifier will have their states change in unison.
26
+ If None, the Shade is assumed to be static.
27
+
28
+ Properties:
29
+ * host
30
+ * modifier
31
+ * modifier_blk
32
+ * dynamic_group_identifier
33
+ * states
34
+ * state_count
35
+ * is_opaque
36
+ * is_modifier_set_on_object
37
+ * is_blk_overridden
38
+ """
39
+
40
+ __slots__ = ()
41
+
42
+ def __init__(self, host, modifier=None, modifier_blk=None,
43
+ dynamic_group_identifier=None):
44
+ """Initialize Shade radiance properties."""
45
+ _DynamicRadianceProperties.__init__(
46
+ self, host, modifier, modifier_blk, dynamic_group_identifier)
47
+
48
+ @property
49
+ def modifier(self):
50
+ """Get or set the Shade modifier.
51
+
52
+ If the modifier is not set on the shade-level, then it will be assigned
53
+ based on the ModifierSet assigned to the parent Room. If the parent Room's
54
+ ModifierSet has no modifier for the Shade type, it will be assigned using the
55
+ honeybee default generic ModifierSet. If there is no parent Room, it will
56
+ be the generic context material.
57
+ """
58
+ if self._modifier: # set by user
59
+ return self._modifier
60
+ elif not self._host.has_parent: # orphaned shade
61
+ return generic_context if self._host.is_detached else \
62
+ generic_modifier_set_visible.shade_set.exterior_modifier
63
+ else: # shade with a parent modifier set
64
+ m_set = self._parent_modifier_set(self._host.parent)
65
+ if m_set is None:
66
+ m_set = generic_modifier_set_visible
67
+ return m_set.get_shade_modifier(self._host.is_indoor)
68
+
69
+ @modifier.setter
70
+ def modifier(self, value):
71
+ if value is not None:
72
+ assert isinstance(value, Modifier), \
73
+ 'Expected Radiance Modifier for shade. Got {}'.format(type(value))
74
+ value.lock() # lock editing in case modifier has multiple references
75
+ self._modifier = value
76
+
77
+ @classmethod
78
+ def from_dict(cls, data, host):
79
+ """Create ShadeRadianceProperties from a dictionary.
80
+
81
+ Note that the dictionary must be a non-abridged version for this
82
+ classmethod to work.
83
+
84
+ Args:
85
+ data: A dictionary representation of ShadeRadianceProperties with the
86
+ format below.
87
+ host: A Shade object that hosts these properties.
88
+
89
+ .. code-block:: python
90
+
91
+ {
92
+ 'type': 'ShadeRadianceProperties',
93
+ 'modifier': {}, # A Honeybee Radiance Modifier dictionary
94
+ 'modifier_blk': {}, # A Honeybee Radiance Modifier dictionary
95
+ 'dynamic_group_identifier': str, # An optional dynamic group identifier
96
+ 'states': [] # An optional list of states
97
+ }
98
+ """
99
+ assert data['type'] == 'ShadeRadianceProperties', \
100
+ 'Expected ShadeRadianceProperties. Got {}.'.format(data['type'])
101
+ new_prop = cls(host)
102
+ new_prop = cls._restore_modifiers_from_dict(new_prop, data)
103
+ return cls._restore_states_from_dict(new_prop, data)
104
+
105
+ def apply_properties_from_dict(self, abridged_data, modifiers):
106
+ """Apply properties from a ShadeRadiancePropertiesAbridged dictionary.
107
+
108
+ Args:
109
+ abridged_data: A ShadeRadiancePropertiesAbridged dictionary (typically
110
+ coming from a Model) with the format below.
111
+ modifiers: A dictionary of modifiers with modifier identifiers as keys,
112
+ which will be used to re-assign modifiers.
113
+
114
+ .. code-block:: python
115
+
116
+ {
117
+ 'type': 'ShadeRadiancePropertiesAbridged',
118
+ 'modifier': str, # A Honeybee Radiance Modifier identifier
119
+ 'modifier_blk': str, # A Honeybee Radiance Modifier identifier
120
+ 'dynamic_group_identifier': str, # An optional dynamic group identifier
121
+ 'states': [] # An optional list of states
122
+ }
123
+ """
124
+ self._apply_modifiers_from_dict(abridged_data, modifiers)
125
+ self._apply_states_from_dict(abridged_data, modifiers)
126
+
127
+ def to_dict(self, abridged=False):
128
+ """Return radiance properties as a dictionary.
129
+
130
+ Args:
131
+ abridged: Boolean to note whether the full dictionary describing the
132
+ object should be returned (False) or just an abridged version (True).
133
+ Default: False.
134
+ """
135
+ base = {'radiance': {}}
136
+ base['radiance']['type'] = 'ShadeRadianceProperties' if not \
137
+ abridged else 'ShadeRadiancePropertiesAbridged'
138
+ self._add_modifiers_to_dict(base, abridged)
139
+ return self._add_states_to_dict(base, abridged)
140
+
141
+ def _check_state(self, obj):
142
+ assert isinstance(obj, RadianceShadeState), \
143
+ 'Expected RadianceShadeState. Got {}.'.format(type(obj))
144
+ assert obj.parent is None, \
145
+ 'RadianceShadeState cannot already have a parent object.'
146
+ obj._parent = self.host
147
+ return obj
148
+
149
+ def _apply_states_from_dict(self, abridged_data, modifiers):
150
+ """Apply states from an Abridged dictionary.
151
+
152
+ Args:
153
+ abridged_data: An Abridged dictionary (typically coming from a Model).
154
+ modifiers: A dictionary of modifiers with modifier identifiers as keys,
155
+ which will be used to re-assign modifiers.
156
+ """
157
+ if 'dynamic_group_identifier' in abridged_data and \
158
+ abridged_data['dynamic_group_identifier'] is not None:
159
+ self.dynamic_group_identifier = abridged_data['dynamic_group_identifier']
160
+ if 'states' in abridged_data and abridged_data['states'] is not None:
161
+ self.states = [RadianceShadeState.from_dict_abridged(st, modifiers)
162
+ for st in abridged_data['states']]
163
+
164
+ @staticmethod
165
+ def _restore_states_from_dict(new_prop, data):
166
+ """Restore states from a data dictionary to a new properties object."""
167
+ if 'dynamic_group_identifier' in data and \
168
+ data['dynamic_group_identifier'] is not None:
169
+ new_prop.dynamic_group_identifier = data['dynamic_group_identifier']
170
+ if 'states' in data and data['states'] is not None:
171
+ new_prop.states = [RadianceShadeState.from_dict(shd)
172
+ for shd in data['states']]
173
+ return new_prop
174
+
175
+ @staticmethod
176
+ def _parent_modifier_set(host_parent):
177
+ """Recursively search through host parents to find a ModifierSet."""
178
+ if hasattr(host_parent.properties.radiance, 'modifier_set'):
179
+ return host_parent.properties.radiance.modifier_set
180
+ elif host_parent.has_parent:
181
+ return ShadeRadianceProperties._parent_modifier_set(host_parent.parent)
182
+ else:
183
+ return None
184
+
185
+ def __repr__(self):
186
+ return 'Shade Radiance Properties:\n host: {}'.format(self.host.identifier)