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,477 @@
|
|
|
1
|
+
"""Radiance aBSDF Material.
|
|
2
|
+
|
|
3
|
+
https://floyd.lbl.gov/radiance/refer/ray.html#BSDF
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import division
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from .materialbase import Material
|
|
9
|
+
import honeybee.typing as typing
|
|
10
|
+
from honeybee.config import folders
|
|
11
|
+
import ladybug_geometry.geometry3d.pointvector as pv
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class aBSDF(Material):
|
|
15
|
+
"""Radiance aBSDF material.
|
|
16
|
+
|
|
17
|
+
From source code: https://github.com/LBNL-ETA/Radiance/blob/master/src/rt/m_bsdf.c
|
|
18
|
+
"For the MAT_ABSDF type, we check for a strong "through" component. Such a component
|
|
19
|
+
will cause direct rays to pass through unscattered. A separate test prevents
|
|
20
|
+
over-counting by dropping samples that are too close to this "through" direction.
|
|
21
|
+
BSDFs with such a through direction will also have a view component, meaning they are
|
|
22
|
+
somewhat see-through. A MAT_BSDF type with zero thickness behaves the same as a
|
|
23
|
+
MAT_ABSDF type with no strong through component."
|
|
24
|
+
|
|
25
|
+
.. code-block:: shell
|
|
26
|
+
|
|
27
|
+
mod aBSDF id
|
|
28
|
+
5+ BSDFfile ux uy uz funcfile transform
|
|
29
|
+
0
|
|
30
|
+
0|3|6|9
|
|
31
|
+
rfdif gfdif bfdif
|
|
32
|
+
rbdif gbdif bbdif
|
|
33
|
+
rtdif gtdif btdif
|
|
34
|
+
|
|
35
|
+
The __init__ method sets additional diffuse reflectance for front and back as well
|
|
36
|
+
as additional diffuse transmittance to 0. You can setup these values by using their
|
|
37
|
+
respective property.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
bsdf_file: Path to an xml file. Data will NOT be cached in memory.
|
|
41
|
+
identifier: Text string for a unique Material ID. Must not contain spaces
|
|
42
|
+
or special characters. This will be used to identify the object across
|
|
43
|
+
a model and in the exported Radiance files. If None, the identifier
|
|
44
|
+
will be derived from the bsdf_file name. (Default: None)
|
|
45
|
+
up_orientation: (x, y ,z) vector that sets the hemisphere that the
|
|
46
|
+
BSDF material faces. For materials that are symmetrical about
|
|
47
|
+
the face plane (like non-angled venetian blinds), this can be
|
|
48
|
+
any vector that is not perfectly normal to the face. For
|
|
49
|
+
asymmetrical materials like angled venetian blinds, this variable
|
|
50
|
+
should be coordinated with the direction the face are facing.
|
|
51
|
+
The default is set to (0.01, 0.01, 1.00), which should hopefully
|
|
52
|
+
not be perpendicular to any typical face.
|
|
53
|
+
modifier: Material modifier (Default: None).
|
|
54
|
+
function_file: Optional input for function file (Default: .).
|
|
55
|
+
transform: Optional transform input to to scale the thickness and reorient
|
|
56
|
+
the up vector (default: None).
|
|
57
|
+
angle_basis: BSDF file angle basis. If not provided by user honeybee tries to
|
|
58
|
+
find it by parsing BSDF file itself.
|
|
59
|
+
dependencies: A list of primitives that this primitive depends on. This
|
|
60
|
+
argument is only useful for defining advanced primitives where the
|
|
61
|
+
primitive is defined based on other primitives. (Default: [])
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Properties:
|
|
65
|
+
* identifier
|
|
66
|
+
* display_name
|
|
67
|
+
* bsdf_file
|
|
68
|
+
* up_orientation
|
|
69
|
+
* function_file
|
|
70
|
+
* transform
|
|
71
|
+
* angle_basis
|
|
72
|
+
* front_diffuse_reflectance
|
|
73
|
+
* back_diffuse_reflectance
|
|
74
|
+
* diffuse_transmittance
|
|
75
|
+
* dependencies
|
|
76
|
+
* values
|
|
77
|
+
* modifier
|
|
78
|
+
* dependencies
|
|
79
|
+
* is_modifier
|
|
80
|
+
* is_material
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
__slots__ = ('_bsdf_file', '_up_orientation', '_function_file',
|
|
84
|
+
'_transform', '_angle_basis', '_front_diffuse_reflectance',
|
|
85
|
+
'_back_diffuse_reflectance', '_diffuse_transmittance')
|
|
86
|
+
|
|
87
|
+
# TODO(): compress file content: https://stackoverflow.com/a/15529390/4394669
|
|
88
|
+
def __init__(self, bsdf_file, identifier=None, up_orientation=None, modifier=None,
|
|
89
|
+
function_file='.', transform=None, angle_basis=None, dependencies=None):
|
|
90
|
+
"""Create aBSDF material."""
|
|
91
|
+
identifier = identifier or \
|
|
92
|
+
'_'.join('.'.join(os.path.split(bsdf_file)[-1].split('.')[:-1]).split(' '))
|
|
93
|
+
|
|
94
|
+
Material.__init__(self, identifier, modifier=modifier,
|
|
95
|
+
dependencies=dependencies)
|
|
96
|
+
|
|
97
|
+
self.bsdf_file = bsdf_file
|
|
98
|
+
self.angle_basis = angle_basis
|
|
99
|
+
self.up_orientation = up_orientation
|
|
100
|
+
self.function_file = function_file
|
|
101
|
+
self.transform = transform
|
|
102
|
+
self._front_diffuse_reflectance = None
|
|
103
|
+
self._back_diffuse_reflectance = None
|
|
104
|
+
self._diffuse_transmittance = None
|
|
105
|
+
|
|
106
|
+
self._update_values()
|
|
107
|
+
|
|
108
|
+
def _update_values(self):
|
|
109
|
+
"update value dictionaries."
|
|
110
|
+
n_path = os.path.normpath(self.bsdf_file).replace('\\', '/')
|
|
111
|
+
f_path = n_path if os.path.isabs(n_path) else './{}'.format(n_path)
|
|
112
|
+
self._values[0] = [
|
|
113
|
+
'"{}"'.format(f_path),
|
|
114
|
+
self.up_orientation.x,
|
|
115
|
+
self.up_orientation.y,
|
|
116
|
+
self.up_orientation.z,
|
|
117
|
+
self.function_file
|
|
118
|
+
]
|
|
119
|
+
if self.transform:
|
|
120
|
+
self.values[0].append(self.transform)
|
|
121
|
+
|
|
122
|
+
if self.front_diffuse_reflectance is not None:
|
|
123
|
+
self._values[2] = list(self.front_diffuse_reflectance)
|
|
124
|
+
|
|
125
|
+
if self.back_diffuse_reflectance is not None:
|
|
126
|
+
for v in self.back_diffuse_reflectance:
|
|
127
|
+
self._values[2].append(v)
|
|
128
|
+
|
|
129
|
+
if self.diffuse_transmittance is not None:
|
|
130
|
+
for v in self.diffuse_transmittance:
|
|
131
|
+
self._values[2].append(v)
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def bsdf_file(self):
|
|
135
|
+
"""Path to BSDF file."""
|
|
136
|
+
return self._bsdf_file
|
|
137
|
+
|
|
138
|
+
@bsdf_file.setter
|
|
139
|
+
def bsdf_file(self, bsdf_file):
|
|
140
|
+
assert os.path.isfile(
|
|
141
|
+
bsdf_file), 'No such file at: {}'.format(bsdf_file)
|
|
142
|
+
assert bsdf_file.lower().endswith('.xml'), \
|
|
143
|
+
'BSDF file must be an xml file: {}'.format(bsdf_file)
|
|
144
|
+
self._bsdf_file = os.path.normpath(bsdf_file).replace('\\', '/')
|
|
145
|
+
if not hasattr(self, '_angle_basis'):
|
|
146
|
+
# first time that file is assigned
|
|
147
|
+
pass
|
|
148
|
+
else:
|
|
149
|
+
self.find_angle_basis(bsdf_file)
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def up_orientation(self):
|
|
153
|
+
"""Get or set the up normal vector.
|
|
154
|
+
|
|
155
|
+
(x, y ,z) vector that sets the hemisphere that the
|
|
156
|
+
BSDF material faces. For materials that are symmetrical about
|
|
157
|
+
the face plane (like non-angled venetian blinds), this can be
|
|
158
|
+
any vector that is not perfectly normal to the face. For
|
|
159
|
+
asymmetrical materials like angled venetian blinds, this variable
|
|
160
|
+
should be coordinated with the direction the face are facing.
|
|
161
|
+
The default is set to (0.01, 0.01, 1.00), which should hopefully
|
|
162
|
+
not be perpendicular to any typical face.
|
|
163
|
+
"""
|
|
164
|
+
return self._up_orientation
|
|
165
|
+
|
|
166
|
+
@up_orientation.setter
|
|
167
|
+
def up_orientation(self, vector):
|
|
168
|
+
if vector:
|
|
169
|
+
up_vector = pv.Vector3D(*[float(v) for v in vector])
|
|
170
|
+
else:
|
|
171
|
+
up_vector = pv.Vector3D(0.01, 0.01, 1.00)
|
|
172
|
+
|
|
173
|
+
self._up_orientation = up_vector
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def function_file(self):
|
|
177
|
+
"""Get or set the path to function file."""
|
|
178
|
+
return self._function_file
|
|
179
|
+
|
|
180
|
+
@function_file.setter
|
|
181
|
+
def function_file(self, value):
|
|
182
|
+
self._function_file = value or '.'
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def transform(self):
|
|
186
|
+
"""Get or set the transform.
|
|
187
|
+
|
|
188
|
+
This is optional and is used to scale the thickness and reorient the
|
|
189
|
+
up vector. (Default: None).
|
|
190
|
+
"""
|
|
191
|
+
return self._transform
|
|
192
|
+
|
|
193
|
+
@transform.setter
|
|
194
|
+
def transform(self, value):
|
|
195
|
+
self._transform = value
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def angle_basis(self):
|
|
199
|
+
"""Get or set a string for the BSDF file angle basis.
|
|
200
|
+
|
|
201
|
+
Valid values are Klems Full, Klems Half, Klems Quarter and TensorTree
|
|
202
|
+
"""
|
|
203
|
+
return self._angle_basis
|
|
204
|
+
|
|
205
|
+
@angle_basis.setter
|
|
206
|
+
def angle_basis(self, value):
|
|
207
|
+
if value:
|
|
208
|
+
assert value in (
|
|
209
|
+
'Klems Full', 'Klems Half',
|
|
210
|
+
'Klems Quarter', 'TensorTree'), '{} is not a valid angle basis.'
|
|
211
|
+
self._angle_basis = value
|
|
212
|
+
else:
|
|
213
|
+
self._angle_basis = self.find_angle_basis(self.bsdf_file)
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def sampling_type(self):
|
|
217
|
+
"""Return rfluxmtx parameters sampling type based on the angle basis.
|
|
218
|
+
|
|
219
|
+
Values are:
|
|
220
|
+
|
|
221
|
+
* kf for klems full.
|
|
222
|
+
* kh for klems half.
|
|
223
|
+
* kq for klems quarter.
|
|
224
|
+
|
|
225
|
+
For other angle basis a None value will be returned.
|
|
226
|
+
"""
|
|
227
|
+
_mapper = {
|
|
228
|
+
'Klems Full': 'kf', 'Klems Half': 'kh', 'Klems Quarter': 'kq'
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
try:
|
|
232
|
+
sampling = _mapper[self.angle_basis]
|
|
233
|
+
except KeyError:
|
|
234
|
+
sampling = None
|
|
235
|
+
|
|
236
|
+
return sampling
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def front_diffuse_reflectance(self):
|
|
240
|
+
"""Get or set the additional front diffuse reflectance."""
|
|
241
|
+
return self._front_diffuse_reflectance
|
|
242
|
+
|
|
243
|
+
@front_diffuse_reflectance.setter
|
|
244
|
+
def front_diffuse_reflectance(self, value):
|
|
245
|
+
if value is not None:
|
|
246
|
+
value = typing.tuple_with_length(value, 3)
|
|
247
|
+
|
|
248
|
+
self._front_diffuse_reflectance = value
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def back_diffuse_reflectance(self):
|
|
252
|
+
"""Get or set the additional back diffuse reflectance."""
|
|
253
|
+
return self._back_diffuse_reflectance
|
|
254
|
+
|
|
255
|
+
@back_diffuse_reflectance.setter
|
|
256
|
+
def back_diffuse_reflectance(self, value):
|
|
257
|
+
if value is not None:
|
|
258
|
+
value = typing.tuple_with_length(value, 3)
|
|
259
|
+
|
|
260
|
+
self._back_diffuse_reflectance = value
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def diffuse_transmittance(self):
|
|
264
|
+
"""Get or set the additional diffuse transmittance."""
|
|
265
|
+
return self._diffuse_transmittance
|
|
266
|
+
|
|
267
|
+
@diffuse_transmittance.setter
|
|
268
|
+
def diffuse_transmittance(self, value):
|
|
269
|
+
if value is not None:
|
|
270
|
+
value = typing.tuple_with_length(value, 3)
|
|
271
|
+
|
|
272
|
+
self._diffuse_transmittance = value
|
|
273
|
+
|
|
274
|
+
@classmethod
|
|
275
|
+
def from_primitive_dict(cls, primitive_dict):
|
|
276
|
+
"""Initialize a aBSDF from a primitive dict.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
data: A dictionary in the format below.
|
|
280
|
+
|
|
281
|
+
.. code-block:: python
|
|
282
|
+
|
|
283
|
+
{
|
|
284
|
+
"modifier": {}, # primitive modifier (Default: None)
|
|
285
|
+
"type": "aBSDF", # primitive type
|
|
286
|
+
"identifier": "", # primitive identifier
|
|
287
|
+
"display_name": "", # primitive display name
|
|
288
|
+
"values": [] # values,
|
|
289
|
+
"dependencies": []
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
"""
|
|
293
|
+
cls._dict_type_check(cls.__name__, primitive_dict)
|
|
294
|
+
modifier, dependencies = cls.filter_dict_input(primitive_dict)
|
|
295
|
+
values = primitive_dict['values'][0]
|
|
296
|
+
extra_values = primitive_dict['values'][2]
|
|
297
|
+
|
|
298
|
+
cls_ = cls(
|
|
299
|
+
bsdf_file=values[0],
|
|
300
|
+
identifier=primitive_dict['identifier'],
|
|
301
|
+
up_orientation=values[1:4],
|
|
302
|
+
modifier=modifier,
|
|
303
|
+
function_file=values[4],
|
|
304
|
+
transform=values[5] if len(values) == 6 else None,
|
|
305
|
+
angle_basis=None,
|
|
306
|
+
dependencies=dependencies
|
|
307
|
+
)
|
|
308
|
+
if 'display_name' in primitive_dict and \
|
|
309
|
+
primitive_dict['display_name'] is not None:
|
|
310
|
+
cls_.display_name = primitive_dict['display_name']
|
|
311
|
+
|
|
312
|
+
# this might look redundant but it is NOT. see glass for explanation.
|
|
313
|
+
cls_.values = primitive_dict['values']
|
|
314
|
+
|
|
315
|
+
if not extra_values:
|
|
316
|
+
return cls_
|
|
317
|
+
|
|
318
|
+
values_length = len(extra_values)
|
|
319
|
+
assert values_length in (3, 6, 9), \
|
|
320
|
+
'Length of real values should be 3, 6 or 9 not %d.' % values_length
|
|
321
|
+
|
|
322
|
+
if values_length == 3:
|
|
323
|
+
cls_.front_diffuse_reflectance = extra_values
|
|
324
|
+
elif values_length == 6:
|
|
325
|
+
cls_.front_diffuse_reflectance = extra_values[:3]
|
|
326
|
+
cls_.back_diffuse_reflectance = extra_values[3:]
|
|
327
|
+
else:
|
|
328
|
+
cls_.front_diffuse_reflectance = extra_values[:3]
|
|
329
|
+
cls_.back_diffuse_reflectance = extra_values[3:6]
|
|
330
|
+
cls_.diffuse_transmittance = extra_values[6:]
|
|
331
|
+
|
|
332
|
+
return cls_
|
|
333
|
+
|
|
334
|
+
@classmethod
|
|
335
|
+
def from_dict(cls, data, folder=None):
|
|
336
|
+
"""Initialize a aBSDF from a dictionary.
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
data: A dictionary in the format below.
|
|
340
|
+
folder: Path to a destination folder to save the bsdf file.
|
|
341
|
+
|
|
342
|
+
.. code-block:: python
|
|
343
|
+
|
|
344
|
+
{
|
|
345
|
+
"modifier": {}, # material modifier (Default: None)
|
|
346
|
+
"type": "aBSDF", # Material type
|
|
347
|
+
"identifier": "", # Material identifer
|
|
348
|
+
"display_name": "" # Material display name
|
|
349
|
+
"up_orientation": [number, number, number],
|
|
350
|
+
"function_file": string, # default: '.'
|
|
351
|
+
"transform": string, # default: None
|
|
352
|
+
"bsdf_data": string, # bsdf file data as string
|
|
353
|
+
"front_diffuse_reflectance": [number, number, number], # optional
|
|
354
|
+
"back_diffuse_reflectance": [number, number, number], # optional
|
|
355
|
+
"diffuse_transmittance": [number, number, number] # optional
|
|
356
|
+
}
|
|
357
|
+
"""
|
|
358
|
+
cls._dict_type_check(cls.__name__, data)
|
|
359
|
+
modifier, dependencies = cls.filter_dict_input(data)
|
|
360
|
+
|
|
361
|
+
# check folder and create it if it does not exist
|
|
362
|
+
folder = os.path.join(folders.default_simulation_folder, 'BSDF') \
|
|
363
|
+
if folder is None else folder
|
|
364
|
+
if not os.path.isdir(folder):
|
|
365
|
+
os.makedirs(folder)
|
|
366
|
+
|
|
367
|
+
fp = os.path.join(folder, '%s.xml' % data['identifier'])
|
|
368
|
+
# write to xml file
|
|
369
|
+
cls.decompress_to_file(data['bsdf_data'], fp)
|
|
370
|
+
|
|
371
|
+
cls_ = cls(
|
|
372
|
+
bsdf_file=fp,
|
|
373
|
+
identifier=data['identifier'],
|
|
374
|
+
up_orientation=data['up_orientation'],
|
|
375
|
+
modifier=modifier,
|
|
376
|
+
dependencies=dependencies
|
|
377
|
+
)
|
|
378
|
+
if 'display_name' in data and data['display_name'] is not None:
|
|
379
|
+
cls_.display_name = data['display_name']
|
|
380
|
+
|
|
381
|
+
if 'front_diffuse_reflectance' in data:
|
|
382
|
+
cls_.front_diffuse_reflectance = data['front_diffuse_reflectance']
|
|
383
|
+
if 'back_diffuse_reflectance' in data:
|
|
384
|
+
cls_.back_diffuse_reflectance = data['back_diffuse_reflectance']
|
|
385
|
+
if 'diffuse_transmittance' in data:
|
|
386
|
+
cls_.diffuse_transmittance = data['diffuse_transmittance']
|
|
387
|
+
|
|
388
|
+
return cls_
|
|
389
|
+
|
|
390
|
+
def to_dict(self):
|
|
391
|
+
"""Convert aBSDF material to a dictionary."""
|
|
392
|
+
bsdf_data = self.compress_file(self.bsdf_file)
|
|
393
|
+
|
|
394
|
+
absdf_dict = {
|
|
395
|
+
'modifier': self.modifier.to_dict(),
|
|
396
|
+
'type': 'aBSDF',
|
|
397
|
+
'identifier': self.identifier,
|
|
398
|
+
'up_orientation': self.up_orientation.to_array(),
|
|
399
|
+
'function_file': self.function_file,
|
|
400
|
+
'transform': self.transform,
|
|
401
|
+
'bsdf_data': bsdf_data,
|
|
402
|
+
'dependencies': [dep.to_dict() for dep in self.dependencies]
|
|
403
|
+
}
|
|
404
|
+
if self._display_name is not None:
|
|
405
|
+
absdf_dict['display_name'] = self.display_name
|
|
406
|
+
|
|
407
|
+
if self.front_diffuse_reflectance:
|
|
408
|
+
absdf_dict['front_diffuse_reflectance'] = self.front_diffuse_reflectance
|
|
409
|
+
if self.back_diffuse_reflectance:
|
|
410
|
+
absdf_dict['back_diffuse_reflectance'] = self.back_diffuse_reflectance
|
|
411
|
+
if self.diffuse_transmittance:
|
|
412
|
+
absdf_dict['diffuse_transmittance'] = self.diffuse_transmittance
|
|
413
|
+
|
|
414
|
+
return absdf_dict
|
|
415
|
+
|
|
416
|
+
@staticmethod
|
|
417
|
+
def find_angle_basis(bsdf_file, max_ln_count=2000):
|
|
418
|
+
"""Find angle basis in an xml file."""
|
|
419
|
+
# find data structure first
|
|
420
|
+
with open(bsdf_file, 'r') as inf:
|
|
421
|
+
for count, line in enumerate(inf):
|
|
422
|
+
if line.strip().startswith('<IncidentDataStructure>'):
|
|
423
|
+
# get data structure
|
|
424
|
+
data_structure = line.replace('<IncidentDataStructure>', '') \
|
|
425
|
+
.replace('</IncidentDataStructure>', '').strip()
|
|
426
|
+
break
|
|
427
|
+
assert count < max_ln_count, \
|
|
428
|
+
'Failed to find IncidentDataStructure in first %d lines. ' \
|
|
429
|
+
'You can check the file by opening the file in a text editor ' \
|
|
430
|
+
'and search for <IncidentDataStructure>' % max_ln_count
|
|
431
|
+
|
|
432
|
+
# now find the angle basis
|
|
433
|
+
if data_structure.startswith('TensorTree'):
|
|
434
|
+
return 'TensorTree'
|
|
435
|
+
elif data_structure.lower() == 'columns':
|
|
436
|
+
# look for AngleBasisName
|
|
437
|
+
with open(bsdf_file, 'r') as inf:
|
|
438
|
+
for i in range(count):
|
|
439
|
+
next(inf)
|
|
440
|
+
for count, line in enumerate(inf):
|
|
441
|
+
if line.strip().startswith('<AngleBasisName>'):
|
|
442
|
+
angle_basis = line.replace('<AngleBasisName>', '') \
|
|
443
|
+
.replace('</AngleBasisName>', '').replace('LBNL/', '') \
|
|
444
|
+
.strip()
|
|
445
|
+
return angle_basis
|
|
446
|
+
assert count < max_ln_count, \
|
|
447
|
+
'Failed to find AngleBasisName in first %d lines. ' \
|
|
448
|
+
'You can check the file by opening the file in a text editor ' \
|
|
449
|
+
'and search for <AngleBasisName>' % max_ln_count
|
|
450
|
+
else:
|
|
451
|
+
raise ValueError(
|
|
452
|
+
'Unknown IncidentDataStructure: {}'.format(data_structure))
|
|
453
|
+
|
|
454
|
+
@staticmethod
|
|
455
|
+
def compress_file(filepath):
|
|
456
|
+
"""Compress bsdf data in an XML file to a string."""
|
|
457
|
+
# TODO: Research better ways to compress the file
|
|
458
|
+
with open(filepath, 'r') as input_file:
|
|
459
|
+
content = input_file.read()
|
|
460
|
+
return content
|
|
461
|
+
|
|
462
|
+
@staticmethod
|
|
463
|
+
def decompress_to_file(value, filepath):
|
|
464
|
+
"""Write bsdf data string to a file."""
|
|
465
|
+
with open(filepath, 'w') as output_file:
|
|
466
|
+
output_file.write(value)
|
|
467
|
+
|
|
468
|
+
def __copy__(self):
|
|
469
|
+
mod, depend = self._dup_mod_and_depend()
|
|
470
|
+
new_absdf = self.__class__(
|
|
471
|
+
self.bsdf_file, self.identifier, self.up_orientation, mod,
|
|
472
|
+
self.function_file, self.transform, self.angle_basis, depend)
|
|
473
|
+
new_absdf._front_diffuse_reflectance = self._front_diffuse_reflectance
|
|
474
|
+
new_absdf._back_diffuse_reflectance = self._back_diffuse_reflectance
|
|
475
|
+
new_absdf._diffuse_transmittance = self._diffuse_transmittance
|
|
476
|
+
new_absdf._display_name = self._display_name
|
|
477
|
+
return new_absdf
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Radiance Antimatter Material.
|
|
2
|
+
|
|
3
|
+
http://radsite.lbl.gov/radiance/refer/ray.html#Antimatter
|
|
4
|
+
"""
|
|
5
|
+
from .materialbase import Material
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# TODO: Implement the class. It's currently only a generic Radiance Primitive
|
|
9
|
+
class Antimatter(Material):
|
|
10
|
+
"""Radiance Antimatter Material.
|
|
11
|
+
|
|
12
|
+
Antimatter is a material that can \'subtract\' volumes from other volumes. A ray
|
|
13
|
+
passing into an antimatter object becomes blind to all the specified modifiers:
|
|
14
|
+
|
|
15
|
+
.. code-block:: shell
|
|
16
|
+
|
|
17
|
+
mod antimatter id
|
|
18
|
+
N mod1 mod2 .. modN
|
|
19
|
+
0
|
|
20
|
+
0
|
|
21
|
+
|
|
22
|
+
The first modifier will also be used to shade the area leaving the antimatter volume
|
|
23
|
+
and entering the regular volume. If mod1 is void, the antimatter volume is completely
|
|
24
|
+
invisible. Antimatter does not work properly with the material type "trans", and
|
|
25
|
+
multiple antimatter surfaces should be disjoint. The viewpoint must be outside all
|
|
26
|
+
volumes concerned for a correct rendering.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
identifier: Text string for a unique Material ID. Must not contain spaces
|
|
30
|
+
or special characters. This will be used to identify the object across
|
|
31
|
+
a model and in the exported Radiance files.
|
|
32
|
+
modifier: Modifier. It can be primitive, mixture, texture or pattern.
|
|
33
|
+
(Default: None).
|
|
34
|
+
values: An array 3 arrays for primitive data. Each of the 3 sub-arrays
|
|
35
|
+
refer to a line number in the radiance primitive definitions and the
|
|
36
|
+
values in each array correspond to values occurring within each line.
|
|
37
|
+
is_opaque: A boolean to indicate whether this primitive is opaque.
|
|
38
|
+
dependencies: A list of primitives that this primitive depends on. This
|
|
39
|
+
argument is only useful for defining advanced primitives that are
|
|
40
|
+
defined based on other primitives. (Default: []).
|
|
41
|
+
|
|
42
|
+
Properties:
|
|
43
|
+
* identifier
|
|
44
|
+
* display_name
|
|
45
|
+
* values
|
|
46
|
+
* modifier
|
|
47
|
+
* dependencies
|
|
48
|
+
* is_modifier
|
|
49
|
+
* is_material
|
|
50
|
+
* is_opaque
|
|
51
|
+
"""
|
|
52
|
+
__slots__ = ()
|
|
53
|
+
|
|
54
|
+
pass
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Radiance Ashik2 Material.
|
|
2
|
+
|
|
3
|
+
http://radsite.lbl.gov/radiance/refer/ray.html#Ashik2
|
|
4
|
+
"""
|
|
5
|
+
from .materialbase import Material
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# TODO: Implement the class. It's currently only a generic Radiance Primitive
|
|
9
|
+
class Ashik2(Material):
|
|
10
|
+
"""Radiance Ashik2 Material.
|
|
11
|
+
|
|
12
|
+
Ashik2 is the anisotropic reflectance model by Ashikhmin & Shirley. The string
|
|
13
|
+
arguments are the same as for plastic2, but the real arguments have additional
|
|
14
|
+
flexibility to specify the specular color. Also, rather than roughness, specular
|
|
15
|
+
power is used, which has no physical meaning other than larger numbers are equivalent
|
|
16
|
+
to a smoother surface.
|
|
17
|
+
|
|
18
|
+
.. code-block:: shell
|
|
19
|
+
|
|
20
|
+
mod ashik2 id
|
|
21
|
+
4+ ux uy uz funcfile transform
|
|
22
|
+
0
|
|
23
|
+
8 dred dgrn dblu sred sgrn sblu u-power v-power
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
identifier: Text string for a unique Material ID. Must not contain spaces
|
|
27
|
+
or special characters. This will be used to identify the object across
|
|
28
|
+
a model and in the exported Radiance files.
|
|
29
|
+
modifier: Modifier. It can be primitive, mixture, texture or pattern.
|
|
30
|
+
(Default: None).
|
|
31
|
+
values: An array 3 arrays for primitive data. Each of the 3 sub-arrays
|
|
32
|
+
refer to a line number in the radiance primitive definitions and the
|
|
33
|
+
values in each array correspond to values occurring within each line.
|
|
34
|
+
is_opaque: A boolean to indicate whether this primitive is opaque.
|
|
35
|
+
dependencies: A list of primitives that this primitive depends on. This
|
|
36
|
+
argument is only useful for defining advanced primitives that are
|
|
37
|
+
defined based on other primitives. (Default: []).
|
|
38
|
+
|
|
39
|
+
Properties:
|
|
40
|
+
* identifier
|
|
41
|
+
* display_name
|
|
42
|
+
* values
|
|
43
|
+
* modifier
|
|
44
|
+
* dependencies
|
|
45
|
+
* is_modifier
|
|
46
|
+
* is_material
|
|
47
|
+
* is_opaque
|
|
48
|
+
"""
|
|
49
|
+
__slots__ = ()
|
|
50
|
+
|
|
51
|
+
pass
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Radiance BRTDfunc Material.
|
|
2
|
+
|
|
3
|
+
http://radsite.lbl.gov/radiance/refer/ray.html#BRTDfunc
|
|
4
|
+
"""
|
|
5
|
+
from .materialbase import Material
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# TODO: Implement the class. It's currently only a generic Radiance Primitive
|
|
9
|
+
class BRTDfunc(Material):
|
|
10
|
+
"""Radiance BRTDfunc Material.
|
|
11
|
+
|
|
12
|
+
The material BRTDfunc gives the maximum flexibility over surface reflectance and
|
|
13
|
+
transmittance, providing for spectrally-dependent specular rays and reflectance and
|
|
14
|
+
transmittance distribution functions.
|
|
15
|
+
|
|
16
|
+
.. code-block:: shell
|
|
17
|
+
|
|
18
|
+
mod BRTDfunc id
|
|
19
|
+
10+ rrefl grefl brefl
|
|
20
|
+
rtrns gtrns btrns
|
|
21
|
+
rbrtd gbrtd bbrtd
|
|
22
|
+
funcfile transform
|
|
23
|
+
0
|
|
24
|
+
9+ rfdif gfdif bfdif
|
|
25
|
+
rbdif gbdif bbdif
|
|
26
|
+
rtdif gtdif btdif
|
|
27
|
+
A10 ..
|
|
28
|
+
|
|
29
|
+
The variables rrefl, grefl and brefl specify the color coefficients for the ideal
|
|
30
|
+
specular (mirror) reflection of the surface. The variables rtrns, gtrns and btrns
|
|
31
|
+
specify the color coefficients for the ideal specular transmission. The functions
|
|
32
|
+
rbrtd, gbrtd and bbrtd take the direction to the incident light (and its solid angle)
|
|
33
|
+
and compute the color coefficients for the directional diffuse part of reflection and
|
|
34
|
+
transmission. As a special case, three identical values of '0' may be given in place
|
|
35
|
+
of these function names to indicate no directional diffuse component.
|
|
36
|
+
|
|
37
|
+
Unlike most other material types, the surface normal is not altered to face the
|
|
38
|
+
incoming ray. Thus, functions and variables must pay attention to the orientation of
|
|
39
|
+
the surface and make adjustments appropriately. However, the special variables for
|
|
40
|
+
the perturbed dot product and surface normal, RdotP, NxP, NyP and NzP are reoriented
|
|
41
|
+
as if the ray hit the front surface for convenience.
|
|
42
|
+
|
|
43
|
+
A diffuse reflection component may be given for the front side with rfdif, gfdif and
|
|
44
|
+
bfdif for the front side of the surface or rbdif, gbdif and bbdif for the back side.
|
|
45
|
+
The diffuse transmittance (must be the same for both sides by physical law) is given
|
|
46
|
+
by rtdif, gtdif and btdif. A pattern will modify these diffuse scattering values, and
|
|
47
|
+
will be available through the special variables CrP, CgP and CbP.
|
|
48
|
+
|
|
49
|
+
Care must be taken when using this material type to produce a physically valid
|
|
50
|
+
reflection model. The reflectance functions should be bidirectional, and under no
|
|
51
|
+
circumstances should the sum of reflected diffuse, transmitted diffuse, reflected
|
|
52
|
+
specular, transmitted specular and the integrated directional diffuse component be
|
|
53
|
+
greater than one.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
identifier: Text string for a unique Material ID. Must not contain spaces
|
|
57
|
+
or special characters. This will be used to identify the object across
|
|
58
|
+
a model and in the exported Radiance files.
|
|
59
|
+
modifier: Modifier. It can be primitive, mixture, texture or pattern.
|
|
60
|
+
(Default: None).
|
|
61
|
+
values: An array 3 arrays for primitive data. Each of the 3 sub-arrays
|
|
62
|
+
refer to a line number in the radiance primitive definitions and the
|
|
63
|
+
values in each array correspond to values occurring within each line.
|
|
64
|
+
is_opaque: A boolean to indicate whether this primitive is opaque.
|
|
65
|
+
dependencies: A list of primitives that this primitive depends on. This
|
|
66
|
+
argument is only useful for defining advanced primitives that are
|
|
67
|
+
defined based on other primitives. (Default: []).
|
|
68
|
+
|
|
69
|
+
Properties:
|
|
70
|
+
* identifier
|
|
71
|
+
* display_name
|
|
72
|
+
* values
|
|
73
|
+
* modifier
|
|
74
|
+
* dependencies
|
|
75
|
+
* is_modifier
|
|
76
|
+
* is_material
|
|
77
|
+
* is_opaque
|
|
78
|
+
"""
|
|
79
|
+
__slots__ = ()
|
|
80
|
+
|
|
81
|
+
pass
|