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.
- honeybee_radiance/__init__.py +11 -0
- honeybee_radiance/__main__.py +4 -0
- honeybee_radiance/_extend_honeybee.py +93 -0
- honeybee_radiance/cli/__init__.py +88 -0
- honeybee_radiance/cli/dc.py +400 -0
- honeybee_radiance/cli/edit.py +529 -0
- honeybee_radiance/cli/glare.py +118 -0
- honeybee_radiance/cli/grid.py +859 -0
- honeybee_radiance/cli/lib.py +458 -0
- honeybee_radiance/cli/modifier.py +133 -0
- honeybee_radiance/cli/mtx.py +226 -0
- honeybee_radiance/cli/multiphase.py +1034 -0
- honeybee_radiance/cli/octree.py +640 -0
- honeybee_radiance/cli/postprocess.py +1186 -0
- honeybee_radiance/cli/raytrace.py +219 -0
- honeybee_radiance/cli/rpict.py +125 -0
- honeybee_radiance/cli/schedule.py +56 -0
- honeybee_radiance/cli/setconfig.py +63 -0
- honeybee_radiance/cli/sky.py +545 -0
- honeybee_radiance/cli/study.py +66 -0
- honeybee_radiance/cli/sunpath.py +331 -0
- honeybee_radiance/cli/threephase.py +255 -0
- honeybee_radiance/cli/translate.py +400 -0
- honeybee_radiance/cli/util.py +121 -0
- honeybee_radiance/cli/view.py +261 -0
- honeybee_radiance/cli/viewfactor.py +347 -0
- honeybee_radiance/config.json +6 -0
- honeybee_radiance/config.py +427 -0
- honeybee_radiance/dictutil.py +50 -0
- honeybee_radiance/dynamic/__init__.py +5 -0
- honeybee_radiance/dynamic/group.py +479 -0
- honeybee_radiance/dynamic/multiphase.py +557 -0
- honeybee_radiance/dynamic/state.py +718 -0
- honeybee_radiance/dynamic/stategeo.py +352 -0
- honeybee_radiance/geometry/__init__.py +13 -0
- honeybee_radiance/geometry/bubble.py +42 -0
- honeybee_radiance/geometry/cone.py +215 -0
- honeybee_radiance/geometry/cup.py +54 -0
- honeybee_radiance/geometry/cylinder.py +197 -0
- honeybee_radiance/geometry/geometrybase.py +37 -0
- honeybee_radiance/geometry/instance.py +40 -0
- honeybee_radiance/geometry/mesh.py +38 -0
- honeybee_radiance/geometry/polygon.py +174 -0
- honeybee_radiance/geometry/ring.py +214 -0
- honeybee_radiance/geometry/source.py +182 -0
- honeybee_radiance/geometry/sphere.py +178 -0
- honeybee_radiance/geometry/tube.py +46 -0
- honeybee_radiance/lib/__init__.py +1 -0
- honeybee_radiance/lib/_loadmodifiers.py +72 -0
- honeybee_radiance/lib/_loadmodifiersets.py +69 -0
- honeybee_radiance/lib/modifiers.py +58 -0
- honeybee_radiance/lib/modifiersets.py +63 -0
- honeybee_radiance/lightpath.py +204 -0
- honeybee_radiance/lightsource/__init__.py +1 -0
- honeybee_radiance/lightsource/_gendaylit.py +479 -0
- honeybee_radiance/lightsource/dictutil.py +49 -0
- honeybee_radiance/lightsource/ground.py +160 -0
- honeybee_radiance/lightsource/sky/__init__.py +7 -0
- honeybee_radiance/lightsource/sky/_skybase.py +177 -0
- honeybee_radiance/lightsource/sky/certainirradiance.py +232 -0
- honeybee_radiance/lightsource/sky/cie.py +378 -0
- honeybee_radiance/lightsource/sky/climatebased.py +501 -0
- honeybee_radiance/lightsource/sky/hemisphere.py +160 -0
- honeybee_radiance/lightsource/sky/skydome.py +113 -0
- honeybee_radiance/lightsource/sky/skymatrix.py +163 -0
- honeybee_radiance/lightsource/sky/strutil.py +34 -0
- honeybee_radiance/lightsource/sky/sunmatrix.py +212 -0
- honeybee_radiance/lightsource/sunpath.py +247 -0
- honeybee_radiance/modifier/__init__.py +3 -0
- honeybee_radiance/modifier/material/__init__.py +30 -0
- honeybee_radiance/modifier/material/absdf.py +477 -0
- honeybee_radiance/modifier/material/antimatter.py +54 -0
- honeybee_radiance/modifier/material/ashik2.py +51 -0
- honeybee_radiance/modifier/material/brtdfunc.py +81 -0
- honeybee_radiance/modifier/material/bsdf.py +292 -0
- honeybee_radiance/modifier/material/dielectric.py +53 -0
- honeybee_radiance/modifier/material/glass.py +431 -0
- honeybee_radiance/modifier/material/glow.py +246 -0
- honeybee_radiance/modifier/material/illum.py +51 -0
- honeybee_radiance/modifier/material/interface.py +49 -0
- honeybee_radiance/modifier/material/light.py +206 -0
- honeybee_radiance/modifier/material/materialbase.py +36 -0
- honeybee_radiance/modifier/material/metal.py +167 -0
- honeybee_radiance/modifier/material/metal2.py +41 -0
- honeybee_radiance/modifier/material/metdata.py +41 -0
- honeybee_radiance/modifier/material/metfunc.py +41 -0
- honeybee_radiance/modifier/material/mirror.py +340 -0
- honeybee_radiance/modifier/material/mist.py +86 -0
- honeybee_radiance/modifier/material/plasdata.py +58 -0
- honeybee_radiance/modifier/material/plasfunc.py +59 -0
- honeybee_radiance/modifier/material/plastic.py +354 -0
- honeybee_radiance/modifier/material/plastic2.py +58 -0
- honeybee_radiance/modifier/material/prism1.py +57 -0
- honeybee_radiance/modifier/material/prism2.py +48 -0
- honeybee_radiance/modifier/material/spotlight.py +50 -0
- honeybee_radiance/modifier/material/trans.py +518 -0
- honeybee_radiance/modifier/material/trans2.py +49 -0
- honeybee_radiance/modifier/material/transdata.py +50 -0
- honeybee_radiance/modifier/material/transfunc.py +53 -0
- honeybee_radiance/modifier/mixture/__init__.py +6 -0
- honeybee_radiance/modifier/mixture/mixdata.py +49 -0
- honeybee_radiance/modifier/mixture/mixfunc.py +54 -0
- honeybee_radiance/modifier/mixture/mixpict.py +52 -0
- honeybee_radiance/modifier/mixture/mixtext.py +66 -0
- honeybee_radiance/modifier/mixture/mixturebase.py +28 -0
- honeybee_radiance/modifier/modifierbase.py +40 -0
- honeybee_radiance/modifier/pattern/__init__.py +9 -0
- honeybee_radiance/modifier/pattern/brightdata.py +49 -0
- honeybee_radiance/modifier/pattern/brightfunc.py +47 -0
- honeybee_radiance/modifier/pattern/brighttext.py +81 -0
- honeybee_radiance/modifier/pattern/colordata.py +56 -0
- honeybee_radiance/modifier/pattern/colorfunc.py +47 -0
- honeybee_radiance/modifier/pattern/colorpict.py +54 -0
- honeybee_radiance/modifier/pattern/colortext.py +73 -0
- honeybee_radiance/modifier/pattern/patternbase.py +34 -0
- honeybee_radiance/modifier/texture/__init__.py +4 -0
- honeybee_radiance/modifier/texture/texdata.py +29 -0
- honeybee_radiance/modifier/texture/texfunc.py +26 -0
- honeybee_radiance/modifier/texture/texturebase.py +27 -0
- honeybee_radiance/modifierset.py +1091 -0
- honeybee_radiance/mutil.py +60 -0
- honeybee_radiance/postprocess/__init__.py +1 -0
- honeybee_radiance/postprocess/annual.py +108 -0
- honeybee_radiance/postprocess/annualdaylight.py +425 -0
- honeybee_radiance/postprocess/annualglare.py +201 -0
- honeybee_radiance/postprocess/annualirradiance.py +187 -0
- honeybee_radiance/postprocess/electriclight.py +119 -0
- honeybee_radiance/postprocess/en17037.py +261 -0
- honeybee_radiance/postprocess/leed.py +304 -0
- honeybee_radiance/postprocess/solartracking.py +90 -0
- honeybee_radiance/primitive.py +554 -0
- honeybee_radiance/properties/__init__.py +1 -0
- honeybee_radiance/properties/_base.py +390 -0
- honeybee_radiance/properties/aperture.py +197 -0
- honeybee_radiance/properties/door.py +198 -0
- honeybee_radiance/properties/face.py +123 -0
- honeybee_radiance/properties/model.py +1291 -0
- honeybee_radiance/properties/room.py +490 -0
- honeybee_radiance/properties/shade.py +186 -0
- honeybee_radiance/properties/shademesh.py +116 -0
- honeybee_radiance/putil.py +44 -0
- honeybee_radiance/reader.py +214 -0
- honeybee_radiance/sensor.py +166 -0
- honeybee_radiance/sensorgrid.py +1008 -0
- honeybee_radiance/view.py +1101 -0
- honeybee_radiance/writer.py +951 -0
- honeybee_radiance-1.66.190.dist-info/METADATA +89 -0
- honeybee_radiance-1.66.190.dist-info/RECORD +152 -0
- honeybee_radiance-1.66.190.dist-info/WHEEL +5 -0
- honeybee_radiance-1.66.190.dist-info/entry_points.txt +2 -0
- honeybee_radiance-1.66.190.dist-info/licenses/LICENSE +661 -0
- honeybee_radiance-1.66.190.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
"""Base class for all Radiance Primitives.
|
|
2
|
+
|
|
3
|
+
The term "Primitive" can refer to either a geometry object or a modifer that can
|
|
4
|
+
be applied to geometry in order to change its reflectance, transmittance, etc.
|
|
5
|
+
All primitives share a similar format for how they are represented within .rad
|
|
6
|
+
files and the Primitive class provides common code used to serialize/de-serialize
|
|
7
|
+
such objects from .rad strings among other functionalities.
|
|
8
|
+
|
|
9
|
+
Because the Primitive class is so abstract, you most likely want to use one of
|
|
10
|
+
the sub-classes of Primitive instead of using this class directly. You will find
|
|
11
|
+
such sub-classes in the honeybee_radiance.modifier and honeybee_radiance.geometry
|
|
12
|
+
sub-packages. More information on Radiance Primitives can be found at:
|
|
13
|
+
|
|
14
|
+
http://radsite.lbl.gov/radiance/refer/ray.html
|
|
15
|
+
"""
|
|
16
|
+
from honeybee.typing import valid_rad_string, list_with_length
|
|
17
|
+
from honeybee._lockable import lockable
|
|
18
|
+
|
|
19
|
+
from honeybee_radiance.reader import string_to_dicts
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Void(object):
|
|
23
|
+
"""Void modifier.
|
|
24
|
+
|
|
25
|
+
Properties:
|
|
26
|
+
* identifier
|
|
27
|
+
* display_name
|
|
28
|
+
* is_modifier
|
|
29
|
+
* is_opaque
|
|
30
|
+
"""
|
|
31
|
+
__slots__ = ()
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def identifier(self):
|
|
35
|
+
"""Void."""
|
|
36
|
+
return 'void'
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def display_name(self):
|
|
40
|
+
"""Void."""
|
|
41
|
+
return 'void'
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def is_modifier(self):
|
|
45
|
+
"""True."""
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def is_opaque(self):
|
|
50
|
+
"""False for a void."""
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def is_void(self):
|
|
55
|
+
"""True for a void."""
|
|
56
|
+
return True
|
|
57
|
+
|
|
58
|
+
def to_radiance(self):
|
|
59
|
+
"""Return full radiance definition."""
|
|
60
|
+
return 'void'
|
|
61
|
+
|
|
62
|
+
def to_dict(self):
|
|
63
|
+
"""Return void."""
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def from_dict(cls, value):
|
|
68
|
+
return cls()
|
|
69
|
+
|
|
70
|
+
def __key(self):
|
|
71
|
+
"""A tuple based on the object properties, useful for hashing."""
|
|
72
|
+
return (self.identifier,)
|
|
73
|
+
|
|
74
|
+
def __hash__(self):
|
|
75
|
+
return hash(self.__key())
|
|
76
|
+
|
|
77
|
+
def __eq__(self, other):
|
|
78
|
+
return isinstance(other, self.__class__) and \
|
|
79
|
+
self.__key() == other.__key()
|
|
80
|
+
|
|
81
|
+
def __ne__(self, other):
|
|
82
|
+
return not self.__eq__(other)
|
|
83
|
+
|
|
84
|
+
def ToString(self):
|
|
85
|
+
"""Overwrite .NET ToString."""
|
|
86
|
+
return self.to_radiance()
|
|
87
|
+
|
|
88
|
+
def __repr__(self):
|
|
89
|
+
return self.to_radiance()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
VOID = Void()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@lockable
|
|
96
|
+
class Primitive(object):
|
|
97
|
+
"""Base class for Radiance Primitives.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
identifier: Text string for a unique Primitive ID. Must not contain spaces
|
|
101
|
+
or special characters. This will be used to identify the object across
|
|
102
|
+
a model and in the exported Radiance files.
|
|
103
|
+
modifier: Modifier. It can be primitive, mixture, texture or pattern.
|
|
104
|
+
(Default: None).
|
|
105
|
+
values: An array 3 arrays for primitive data. Each of the 3 sub-arrays
|
|
106
|
+
refer to a line number in the radiance primitive definitions and the
|
|
107
|
+
values in each array correspond to values occurring within each line.
|
|
108
|
+
For example, [[], [], ['0.500', '0.500', '0.500', '0.000', '0.050']]
|
|
109
|
+
corresponds to values one would find for a Plastic material.
|
|
110
|
+
(Default: [[], [], []]).
|
|
111
|
+
is_opaque: A boolean to indicate whether this primitive is opaque.
|
|
112
|
+
dependencies: A list of primitives that this primitive depends on. This
|
|
113
|
+
argument is only useful for defining advanced primitives that are
|
|
114
|
+
defined based on other primitives. (Default: []).
|
|
115
|
+
|
|
116
|
+
Properties:
|
|
117
|
+
* identifier
|
|
118
|
+
* display_name
|
|
119
|
+
* values
|
|
120
|
+
* modifier
|
|
121
|
+
* dependencies
|
|
122
|
+
* is_geometry
|
|
123
|
+
* is_modifier
|
|
124
|
+
* is_material
|
|
125
|
+
* is_texture
|
|
126
|
+
* is_pattern
|
|
127
|
+
* is_mixture
|
|
128
|
+
* is_opaque
|
|
129
|
+
* is_void
|
|
130
|
+
"""
|
|
131
|
+
__slots__ = ('_identifier', '_display_name', '_modifier', '_values',
|
|
132
|
+
'_is_opaque', '_dependencies', '_type', '_locked')
|
|
133
|
+
|
|
134
|
+
# All Radiance geometry types
|
|
135
|
+
GEOMETRYTYPES = set(('source', 'sphere', 'bubble', 'polygon', 'cone', 'cup',
|
|
136
|
+
'cylinder', 'tube', 'ring', 'instance', 'mesh'))
|
|
137
|
+
|
|
138
|
+
# All Radiance material types
|
|
139
|
+
MATERIALTYPES = \
|
|
140
|
+
set(('plastic', 'glass', 'trans', 'metal', 'mirror', 'illum',
|
|
141
|
+
'mixedfunc', 'dielectric', 'transdata', 'light', 'glow', 'BSDF',
|
|
142
|
+
'aBSDF', 'spotlight', 'prism1', 'prism2', 'mist', 'plastic2',
|
|
143
|
+
'metal2', 'trans2', 'ashik2', 'dielectric', 'interface',
|
|
144
|
+
'plasfunc', 'metfunc', 'transfunc', 'BRTDfunc',
|
|
145
|
+
'plasdata', 'metdata', 'transdata', 'antimatter'))
|
|
146
|
+
|
|
147
|
+
TEXTURETYPES = set(('texfunc', 'texdata'))
|
|
148
|
+
|
|
149
|
+
PATTERNTYPES = set(('colorfunc', 'brightfunc', 'colordata', 'brightdata',
|
|
150
|
+
'colorpict', 'colortext', 'brighttext'))
|
|
151
|
+
|
|
152
|
+
MIXTURETYPES = set(('mixfunc', 'mixdata', 'mixpict', 'mixtext'))
|
|
153
|
+
|
|
154
|
+
# All modifier types (everything except geometry)
|
|
155
|
+
MODIFIERTYPES = set().union(MATERIALTYPES, MIXTURETYPES, TEXTURETYPES, PATTERNTYPES)
|
|
156
|
+
|
|
157
|
+
# All Radiance primitive types
|
|
158
|
+
TYPES = set().union(GEOMETRYTYPES, MODIFIERTYPES)
|
|
159
|
+
|
|
160
|
+
# Modifiers that are not usually opaque. This will be used to set is_opaque property
|
|
161
|
+
# if it is not overridded by the user by setting the is_opaque property
|
|
162
|
+
NONEOPAQUETYPES = set(('glass', 'trans', 'trans2', 'transdata', 'transfunc',
|
|
163
|
+
'dielectric', 'BSDF', 'aBSDF', 'mixfunc', 'BRTDfunc', 'mist',
|
|
164
|
+
'prism1', 'prism2'))
|
|
165
|
+
|
|
166
|
+
def __init__(self, identifier, modifier=None, values=None, is_opaque=None,
|
|
167
|
+
dependencies=None):
|
|
168
|
+
"""Create primitive base."""
|
|
169
|
+
self.identifier = identifier
|
|
170
|
+
self._display_name = None
|
|
171
|
+
self.type = self.__class__.__name__.lower()
|
|
172
|
+
self.modifier = modifier
|
|
173
|
+
self.values = values or [[], [], []]
|
|
174
|
+
self._is_opaque = is_opaque
|
|
175
|
+
self._dependencies = []
|
|
176
|
+
dependencies = dependencies or []
|
|
177
|
+
for dep in dependencies:
|
|
178
|
+
self.add_dependent(dep)
|
|
179
|
+
|
|
180
|
+
@classmethod
|
|
181
|
+
def from_string(cls, primitive_string):
|
|
182
|
+
"""Create a Radiance primitive from a string.
|
|
183
|
+
|
|
184
|
+
If the primitive modifier is not void or it has other dependencies,
|
|
185
|
+
the modifier and/or dependencies must also be part of the input string.
|
|
186
|
+
"""
|
|
187
|
+
pr_dict = string_to_dicts(primitive_string)
|
|
188
|
+
assert len(pr_dict) == 1, \
|
|
189
|
+
'Input string includes more than one Radiance objects.'
|
|
190
|
+
return cls.from_primitive_dict(pr_dict[0])
|
|
191
|
+
|
|
192
|
+
@classmethod
|
|
193
|
+
def from_primitive_dict(cls, primitive_dict):
|
|
194
|
+
"""Initialize the object from a primitive dict.
|
|
195
|
+
|
|
196
|
+
The primitive_dict is a dictionary following the base Primitive schema
|
|
197
|
+
of a Radiance object. This base Primitive schema is the same for all
|
|
198
|
+
Radiance Primitives (including Modifiers and Geometry) whereas the
|
|
199
|
+
from_dict classmethod accepts a different schema that is customized
|
|
200
|
+
to each subclass inheriting from the Radiance Primitive.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
data: A dictionary in the format below
|
|
204
|
+
|
|
205
|
+
.. code-block:: python
|
|
206
|
+
|
|
207
|
+
{
|
|
208
|
+
"modifier": {}, # primitive modifier (Default: None)
|
|
209
|
+
"type": "", # lowercase string for the primitive type
|
|
210
|
+
"identifier": "", # primitive identifier
|
|
211
|
+
"display_name": "", # primitive display name
|
|
212
|
+
"values": [], # values
|
|
213
|
+
"dependencies": []
|
|
214
|
+
}
|
|
215
|
+
"""
|
|
216
|
+
modifier, dependencies = cls.filter_dict_input(primitive_dict)
|
|
217
|
+
|
|
218
|
+
cls_ = cls(
|
|
219
|
+
identifier=primitive_dict['identifier'],
|
|
220
|
+
modifier=modifier,
|
|
221
|
+
values=primitive_dict['values'],
|
|
222
|
+
dependencies=dependencies
|
|
223
|
+
)
|
|
224
|
+
if 'display_name' in primitive_dict and \
|
|
225
|
+
primitive_dict['display_name'] is not None:
|
|
226
|
+
cls_.display_name = primitive_dict['display_name']
|
|
227
|
+
|
|
228
|
+
if cls_.type == 'primitive':
|
|
229
|
+
cls_.type = primitive_dict['type']
|
|
230
|
+
|
|
231
|
+
return cls_
|
|
232
|
+
|
|
233
|
+
@classmethod
|
|
234
|
+
def from_dict(cls, data):
|
|
235
|
+
"""Initialize the object from a dictionary.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
data: A dictionary in the format below.
|
|
239
|
+
|
|
240
|
+
.. code-block:: python
|
|
241
|
+
|
|
242
|
+
{
|
|
243
|
+
"modifier": {}, # primitive modifier (Default: None)
|
|
244
|
+
"type": "", # lowercase string for the primitive type
|
|
245
|
+
"identifier": "", # primitive identifier
|
|
246
|
+
"display_name": "", # primitive display name
|
|
247
|
+
"values": [], # values
|
|
248
|
+
"dependencies": []
|
|
249
|
+
}
|
|
250
|
+
"""
|
|
251
|
+
return cls.from_primitive_dict(data)
|
|
252
|
+
|
|
253
|
+
@property
|
|
254
|
+
def type(self):
|
|
255
|
+
"""Get or set a string for the primitive type.
|
|
256
|
+
|
|
257
|
+
This should always be lower case in order to match the radiance convention.
|
|
258
|
+
"""
|
|
259
|
+
return self._type
|
|
260
|
+
|
|
261
|
+
@type.setter
|
|
262
|
+
def type(self, type_str):
|
|
263
|
+
_mapper = {'bsdf': 'BSDF', 'absdf': 'aBSDF', 'brtdfunc': 'BRTDfunc'}
|
|
264
|
+
|
|
265
|
+
if type_str != 'primitive':
|
|
266
|
+
if type_str not in self.TYPES:
|
|
267
|
+
# try base classes for subclasses
|
|
268
|
+
for base in self.__class__.__mro__:
|
|
269
|
+
if base.__name__.lower() in _mapper:
|
|
270
|
+
type_str = _mapper[base.__name__.lower()]
|
|
271
|
+
break
|
|
272
|
+
if base.__name__.lower() in self.TYPES:
|
|
273
|
+
type_str = base.__name__.lower()
|
|
274
|
+
break
|
|
275
|
+
|
|
276
|
+
assert type_str in self.TYPES, \
|
|
277
|
+
"%s is not a supported Radiance primitive type." % type_str + \
|
|
278
|
+
"Try one of these primitives:\n%s" % str(self.TYPES)
|
|
279
|
+
|
|
280
|
+
self._type = type_str
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def identifier(self):
|
|
284
|
+
"""Get or set a text string for the unique primitive identifier."""
|
|
285
|
+
return self._identifier
|
|
286
|
+
|
|
287
|
+
@identifier.setter
|
|
288
|
+
def identifier(self, identifier):
|
|
289
|
+
self._identifier = valid_rad_string(identifier)
|
|
290
|
+
|
|
291
|
+
@property
|
|
292
|
+
def display_name(self):
|
|
293
|
+
"""Get or set a string for the object name without any character restrictions.
|
|
294
|
+
|
|
295
|
+
If not set, this will be equal to the identifier.
|
|
296
|
+
"""
|
|
297
|
+
if self._display_name is None:
|
|
298
|
+
return self._identifier
|
|
299
|
+
return self._display_name
|
|
300
|
+
|
|
301
|
+
@display_name.setter
|
|
302
|
+
def display_name(self, value):
|
|
303
|
+
try:
|
|
304
|
+
self._display_name = str(value)
|
|
305
|
+
except UnicodeEncodeError: # Python 2 machine lacking the character set
|
|
306
|
+
self._display_name = value # keep it as unicode
|
|
307
|
+
|
|
308
|
+
@property
|
|
309
|
+
def values(self):
|
|
310
|
+
"""Get or set the values of the current primitive as a list of three lists.
|
|
311
|
+
|
|
312
|
+
Each sub-list represents a line of the primitive's radiance representation
|
|
313
|
+
and contain the properties that define the primitive.
|
|
314
|
+
|
|
315
|
+
Usage:
|
|
316
|
+
|
|
317
|
+
.. code-block:: python
|
|
318
|
+
|
|
319
|
+
# This will erase all values except the first line, which has 9 custom items
|
|
320
|
+
primitive.values = [
|
|
321
|
+
[0.5, 0.5, 0.5, "/usr/oak.pic", ".", "frac(U)", "frac(V)", "-s", 1.1667],
|
|
322
|
+
[],
|
|
323
|
+
[]
|
|
324
|
+
]
|
|
325
|
+
"""
|
|
326
|
+
self._update_values()
|
|
327
|
+
return self._values
|
|
328
|
+
|
|
329
|
+
@values.setter
|
|
330
|
+
def values(self, new_values):
|
|
331
|
+
self._values = list_with_length(new_values, 3, list, 'radiance primitive values')
|
|
332
|
+
|
|
333
|
+
@property
|
|
334
|
+
def modifier(self):
|
|
335
|
+
"""Get or set an object for the primitive modifier."""
|
|
336
|
+
return self._modifier
|
|
337
|
+
|
|
338
|
+
@modifier.setter
|
|
339
|
+
def modifier(self, modifier):
|
|
340
|
+
if not modifier or modifier == 'void':
|
|
341
|
+
self._modifier = VOID
|
|
342
|
+
else:
|
|
343
|
+
try:
|
|
344
|
+
assert modifier.is_modifier, \
|
|
345
|
+
'A {} cannot be a modifier. ' \
|
|
346
|
+
'Modifiers must be materials, mixtures, ' \
|
|
347
|
+
'textures or patterns'.format(type(modifier))
|
|
348
|
+
except AttributeError:
|
|
349
|
+
raise TypeError('Invalid modifier: %s' % modifier)
|
|
350
|
+
except AssertionError as e:
|
|
351
|
+
raise AssertionError(e)
|
|
352
|
+
else:
|
|
353
|
+
self._modifier = modifier
|
|
354
|
+
|
|
355
|
+
@property
|
|
356
|
+
def dependencies(self):
|
|
357
|
+
"""Get list of dependencies for this primitive.
|
|
358
|
+
|
|
359
|
+
Additional dependencies can be added with the add_dependent method.
|
|
360
|
+
"""
|
|
361
|
+
return self._dependencies
|
|
362
|
+
|
|
363
|
+
@property
|
|
364
|
+
def is_geometry(self):
|
|
365
|
+
"""Get a boolean noting whether this object is a Radiance geometry."""
|
|
366
|
+
return False
|
|
367
|
+
|
|
368
|
+
@property
|
|
369
|
+
def is_modifier(self):
|
|
370
|
+
"""Get a boolean indicating whether this object is a Radiance modifier.
|
|
371
|
+
|
|
372
|
+
Modifiers include materials, mixtures, textures and patterns.
|
|
373
|
+
"""
|
|
374
|
+
return self.type in self.MODIFIERTYPES
|
|
375
|
+
|
|
376
|
+
@property
|
|
377
|
+
def is_material(self):
|
|
378
|
+
"""Get a boolean noting whether this object is a material modifier."""
|
|
379
|
+
return self.type in self.MATERIALTYPES
|
|
380
|
+
|
|
381
|
+
@property
|
|
382
|
+
def is_texture(self):
|
|
383
|
+
"""Get a boolean noting whether this object is a texture modifier."""
|
|
384
|
+
return self.type in self.TEXTURETYPES
|
|
385
|
+
|
|
386
|
+
@property
|
|
387
|
+
def is_pattern(self):
|
|
388
|
+
"""Get a boolean noting whether this object is a pattern modifier."""
|
|
389
|
+
return self.type in self.PATTERNTYPES
|
|
390
|
+
|
|
391
|
+
@property
|
|
392
|
+
def is_mixture(self):
|
|
393
|
+
"""Get a boolean noting whether this object is a mixture modifier."""
|
|
394
|
+
return self.type in self.MIXTURETYPES
|
|
395
|
+
|
|
396
|
+
@property
|
|
397
|
+
def is_opaque(self):
|
|
398
|
+
"""Get or set a boolean to indicate whether this primitive is opaque.
|
|
399
|
+
|
|
400
|
+
This property is used to separate opaque and non-opaque geometries as
|
|
401
|
+
well as modifiers.
|
|
402
|
+
"""
|
|
403
|
+
if self._is_opaque: # opaque modifier
|
|
404
|
+
return self._is_opaque
|
|
405
|
+
elif self.type in self.NONEOPAQUETYPES: # non-opaque modifier
|
|
406
|
+
return False
|
|
407
|
+
else: # it's a geometry or it has a void modifier; check the modifier
|
|
408
|
+
return self.modifier.is_void or self.modifier.is_opaque
|
|
409
|
+
|
|
410
|
+
@is_opaque.setter
|
|
411
|
+
def is_opaque(self, is_opaque):
|
|
412
|
+
self._is_opaque = bool(is_opaque)
|
|
413
|
+
|
|
414
|
+
@property
|
|
415
|
+
def is_void(self):
|
|
416
|
+
"""Only true for a void."""
|
|
417
|
+
return False
|
|
418
|
+
|
|
419
|
+
def _update_values(self):
|
|
420
|
+
"""update value dictionaries.
|
|
421
|
+
|
|
422
|
+
_update_values must be implemented in each subclass.
|
|
423
|
+
"""
|
|
424
|
+
pass
|
|
425
|
+
|
|
426
|
+
def add_dependent(self, dep):
|
|
427
|
+
"""Add dependent."""
|
|
428
|
+
assert isinstance(dep, Primitive), \
|
|
429
|
+
'{} is not a valid dependent type'.format(type(dep))
|
|
430
|
+
self._dependencies.append(dep)
|
|
431
|
+
|
|
432
|
+
@staticmethod
|
|
433
|
+
def _to_radiance(primitive, minimal=False):
|
|
434
|
+
"""Return Radiance representation of primitive."""
|
|
435
|
+
header = "%s %s %s" % (primitive.modifier.identifier,
|
|
436
|
+
primitive.type, primitive.identifier)
|
|
437
|
+
output = [header]
|
|
438
|
+
for line_count in range(3):
|
|
439
|
+
try:
|
|
440
|
+
values = (str(v) for v in primitive.values[line_count])
|
|
441
|
+
except BaseException:
|
|
442
|
+
values = [] # line will be displayed as 0
|
|
443
|
+
else:
|
|
444
|
+
count = len(primitive.values[line_count])
|
|
445
|
+
line = '%d %s' % (count, ' '.join(values).rstrip()) if count else '0'
|
|
446
|
+
output.append(line)
|
|
447
|
+
|
|
448
|
+
return ' '.join(output) if minimal else '\n'.join(output)
|
|
449
|
+
|
|
450
|
+
def to_radiance(self, minimal=False, include_modifier=True,
|
|
451
|
+
include_dependencies=True):
|
|
452
|
+
"""Return full radiance definition.
|
|
453
|
+
|
|
454
|
+
Args:
|
|
455
|
+
minimal: Boolean to note whether the radiance string should be written
|
|
456
|
+
in a minimal format (with spaces instead of line breaks). Default: False.
|
|
457
|
+
include_modifier: Boolean to note whether the modifier of this primitive
|
|
458
|
+
should be included in the string. Default: True.
|
|
459
|
+
include_dependencies: Boolean to note whether the dependencies of this
|
|
460
|
+
primitive should be included in the string. Default: True.
|
|
461
|
+
"""
|
|
462
|
+
output = []
|
|
463
|
+
|
|
464
|
+
if include_dependencies:
|
|
465
|
+
for dep in self.dependencies:
|
|
466
|
+
if isinstance(dep, Void):
|
|
467
|
+
continue
|
|
468
|
+
output.append(self._to_radiance(dep, minimal))
|
|
469
|
+
|
|
470
|
+
if include_modifier and not self.modifier.is_void:
|
|
471
|
+
output.append(self._to_radiance(self.modifier, minimal))
|
|
472
|
+
output.append(self._to_radiance(self, minimal))
|
|
473
|
+
|
|
474
|
+
return '\n'.join(output)
|
|
475
|
+
|
|
476
|
+
def to_dict(self):
|
|
477
|
+
"""Translate this object to a dictionary."""
|
|
478
|
+
base = {
|
|
479
|
+
"modifier": self.modifier.to_dict(),
|
|
480
|
+
"type": self.type,
|
|
481
|
+
"identifier": self.identifier,
|
|
482
|
+
"values": self.values,
|
|
483
|
+
"dependencies": [dep.to_dict() for dep in self.dependencies]
|
|
484
|
+
}
|
|
485
|
+
if self._display_name is not None:
|
|
486
|
+
base['display_name'] = self.display_name
|
|
487
|
+
return base
|
|
488
|
+
|
|
489
|
+
def duplicate(self):
|
|
490
|
+
"""Get a copy of this object."""
|
|
491
|
+
return self.__copy__()
|
|
492
|
+
|
|
493
|
+
@staticmethod
|
|
494
|
+
def filter_dict_input(input_dict):
|
|
495
|
+
"""Filter a dictionary of a Primitive to get modifier and dependency objects."""
|
|
496
|
+
try: # see if the mutil module has already been imported
|
|
497
|
+
mutil
|
|
498
|
+
except NameError:
|
|
499
|
+
# import the module here (instead of at top) to avoid a circular import
|
|
500
|
+
import honeybee_radiance.mutil as mutil # imports all modifiers classes
|
|
501
|
+
|
|
502
|
+
# try to get modifier
|
|
503
|
+
if 'modifier' not in input_dict or input_dict['modifier'] is None or \
|
|
504
|
+
input_dict['modifier'] == 'void':
|
|
505
|
+
modifier = VOID
|
|
506
|
+
else:
|
|
507
|
+
modifier = mutil.dict_to_modifier(input_dict['modifier'])
|
|
508
|
+
|
|
509
|
+
if 'dependencies' not in input_dict:
|
|
510
|
+
dependencies = []
|
|
511
|
+
else:
|
|
512
|
+
dependencies = [
|
|
513
|
+
mutil.dict_to_modifier(dep) for dep in input_dict['dependencies']
|
|
514
|
+
]
|
|
515
|
+
|
|
516
|
+
return modifier, dependencies
|
|
517
|
+
|
|
518
|
+
def __key(self):
|
|
519
|
+
"""A tuple based on the object properties, useful for hashing."""
|
|
520
|
+
return (hash(self.modifier), self.type, self.identifier) + \
|
|
521
|
+
tuple(hash(tuple(vals)) for vals in self.values) + \
|
|
522
|
+
tuple(hash(dep) for dep in self._dependencies)
|
|
523
|
+
|
|
524
|
+
def __hash__(self):
|
|
525
|
+
return hash(self.__key())
|
|
526
|
+
|
|
527
|
+
def __eq__(self, other):
|
|
528
|
+
return isinstance(other, self.__class__) and \
|
|
529
|
+
self.__key() == other.__key()
|
|
530
|
+
|
|
531
|
+
def __ne__(self, other):
|
|
532
|
+
return not self.__eq__(other)
|
|
533
|
+
|
|
534
|
+
def __copy__(self):
|
|
535
|
+
mod, depend = self._dup_mod_and_depend()
|
|
536
|
+
values_copy = [line[:] for line in self._values] # copy each line
|
|
537
|
+
new_obj = self.__class__(
|
|
538
|
+
self.identifier, mod, values_copy, self._is_opaque, depend)
|
|
539
|
+
new_obj._display_name = self._display_name
|
|
540
|
+
return new_obj
|
|
541
|
+
|
|
542
|
+
def _dup_mod_and_depend(self):
|
|
543
|
+
"""Duplicate this object's modifer and its dependencies."""
|
|
544
|
+
mod = None if isinstance(self._modifier, Void) else self._modifier.duplicate()
|
|
545
|
+
dependencies = [dep.duplicate() for dep in self._dependencies]
|
|
546
|
+
return mod, dependencies
|
|
547
|
+
|
|
548
|
+
def ToString(self):
|
|
549
|
+
"""Overwrite .NET ToString."""
|
|
550
|
+
return self.__repr__()
|
|
551
|
+
|
|
552
|
+
def __repr__(self):
|
|
553
|
+
"""Return primitive definition."""
|
|
554
|
+
return self.to_radiance()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""honeybee-radiance properties."""
|