From d32ba4cb06528f08929aa5c5bcc74ac761cc34d4 Mon Sep 17 00:00:00 2001 From: chriswmackey Date: Sat, 19 Oct 2024 19:06:16 +0000 Subject: [PATCH] deploy: update docs --- .nojekyll | 0 README.md | 1 + docs/.buildinfo | 4 + docs/.doctrees/cli/compare.doctree | Bin 0 -> 19440 bytes docs/.doctrees/cli/create.doctree | Bin 0 -> 85034 bytes docs/.doctrees/cli/edit.doctree | Bin 0 -> 132374 bytes docs/.doctrees/cli/index.doctree | Bin 0 -> 4022 bytes docs/.doctrees/cli/lib.doctree | Bin 0 -> 10803 bytes docs/.doctrees/cli/main.doctree | Bin 0 -> 6848 bytes docs/.doctrees/cli/setconfig.doctree | Bin 0 -> 6130 bytes docs/.doctrees/cli/validate.doctree | Bin 0 -> 21585 bytes docs/.doctrees/environment.pickle | Bin 0 -> 1308893 bytes docs/.doctrees/honeybee.altnumber.doctree | Bin 0 -> 14914 bytes docs/.doctrees/honeybee.aperture.doctree | Bin 0 -> 207458 bytes .../honeybee.boundarycondition.doctree | Bin 0 -> 69135 bytes docs/.doctrees/honeybee.checkdup.doctree | Bin 0 -> 25344 bytes docs/.doctrees/honeybee.cli.compare.doctree | Bin 0 -> 3159 bytes docs/.doctrees/honeybee.cli.create.doctree | Bin 0 -> 3156 bytes docs/.doctrees/honeybee.cli.doctree | Bin 0 -> 10973 bytes docs/.doctrees/honeybee.cli.edit.doctree | Bin 0 -> 3132 bytes docs/.doctrees/honeybee.cli.lib.doctree | Bin 0 -> 2852 bytes docs/.doctrees/honeybee.cli.setconfig.doctree | Bin 0 -> 3213 bytes docs/.doctrees/honeybee.cli.validate.doctree | Bin 0 -> 14539 bytes docs/.doctrees/honeybee.colorobj.doctree | Bin 0 -> 61480 bytes docs/.doctrees/honeybee.config.doctree | Bin 0 -> 34594 bytes docs/.doctrees/honeybee.dictutil.doctree | Bin 0 -> 8509 bytes docs/.doctrees/honeybee.doctree | Bin 0 -> 4782 bytes docs/.doctrees/honeybee.door.doctree | Bin 0 -> 161529 bytes docs/.doctrees/honeybee.extensionutil.doctree | Bin 0 -> 40635 bytes docs/.doctrees/honeybee.face.doctree | Bin 0 -> 320655 bytes docs/.doctrees/honeybee.facetype.doctree | Bin 0 -> 26494 bytes docs/.doctrees/honeybee.logutil.doctree | Bin 0 -> 8660 bytes docs/.doctrees/honeybee.model.doctree | Bin 0 -> 464086 bytes docs/.doctrees/honeybee.orientation.doctree | Bin 0 -> 26359 bytes docs/.doctrees/honeybee.properties.doctree | Bin 0 -> 243952 bytes docs/.doctrees/honeybee.room.doctree | Bin 0 -> 401870 bytes docs/.doctrees/honeybee.search.doctree | Bin 0 -> 20424 bytes docs/.doctrees/honeybee.shade.doctree | Bin 0 -> 109303 bytes docs/.doctrees/honeybee.shademesh.doctree | Bin 0 -> 77760 bytes docs/.doctrees/honeybee.typing.doctree | Bin 0 -> 82795 bytes docs/.doctrees/honeybee.units.doctree | Bin 0 -> 12180 bytes .../honeybee.writer.aperture.doctree | Bin 0 -> 3852 bytes docs/.doctrees/honeybee.writer.doctree | Bin 0 -> 4762 bytes docs/.doctrees/honeybee.writer.door.doctree | Bin 0 -> 3780 bytes docs/.doctrees/honeybee.writer.face.doctree | Bin 0 -> 3780 bytes docs/.doctrees/honeybee.writer.model.doctree | Bin 0 -> 3798 bytes docs/.doctrees/honeybee.writer.room.doctree | Bin 0 -> 3780 bytes docs/.doctrees/honeybee.writer.shade.doctree | Bin 0 -> 3798 bytes .../honeybee.writer.shademesh.doctree | Bin 0 -> 3870 bytes docs/.doctrees/index.doctree | Bin 0 -> 11710 bytes docs/.doctrees/modules.doctree | Bin 0 -> 2771 bytes docs/.nojekyll | 0 docs/README.md | 1 + docs/_modules/honeybee/altnumber.html | 1181 +++ docs/_modules/honeybee/aperture.html | 2029 +++++ docs/_modules/honeybee/boundarycondition.html | 1516 ++++ docs/_modules/honeybee/checkdup.html | 1310 ++++ docs/_modules/honeybee/cli/validate.html | 1328 ++++ docs/_modules/honeybee/colorobj.html | 1497 ++++ docs/_modules/honeybee/config.html | 1478 ++++ docs/_modules/honeybee/dictutil.html | 1185 +++ docs/_modules/honeybee/door.html | 1826 +++++ docs/_modules/honeybee/extensionutil.html | 1354 ++++ docs/_modules/honeybee/face.html | 3386 ++++++++ docs/_modules/honeybee/facetype.html | 1296 ++++ docs/_modules/honeybee/logutil.html | 1210 +++ docs/_modules/honeybee/model.html | 4827 ++++++++++++ docs/_modules/honeybee/orientation.html | 1275 +++ docs/_modules/honeybee/properties.html | 1973 +++++ docs/_modules/honeybee/room.html | 4092 ++++++++++ docs/_modules/honeybee/search.html | 1238 +++ docs/_modules/honeybee/shade.html | 1659 ++++ docs/_modules/honeybee/shademesh.html | 1509 ++++ docs/_modules/honeybee/typing.html | 1693 ++++ docs/_modules/honeybee/units.html | 1222 +++ docs/_modules/index.html | 1150 +++ docs/_sources/cli/compare.rst.txt | 6 + docs/_sources/cli/create.rst.txt | 6 + docs/_sources/cli/edit.rst.txt | 6 + docs/_sources/cli/index.rst.txt | 21 + docs/_sources/cli/lib.rst.txt | 6 + docs/_sources/cli/main.rst.txt | 7 + docs/_sources/cli/setconfig.rst.txt | 6 + docs/_sources/cli/validate.rst.txt | 6 + docs/_sources/honeybee.altnumber.rst.txt | 7 + docs/_sources/honeybee.aperture.rst.txt | 7 + .../honeybee.boundarycondition.rst.txt | 7 + docs/_sources/honeybee.checkdup.rst.txt | 7 + docs/_sources/honeybee.cli.compare.rst.txt | 7 + docs/_sources/honeybee.cli.create.rst.txt | 7 + docs/_sources/honeybee.cli.edit.rst.txt | 7 + docs/_sources/honeybee.cli.lib.rst.txt | 7 + docs/_sources/honeybee.cli.rst.txt | 23 + docs/_sources/honeybee.cli.setconfig.rst.txt | 7 + docs/_sources/honeybee.cli.validate.rst.txt | 7 + docs/_sources/honeybee.colorobj.rst.txt | 7 + docs/_sources/honeybee.config.rst.txt | 7 + docs/_sources/honeybee.dictutil.rst.txt | 7 + docs/_sources/honeybee.door.rst.txt | 7 + docs/_sources/honeybee.extensionutil.rst.txt | 7 + docs/_sources/honeybee.face.rst.txt | 7 + docs/_sources/honeybee.facetype.rst.txt | 7 + docs/_sources/honeybee.logutil.rst.txt | 7 + docs/_sources/honeybee.model.rst.txt | 7 + docs/_sources/honeybee.orientation.rst.txt | 7 + docs/_sources/honeybee.properties.rst.txt | 7 + docs/_sources/honeybee.room.rst.txt | 7 + docs/_sources/honeybee.rst.txt | 47 + docs/_sources/honeybee.search.rst.txt | 7 + docs/_sources/honeybee.shade.rst.txt | 7 + docs/_sources/honeybee.shademesh.rst.txt | 7 + docs/_sources/honeybee.typing.rst.txt | 7 + docs/_sources/honeybee.units.rst.txt | 7 + .../_sources/honeybee.writer.aperture.rst.txt | 7 + docs/_sources/honeybee.writer.door.rst.txt | 7 + docs/_sources/honeybee.writer.face.rst.txt | 7 + docs/_sources/honeybee.writer.model.rst.txt | 7 + docs/_sources/honeybee.writer.room.rst.txt | 7 + docs/_sources/honeybee.writer.rst.txt | 24 + docs/_sources/honeybee.writer.shade.rst.txt | 7 + .../honeybee.writer.shademesh.rst.txt | 7 + docs/_sources/index.rst.txt | 62 + docs/_sources/modules.rst.txt | 7 + docs/_static/basic.css | 925 +++ .../css/bootstrap-responsive.css | 1109 +++ .../css/bootstrap-responsive.min.css | 9 + .../_static/bootstrap-2.3.2/css/bootstrap.css | 6167 +++++++++++++++ .../bootstrap-2.3.2/css/bootstrap.min.css | 9 + .../img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../img/glyphicons-halflings.png | Bin 0 -> 12799 bytes docs/_static/bootstrap-2.3.2/js/bootstrap.js | 2287 ++++++ .../bootstrap-2.3.2/js/bootstrap.min.js | 6 + .../bootstrap-3.4.1/css/bootstrap-theme.css | 587 ++ .../css/bootstrap-theme.css.map | 1 + .../css/bootstrap-theme.min.css | 6 + .../css/bootstrap-theme.min.css.map | 1 + .../_static/bootstrap-3.4.1/css/bootstrap.css | 6834 +++++++++++++++++ .../bootstrap-3.4.1/css/bootstrap.css.map | 1 + .../bootstrap-3.4.1/css/bootstrap.min.css | 6 + .../bootstrap-3.4.1/css/bootstrap.min.css.map | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes docs/_static/bootstrap-3.4.1/js/bootstrap.js | 2580 +++++++ .../bootstrap-3.4.1/js/bootstrap.min.js | 6 + docs/_static/bootstrap-3.4.1/js/npm.js | 13 + docs/_static/bootstrap-sphinx.css | 223 + docs/_static/bootstrap-sphinx.js | 175 + .../bootswatch-2.3.2/amelia/bootstrap.min.css | 9 + .../cerulean/bootstrap.min.css | 9 + .../bootswatch-2.3.2/cosmo/bootstrap.min.css | 9 + .../bootswatch-2.3.2/cyborg/bootstrap.min.css | 9 + .../bootswatch-2.3.2/flatly/bootstrap.min.css | 9 + .../img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../img/glyphicons-halflings.png | Bin 0 -> 12799 bytes .../journal/bootstrap.min.css | 9 + .../readable/bootstrap.min.css | 9 + .../simplex/bootstrap.min.css | 9 + .../bootswatch-2.3.2/slate/bootstrap.min.css | 9 + .../spacelab/bootstrap.min.css | 9 + .../bootswatch-2.3.2/spruce/bootstrap.min.css | 9 + .../superhero/bootstrap.min.css | 9 + .../bootswatch-2.3.2/united/bootstrap.min.css | 9 + .../cerulean/bootstrap.min.css | 11 + .../bootswatch-3.4.1/cosmo/bootstrap.min.css | 11 + .../bootswatch-3.4.1/cyborg/bootstrap.min.css | 11 + .../bootswatch-3.4.1/darkly/bootstrap.min.css | 11 + .../bootswatch-3.4.1/flatly/bootstrap.min.css | 11 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../journal/bootstrap.min.css | 11 + .../bootswatch-3.4.1/lumen/bootstrap.min.css | 11 + .../bootswatch-3.4.1/paper/bootstrap.min.css | 11 + .../readable/bootstrap.min.css | 11 + .../sandstone/bootstrap.min.css | 11 + .../simplex/bootstrap.min.css | 11 + .../bootswatch-3.4.1/slate/bootstrap.min.css | 11 + .../spacelab/bootstrap.min.css | 11 + .../superhero/bootstrap.min.css | 11 + .../bootswatch-3.4.1/united/bootstrap.min.css | 11 + .../bootswatch-3.4.1/yeti/bootstrap.min.css | 11 + docs/_static/custom.css | 65 + docs/_static/doctools.js | 156 + docs/_static/documentation_options.js | 13 + docs/_static/file.png | Bin 0 -> 286 bytes docs/_static/js/jquery-1.12.4.min.js | 5 + docs/_static/js/jquery-fix.js | 2 + docs/_static/language_data.js | 199 + docs/_static/minus.png | Bin 0 -> 90 bytes docs/_static/plus.png | Bin 0 -> 90 bytes docs/_static/pygments.css | 84 + docs/_static/searchtools.js | 620 ++ docs/_static/sphinx_highlight.js | 154 + docs/cli/compare.html | 1272 +++ docs/cli/create.html | 1642 ++++ docs/cli/edit.html | 1868 +++++ docs/cli/index.html | 1190 +++ docs/cli/lib.html | 1228 +++ docs/cli/main.html | 1224 +++ docs/cli/setconfig.html | 1214 +++ docs/cli/validate.html | 1288 ++++ docs/genindex.html | 4924 ++++++++++++ docs/honeybee.altnumber.html | 1283 ++++ docs/honeybee.aperture.html | 2215 ++++++ docs/honeybee.boundarycondition.html | 1547 ++++ docs/honeybee.checkdup.html | 1291 ++++ docs/honeybee.cli.compare.html | 1194 +++ docs/honeybee.cli.create.html | 1194 +++ docs/honeybee.cli.edit.html | 1194 +++ docs/honeybee.cli.html | 1262 +++ docs/honeybee.cli.lib.html | 1193 +++ docs/honeybee.cli.setconfig.html | 1194 +++ docs/honeybee.cli.validate.html | 1243 +++ docs/honeybee.colorobj.html | 1517 ++++ docs/honeybee.config.html | 1378 ++++ docs/honeybee.dictutil.html | 1239 +++ docs/honeybee.door.html | 2057 +++++ docs/honeybee.extensionutil.html | 1367 ++++ docs/honeybee.face.html | 2803 +++++++ docs/honeybee.facetype.html | 1351 ++++ docs/honeybee.html | 2139 ++++++ docs/honeybee.logutil.html | 1231 +++ docs/honeybee.model.html | 3431 +++++++++ docs/honeybee.orientation.html | 1339 ++++ docs/honeybee.properties.html | 2590 +++++++ docs/honeybee.room.html | 3192 ++++++++ docs/honeybee.search.html | 1293 ++++ docs/honeybee.shade.html | 1777 +++++ docs/honeybee.shademesh.html | 1613 ++++ docs/honeybee.typing.html | 1519 ++++ docs/honeybee.units.html | 1256 +++ docs/honeybee.writer.aperture.html | 1199 +++ docs/honeybee.writer.door.html | 1199 +++ docs/honeybee.writer.face.html | 1199 +++ docs/honeybee.writer.html | 1217 +++ docs/honeybee.writer.model.html | 1199 +++ docs/honeybee.writer.room.html | 1199 +++ docs/honeybee.writer.shade.html | 1199 +++ docs/honeybee.writer.shademesh.html | 1199 +++ docs/index.html | 1228 +++ docs/modules.html | 1315 ++++ docs/objects.inv | Bin 0 -> 7560 bytes docs/py-modindex.html | 1328 ++++ docs/search.html | 1155 +++ docs/searchindex.js | 1 + 250 files changed, 143207 insertions(+) create mode 100644 .nojekyll create mode 100644 README.md create mode 100644 docs/.buildinfo create mode 100644 docs/.doctrees/cli/compare.doctree create mode 100644 docs/.doctrees/cli/create.doctree create mode 100644 docs/.doctrees/cli/edit.doctree create mode 100644 docs/.doctrees/cli/index.doctree create mode 100644 docs/.doctrees/cli/lib.doctree create mode 100644 docs/.doctrees/cli/main.doctree create mode 100644 docs/.doctrees/cli/setconfig.doctree create mode 100644 docs/.doctrees/cli/validate.doctree create mode 100644 docs/.doctrees/environment.pickle create mode 100644 docs/.doctrees/honeybee.altnumber.doctree create mode 100644 docs/.doctrees/honeybee.aperture.doctree create mode 100644 docs/.doctrees/honeybee.boundarycondition.doctree create mode 100644 docs/.doctrees/honeybee.checkdup.doctree create mode 100644 docs/.doctrees/honeybee.cli.compare.doctree create mode 100644 docs/.doctrees/honeybee.cli.create.doctree create mode 100644 docs/.doctrees/honeybee.cli.doctree create mode 100644 docs/.doctrees/honeybee.cli.edit.doctree create mode 100644 docs/.doctrees/honeybee.cli.lib.doctree create mode 100644 docs/.doctrees/honeybee.cli.setconfig.doctree create mode 100644 docs/.doctrees/honeybee.cli.validate.doctree create mode 100644 docs/.doctrees/honeybee.colorobj.doctree create mode 100644 docs/.doctrees/honeybee.config.doctree create mode 100644 docs/.doctrees/honeybee.dictutil.doctree create mode 100644 docs/.doctrees/honeybee.doctree create mode 100644 docs/.doctrees/honeybee.door.doctree create mode 100644 docs/.doctrees/honeybee.extensionutil.doctree create mode 100644 docs/.doctrees/honeybee.face.doctree create mode 100644 docs/.doctrees/honeybee.facetype.doctree create mode 100644 docs/.doctrees/honeybee.logutil.doctree create mode 100644 docs/.doctrees/honeybee.model.doctree create mode 100644 docs/.doctrees/honeybee.orientation.doctree create mode 100644 docs/.doctrees/honeybee.properties.doctree create mode 100644 docs/.doctrees/honeybee.room.doctree create mode 100644 docs/.doctrees/honeybee.search.doctree create mode 100644 docs/.doctrees/honeybee.shade.doctree create mode 100644 docs/.doctrees/honeybee.shademesh.doctree create mode 100644 docs/.doctrees/honeybee.typing.doctree create mode 100644 docs/.doctrees/honeybee.units.doctree create mode 100644 docs/.doctrees/honeybee.writer.aperture.doctree create mode 100644 docs/.doctrees/honeybee.writer.doctree create mode 100644 docs/.doctrees/honeybee.writer.door.doctree create mode 100644 docs/.doctrees/honeybee.writer.face.doctree create mode 100644 docs/.doctrees/honeybee.writer.model.doctree create mode 100644 docs/.doctrees/honeybee.writer.room.doctree create mode 100644 docs/.doctrees/honeybee.writer.shade.doctree create mode 100644 docs/.doctrees/honeybee.writer.shademesh.doctree create mode 100644 docs/.doctrees/index.doctree create mode 100644 docs/.doctrees/modules.doctree create mode 100644 docs/.nojekyll create mode 100644 docs/README.md create mode 100644 docs/_modules/honeybee/altnumber.html create mode 100644 docs/_modules/honeybee/aperture.html create mode 100644 docs/_modules/honeybee/boundarycondition.html create mode 100644 docs/_modules/honeybee/checkdup.html create mode 100644 docs/_modules/honeybee/cli/validate.html create mode 100644 docs/_modules/honeybee/colorobj.html create mode 100644 docs/_modules/honeybee/config.html create mode 100644 docs/_modules/honeybee/dictutil.html create mode 100644 docs/_modules/honeybee/door.html create mode 100644 docs/_modules/honeybee/extensionutil.html create mode 100644 docs/_modules/honeybee/face.html create mode 100644 docs/_modules/honeybee/facetype.html create mode 100644 docs/_modules/honeybee/logutil.html create mode 100644 docs/_modules/honeybee/model.html create mode 100644 docs/_modules/honeybee/orientation.html create mode 100644 docs/_modules/honeybee/properties.html create mode 100644 docs/_modules/honeybee/room.html create mode 100644 docs/_modules/honeybee/search.html create mode 100644 docs/_modules/honeybee/shade.html create mode 100644 docs/_modules/honeybee/shademesh.html create mode 100644 docs/_modules/honeybee/typing.html create mode 100644 docs/_modules/honeybee/units.html create mode 100644 docs/_modules/index.html create mode 100644 docs/_sources/cli/compare.rst.txt create mode 100644 docs/_sources/cli/create.rst.txt create mode 100644 docs/_sources/cli/edit.rst.txt create mode 100644 docs/_sources/cli/index.rst.txt create mode 100644 docs/_sources/cli/lib.rst.txt create mode 100644 docs/_sources/cli/main.rst.txt create mode 100644 docs/_sources/cli/setconfig.rst.txt create mode 100644 docs/_sources/cli/validate.rst.txt create mode 100644 docs/_sources/honeybee.altnumber.rst.txt create mode 100644 docs/_sources/honeybee.aperture.rst.txt create mode 100644 docs/_sources/honeybee.boundarycondition.rst.txt create mode 100644 docs/_sources/honeybee.checkdup.rst.txt create mode 100644 docs/_sources/honeybee.cli.compare.rst.txt create mode 100644 docs/_sources/honeybee.cli.create.rst.txt create mode 100644 docs/_sources/honeybee.cli.edit.rst.txt create mode 100644 docs/_sources/honeybee.cli.lib.rst.txt create mode 100644 docs/_sources/honeybee.cli.rst.txt create mode 100644 docs/_sources/honeybee.cli.setconfig.rst.txt create mode 100644 docs/_sources/honeybee.cli.validate.rst.txt create mode 100644 docs/_sources/honeybee.colorobj.rst.txt create mode 100644 docs/_sources/honeybee.config.rst.txt create mode 100644 docs/_sources/honeybee.dictutil.rst.txt create mode 100644 docs/_sources/honeybee.door.rst.txt create mode 100644 docs/_sources/honeybee.extensionutil.rst.txt create mode 100644 docs/_sources/honeybee.face.rst.txt create mode 100644 docs/_sources/honeybee.facetype.rst.txt create mode 100644 docs/_sources/honeybee.logutil.rst.txt create mode 100644 docs/_sources/honeybee.model.rst.txt create mode 100644 docs/_sources/honeybee.orientation.rst.txt create mode 100644 docs/_sources/honeybee.properties.rst.txt create mode 100644 docs/_sources/honeybee.room.rst.txt create mode 100644 docs/_sources/honeybee.rst.txt create mode 100644 docs/_sources/honeybee.search.rst.txt create mode 100644 docs/_sources/honeybee.shade.rst.txt create mode 100644 docs/_sources/honeybee.shademesh.rst.txt create mode 100644 docs/_sources/honeybee.typing.rst.txt create mode 100644 docs/_sources/honeybee.units.rst.txt create mode 100644 docs/_sources/honeybee.writer.aperture.rst.txt create mode 100644 docs/_sources/honeybee.writer.door.rst.txt create mode 100644 docs/_sources/honeybee.writer.face.rst.txt create mode 100644 docs/_sources/honeybee.writer.model.rst.txt create mode 100644 docs/_sources/honeybee.writer.room.rst.txt create mode 100644 docs/_sources/honeybee.writer.rst.txt create mode 100644 docs/_sources/honeybee.writer.shade.rst.txt create mode 100644 docs/_sources/honeybee.writer.shademesh.rst.txt create mode 100644 docs/_sources/index.rst.txt create mode 100644 docs/_sources/modules.rst.txt create mode 100644 docs/_static/basic.css create mode 100644 docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.css create mode 100644 docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.min.css create mode 100644 docs/_static/bootstrap-2.3.2/css/bootstrap.css create mode 100644 docs/_static/bootstrap-2.3.2/css/bootstrap.min.css create mode 100644 docs/_static/bootstrap-2.3.2/img/glyphicons-halflings-white.png create mode 100644 docs/_static/bootstrap-2.3.2/img/glyphicons-halflings.png create mode 100644 docs/_static/bootstrap-2.3.2/js/bootstrap.js create mode 100644 docs/_static/bootstrap-2.3.2/js/bootstrap.min.js create mode 100644 docs/_static/bootstrap-3.4.1/css/bootstrap-theme.css create mode 100644 docs/_static/bootstrap-3.4.1/css/bootstrap-theme.css.map create mode 100644 docs/_static/bootstrap-3.4.1/css/bootstrap-theme.min.css create mode 100644 docs/_static/bootstrap-3.4.1/css/bootstrap-theme.min.css.map create mode 100644 docs/_static/bootstrap-3.4.1/css/bootstrap.css create mode 100644 docs/_static/bootstrap-3.4.1/css/bootstrap.css.map create mode 100644 docs/_static/bootstrap-3.4.1/css/bootstrap.min.css create mode 100644 docs/_static/bootstrap-3.4.1/css/bootstrap.min.css.map create mode 100644 docs/_static/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.eot create mode 100644 docs/_static/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.svg create mode 100644 docs/_static/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.ttf create mode 100644 docs/_static/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.woff create mode 100644 docs/_static/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.woff2 create mode 100644 docs/_static/bootstrap-3.4.1/js/bootstrap.js create mode 100644 docs/_static/bootstrap-3.4.1/js/bootstrap.min.js create mode 100644 docs/_static/bootstrap-3.4.1/js/npm.js create mode 100644 docs/_static/bootstrap-sphinx.css create mode 100644 docs/_static/bootstrap-sphinx.js create mode 100644 docs/_static/bootswatch-2.3.2/amelia/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/cerulean/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/cosmo/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/cyborg/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/flatly/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/img/glyphicons-halflings-white.png create mode 100644 docs/_static/bootswatch-2.3.2/img/glyphicons-halflings.png create mode 100644 docs/_static/bootswatch-2.3.2/journal/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/readable/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/simplex/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/slate/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/spacelab/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/spruce/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/superhero/bootstrap.min.css create mode 100644 docs/_static/bootswatch-2.3.2/united/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/cerulean/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/cosmo/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/cyborg/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/darkly/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/flatly/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/fonts/glyphicons-halflings-regular.eot create mode 100644 docs/_static/bootswatch-3.4.1/fonts/glyphicons-halflings-regular.svg create mode 100644 docs/_static/bootswatch-3.4.1/fonts/glyphicons-halflings-regular.ttf create mode 100644 docs/_static/bootswatch-3.4.1/fonts/glyphicons-halflings-regular.woff create mode 100644 docs/_static/bootswatch-3.4.1/fonts/glyphicons-halflings-regular.woff2 create mode 100644 docs/_static/bootswatch-3.4.1/journal/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/lumen/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/paper/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/readable/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/sandstone/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/simplex/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/slate/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/spacelab/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/superhero/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/united/bootstrap.min.css create mode 100644 docs/_static/bootswatch-3.4.1/yeti/bootstrap.min.css create mode 100644 docs/_static/custom.css create mode 100644 docs/_static/doctools.js create mode 100644 docs/_static/documentation_options.js create mode 100644 docs/_static/file.png create mode 100644 docs/_static/js/jquery-1.12.4.min.js create mode 100644 docs/_static/js/jquery-fix.js create mode 100644 docs/_static/language_data.js create mode 100644 docs/_static/minus.png create mode 100644 docs/_static/plus.png create mode 100644 docs/_static/pygments.css create mode 100644 docs/_static/searchtools.js create mode 100644 docs/_static/sphinx_highlight.js create mode 100644 docs/cli/compare.html create mode 100644 docs/cli/create.html create mode 100644 docs/cli/edit.html create mode 100644 docs/cli/index.html create mode 100644 docs/cli/lib.html create mode 100644 docs/cli/main.html create mode 100644 docs/cli/setconfig.html create mode 100644 docs/cli/validate.html create mode 100644 docs/genindex.html create mode 100644 docs/honeybee.altnumber.html create mode 100644 docs/honeybee.aperture.html create mode 100644 docs/honeybee.boundarycondition.html create mode 100644 docs/honeybee.checkdup.html create mode 100644 docs/honeybee.cli.compare.html create mode 100644 docs/honeybee.cli.create.html create mode 100644 docs/honeybee.cli.edit.html create mode 100644 docs/honeybee.cli.html create mode 100644 docs/honeybee.cli.lib.html create mode 100644 docs/honeybee.cli.setconfig.html create mode 100644 docs/honeybee.cli.validate.html create mode 100644 docs/honeybee.colorobj.html create mode 100644 docs/honeybee.config.html create mode 100644 docs/honeybee.dictutil.html create mode 100644 docs/honeybee.door.html create mode 100644 docs/honeybee.extensionutil.html create mode 100644 docs/honeybee.face.html create mode 100644 docs/honeybee.facetype.html create mode 100644 docs/honeybee.html create mode 100644 docs/honeybee.logutil.html create mode 100644 docs/honeybee.model.html create mode 100644 docs/honeybee.orientation.html create mode 100644 docs/honeybee.properties.html create mode 100644 docs/honeybee.room.html create mode 100644 docs/honeybee.search.html create mode 100644 docs/honeybee.shade.html create mode 100644 docs/honeybee.shademesh.html create mode 100644 docs/honeybee.typing.html create mode 100644 docs/honeybee.units.html create mode 100644 docs/honeybee.writer.aperture.html create mode 100644 docs/honeybee.writer.door.html create mode 100644 docs/honeybee.writer.face.html create mode 100644 docs/honeybee.writer.html create mode 100644 docs/honeybee.writer.model.html create mode 100644 docs/honeybee.writer.room.html create mode 100644 docs/honeybee.writer.shade.html create mode 100644 docs/honeybee.writer.shademesh.html create mode 100644 docs/index.html create mode 100644 docs/modules.html create mode 100644 docs/objects.inv create mode 100644 docs/py-modindex.html create mode 100644 docs/search.html create mode 100644 docs/searchindex.js diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/README.md b/README.md new file mode 100644 index 00000000..ebfb3665 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# documentation diff --git a/docs/.buildinfo b/docs/.buildinfo new file mode 100644 index 00000000..3c0c4f40 --- /dev/null +++ b/docs/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: b1b6b77ea7804bab1ee268c44f50ae98 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/.doctrees/cli/compare.doctree b/docs/.doctrees/cli/compare.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7bb9b8d2dda15fe4ad5c3fdf5f4f69c2bc034fd1 GIT binary patch literal 19440 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 IMA}^YA591O)&Kwi literal 0 HcmV?d00001 diff --git a/docs/.doctrees/cli/create.doctree b/docs/.doctrees/cli/create.doctree new file mode 100644 index 0000000000000000000000000000000000000000..cc310a4ebc6a08ba2429d47101d37d1ceb9e466c GIT binary patch literal 85034 zcmeHw3zQ^PnI<${RsC)r!h%g>fFjk>*)QHr3pCKsy$#*iG=d;xM`cD;W^`6Yni1L6 z<+IgQVGP!BO-2W2(4FJFmKhP|xQCtL_+Z9e9oKan92I00adv#L&d7{2;#p<(|L;2@ zZ^XS3nPuC1mUB9|6&d%&|Nr-YeD@LmJu-IR_;JS{hyTT^!%m~wKD@!L*V{qe3;Xes zdQj`ldhMwHf&RL;_utZ=jF)!ZxiIK;YhFJ-4xXqrnyq@*YxnQ$$E)!1sM!iPu=*3B zSBsiKTU2k1HO3ngclIY6OXIPq8MQp+r+B>9_1wto;}h_};{D!Xe6zU!u0EwuOx+=TL2 z+nuGQCG}oM{xRj&4tBk1e5MyqMD7g!)NibAtZA%hoY^>`u{Pemu@TIA8@s)B+v{$e z3%Up4M%$a8^1Mnd=z6KYfZT9nt<~H}dEL+rfseCxFX~M-mQxW+8J);)#H)Fejw+(l z2JbTw0ezb&eR~>bp%fY~1J)a7gIr$@|IUSf=fS^qz*ggY!cL{JmOcuCUkdVdXS!~u zq4v%zuL)*n-F7{6rh_h}quHKub~0w2S7k*F6NqF_13Yx+h-Ja@#XKcLwi;4X@P# z18X#A8ZG!2Ro(6ksxx-q-p1Mn^qpWnM~{|HcZ1nVINz@EZc^^Zo@m*s|j~H=jXqD4!hf%jj+y&Jzq!JY@YIw7v zBSzh<2u= z84RXLx$Vs{#f$=H%46QPF4V77UCGl!#dul*JpGa6Dc^~|8wCLUD;d2a0QS1+{vQR z>g@%uBoq)jd4%q4hYE!!{%Nd--Vj+ev+)3%v>IIfWh(6me?asR5tZw+AG2 zAuNJFB+#8iLM2=fPA40u#UKudn6>N{`;wW>DP{nQFYk1NsTPPlYSvUBe*6J0ODM?} zE>E=}!yXRZw)EZf5GEdjAzHKE$DcPNBK9xCCf4{!3q-`z;`3}dmQ(n6>RDnH5c^YsT*NWj9 zk-XJM%iERUDWPAw#7WSOVWS%!4rn(kjEiufB95WkksNkM%i%ewb`lCJF^n?Wj07OD zc~sJQWCV2P8zMt0=7;X?O_?9UA>2)3c+`_#gpO^+kWZOHxO)4|JE}MCy>`b9)$4ZM zu*2EAf9H;U%8g}C=6^T8ZqGHXjB^q z8ty%fDLz}#sLSbzcd_XSIwl_P_NKbYSTM1-gA;`z=T`hJmFJNn%Hw|mpC(fiV&r>V zJcfhf!%7UIW8h5e8&3c{=z9qzt43lz6L1{N;KDD}unF^=QLmeroPAkkdOZX!Y$Q{n>o)%+KcIz`p8JSAeO;t|DOMsdRX$_{MfjUz3)G18VJmm3Pgh&4= z(O`q99btI|Aqr=w@$9#MTYdY=MDKAzQg{lCfZtSWdjr#$Xj==z9p1V08g>rynmv4GN}k;0He_)9vvR0O6=d z#HIMpq6}98OJ2OJ8U?i~j5wmOzYf+l@Gqipjd4`&Z@`lqildl5DfMs;X~tJ6ZhLTbTfxmutK9N{X=*9yU1%xW6eMEnc!xiv!0v;|m6k&43m zJA#qNIQ8wRz8_`6hN$>>g`%pZzx*hO){5fn1-xqpO1ijn82i58crbiemdsF_y@Tc%rOJO>i ztp16ptlW`(QDqY4ivV)GrWrbD;btoCLiAk#2;MZqwc0%-mC5*tg0<(5ji zCW)>tN>N5v|EmMcO!`kM_u|z9&ER^duX<|#2#S;j%YnzG;NOue_(?kl{Z`QkkCq7s zt?7?RyJ$4nurwWi9^OjE@ss}fQ1sWsCE+LiO>pPVK9Pj$Z-GD7`4_-d>kQw7KM-f= zUxZJRRbsx3+K}$=q;z7DPC?BrQ4u%kN-Myy`5a|AlKKE>z(9!7hW|^VL1D|vY>sY2Tc9= zQd=8w!4<` zut2tZtq@UB+ube*v$9>zM|s=5171ku>+7*ZY?qXVuwB`0a#P8`%#vL7kPorl31m)| z?&)#WU0urn)8k&KIMb~FW}T5JG1FYAj-+|M5Y4!=XDxSzT)rtGk=;FnGZ3!i z>Aib`2!_I@WswxX zM$0Dsfpe9^=X$3dh?%32wI?}#bQBz?I$GJKv$YoVVEX{wqv!;Oyl%_wzzkV5=fPeI zH1}QyRzb=3Mk)o?zjBxCFil84zfhP@T&(`DiJr}kpbc18Bbop%PinwUs^?qs^_kR5Xx(20e{%2v?b88KTZ`ej7f(bbI8d-Z%15R9=H;zeF|<5x-D*@daYeme_miC}E&yCl@sOidFXhe19)$)A=G`a%S@ z;0xvEfVbqLMrDJ*t-G$>zq7j8xnaki>q&v$*urmY$=M-*TL-SYVej63)%|;`w6Jr> zuIqR1=h}0Wsi3_I;@J+}Q+Bh!Ak<4PONgxjY#=ZGmOAyCB09yEB-mJm?-nS%D#2Fo zFXH;ZhjNKg1c&mejRKv1ye@kRCDB5qlh`aUFoTnLIOBB{04L2^55AMB1k=;7F4XrA zqU2J$2AHy&mp0Z_I=Dq3-Kw)q+^N#{u+0LAMGx2(04&i(4=l>wJe1p;mg^i{(TLD5 zn9fjF=gTj3nA`UM6_$WFbBUGzdj(y($q&o57Ciy#l2Ux~V83u_>wc2bzu!Qh)iwY< zfvWW5Q?k?qwgYH?lO+Cufkdl40a_Aez?dYak+&9+u($yuVEY5|m%AqY!@!FFTX69* z7QKY_f|m^#-`aV(No8*0Vfc=Ru293$Kgxw7f=s67rK8SsMUIOM5F*A@^&&E z0v{8S2@|fH#~|fWFF%{BmuXl5b5CmLeoAyMY@uE@-Sk@ZYO4ufiw^AXfKO@3&jY{U zSGKGs*-0X6#uIE`2bc52wRE3{;TgnIu;e0q)lHT<9810j+iVJfK4DrSSy&gj1;`e?Bcfev?A%PYMzHkCfPdfd3ixf#7nk+AGhQtN1^l zt)nOmP}2V@KAL#JSMUy5%gzP0{+H=XxR&rqR_U-b2$yea;eJD33HLB%?rEXR%;${p zY4De0iA;l&Qpss>jxfruG!KKh;4^n?%mo`^lnt6!m4SGbFbcZ!uwe&gj{5!uAimOY z>t&S?;g-^%vyJ>wC9P+GEU}qqQ6*Fi=nAA{*u}1`q7h*;BLi9HwzEOjErPBgK$f0> z1jvHDluB=K-MK&2&2`lm^v{P6|0 z;~iD7bg!ieOI-zA_;tA0V5v(O%SJ4<8L$-Yf1FX~^%;_a`5dGYKY9VAG~+=+2>8N9 zOof!FDZAvJ+%7R-iFZrp{tDtoazW7ln}J)C{!_|58?f-(Mabh|;eMp z0U&H11PFhOl>i|4|D-(Y^Shwd$8T2L+9QSNVz}TTs8kRaJZP@MaRG8&92b0$F=C*L z;{x8}`VgN|7mf?K4d^Rb;DTp>NV+`!9V`)CKuX6TE^rIr0ylvRt}BHL&~L!!>-ZH+ z1-@R#PdJ{(J})~NbAH7o-)p3sg$?)eR+YRd11SJkd^*NeOzP)M6S;~51Ox)VvWF&A5BwC>cJ&6g_@RCeT0Vk{f zQ4+bqKxBD2st5uNB)-fRK@1Aq4oAEQZ}HCohHP-eKQqNP;)vI5=Myk|!FUr{D8At0 zO=7*y*XMR@DzKzS&)2fbAe;rl zA$JrZkK>Truu?7#(M(hv#7YA=gx^IRqRvlr3em-I$ShPc#QU^_o8~GUhalI*amX!< z5d&QuhwvWf!9rSZ&in+oA$=ta9P$7VNpZ+WutabODIHxLvb`KI=)nh8LATNk0{D>h zLThiQR#T@fE-pib+wJ=gVb?43AJ>#=sN&X}?i8kipbW`YmG4yfe30>Dnsdn~jY2#C zc-$_cp43awPLrS5#H*4uIn+ttmX7Z+rubYbOTnH;MI)n!J?6HvVb2qSt|2B!^aLbe z&k4{!T-2m2<@=0*1S?phCqacZ9z>ek&IUPuBIp_dMCu7hfE)mhB9{y)OZk4rK!O#N z(UUM55NU2ZTfSd6FlPlK^#mm3dy)zwsfD5LLrBv6B4z)#2J(J2WiO-2Byl4JU?hyj zb8<%{w}Yjfi5-r707U9Pj+eiKiw%yvk9C3(N8Xx=BT0`Zf#g&WMUcLm{vxp?b#i(r zxnS)}g_~HCH*PVY$;GVl!lB7EMabi5@^q|J0!^Ne^#;%+zpFu$n+j3K&}0QF8Bkjq zO|COn;b;)l3p9Bb5J}Nw6-xw7lG4#dlchGP z_X;eG_7V%DTT7w6Ub_h?vHSr0x$I)-DU}{h3zDXsZRCF$i=IF+jdhDEJ!SCqMy6$4 z14;q6L!yz<12=Qq*}&rcg03Neo1TCKu$W*yz(p+nmOlLf11VM@LQjec;Nm3-Edc*0 zZ%AVP$Uux0;L;K!z0M?2?6_h(A4RRf4nDjY==VPg7aQadGG>j)VGfVw5lfWRq{8_y z@@DZPcaqqhY#XPay3crUIu0Z*bG*Z_c^STDzp)oam_=^#M*Q#ub}-%uY31lwDDcO1 zo)@imcC{fzH~e)C?1*4L$uG)|+WVzqd@ffp49MegDd+`S1bwmyc^r9s4J&0Mj}-?F zoJV`?yurDwA7I@9^uh0RIh=DGS zKzRT2P$GRn4g%rUsjp;#K+ass5y)CB5d=a?#~=cU3Lp?jFQCjf4I~RpjMB0`lZ%2D z?Bs;J?0vri!YhqJ)>Oc^RVt!6XPYQypb?QAVNoSgOy^RhV%W{v7m7wkk4DUGXQPq5 zg03OZh@OB18doh!(#(^9jur&cTaKj0M;11ehvkpfx)E!J53179TxmgzaHL|DQncLF_ zxN$^CEjeaMRpWbrxsU}ED3CML^Lw`kYjE;JLG&x&^1KJ(G!pe zIjLOhY^EV~SK9qk2C}Tej-ISU*hyzwXLO}+OTxZyAj~TCXbDq84=TU?_d%-N*bR># zh4%fY;bIef9%3w;g3m(cKWF{2kgt$^eEhOJjG2la=`q)fLRv{bk*dan4j1lFLFaTJ zm1Od%w( zLpp`BU#e5%yu8Fh2+tQ)VE+zUr>IuiJeSBO2JQ2G*r(J!<#SSB-p{&xDAahbXhdi_ zsJDt>%5Un`wyhZG-SBQJ14TjD80fDtW){dm9~QDIVW1xuv{@M_XJse@{XD#r8t50W zL=2Raj;eu{kDgmfMb9mCmU4*b2`vm-=QG%$iRigSnMHh-b@x!l`7P1N=#5j`wql%5 z!n>`E6XjrIoZn>3ERb<7T0R7%{#QYpm2q-bhBD4GfM9BzFU1luPEtCm#yLdv1nac^ zfJ%v;LzpLzidy^Jj0%yAo~nUfkgG42@OGnUWb_8AZCf$WSHZij3={=nW1#C9GYe#( zHw#&nh@LkI+N=zevoe%{`tVL_pa-!;43w0Ps)6n-0dMtbP2=shD-UR``Zh`f-%~T% z8;rB>z^cnL^Lvbqt>>q81PDn2~KjnGOjdpExWe;D&g9;d=iW>Tk)DZxtV6QJRF>{ZC0W1WOpNCW(Z$ci z_&$+1&zYR}`s=3L(4z;VZ*{Kg!AYVW7tX?f4;fu2)h*-*Qusdcri1*PQp|J_dfh{C zYASQHqiRle%+Cu80JEh3%vu1~x}a6CFpYA+1Y&`*RW5)Zy7X+A$#5M_lnPtqNJrQ4 z02s)rn#dAAn#LsaD_0a5nPBf@682?SOC(`ebnTKl?(Lg}L$E2&bd#Xlu0wybtu*`_ zRl00Lxf8}#y1wLS%?LP>9#gY3i=>Ok?l){0BhR6o*gVI~Sf-U1XN~KOU&$&j4;AGW zQlci69(3&GAiUD)+rNhDzY~={vr9f})ekIBfd%3%S$f5mI%!8T-U$`|)Hp zTvZ#W%qDiF4IGiFKAZ8f3h@~}>1rqs1Y%EbzcF3RQ zc8G5MPT}oQ!JE}sh>HToLbQ=GJIVeU-bu$oPhg3Rg-EIFSco~rvg>y&({!2e02|3{ z!$Wc(S-J4gi#oliGTp>PlHbLiD<2-n=kUt@8nAcLdKFvG2oD+C$o`(`5Fe%`HOVqO z{7^J9`tV?GJ3Bm#tpqXWY|FNCcX|Q_!h_PiN_bH2N~1s7K$cZ_(33R~9@2Wj!h?ES z66P2PD=#lKJfQO1hX+N1cH!a2(7gW=;KU|8e2;0aDLi!cb}$hvoYsLRhNEOQPQsu- zCojk-IgGkEdokC9p)@@@6teozqeJI6I9Ja*?3f1!P7mcrd~~2n1Y4S+MQj*y{X>a^ zxnKT^r8-=es}6?XbTO-J`UvMjJnnmq&pTqM;B*tblLn{PV2K1LQW`QiJzQeP*)2tc zH{vl9-PE$J_>f5%wZ<1&0yv!LSLzMS?%R%fmZ^;lPU#;)dC~!n`lQs>!?^;tjAW5$ zWb~0t+qQI!egN;bn#V^`WX|I&`0x#k8IyC<>@Z`J*8Cy`{vjbN-QdgM9_|ygB@sue z8sCu0SsBVbJOuBg?%@+yBJP2dhI0?H3+2?XZk9rs#?PNZE;@_93J-ZCiNh1ehNo}K zp8Is6p2L~^$FRoWOnybohwOlxAdGO@$g0&>wUn)d5&efmAeITE% zON)xmiy?b3TQ5#MivR!N;WDdC#*yZ-Tb?f3E&eyLMnd%E7fOCq=_3|o88lp*=a@^ED>u9ILxHk(Lq30C$N%OZ?>o{qsl-8a zyFqlNS9=CrYvI+NJBsu-AGuI~z!#o}UF{jjXPFG!8A~v5T5nFy;bar3<9Y{1Pb5|EyN z#2laQP+sOibw5e>`7r~5Rh1%aFiH{gaw3_$Rk|@VUlf*Rg4u?sa z+@NjQP5-?Ec=3M^E}7GRiiezMjB7{8>VdtVD0W~k&JX@-oY#Bo5iZs8i@9o<27-7n ztkSigmtDI+S)IOJggl1nJa2n8fFaKxVGXq$h)N-+18JYtXEg(>~S(KbIRL>J5B z^gL8DOx2Rl2Nenb$XtczaYC*Qpp75BtGwVz#)yF~p2vyzIG?AGzDKiLh)*nW51_AP zk;mzr)qGOv)gvW2IbdpgVpSD-B?SKW29k8zhe3EkqZ? z1`k0cLkv!1g9pu3I5t48i(`WiGDZw^acsbQoU4m8yc}%6Z9rei0vkL7MA8MP?_h~w z15!E`u>qXFYmW_*2k>6cr{4IoSkjkeVFTrGO>qJ*c6-_Bm4!QjmnkDxl%zAVL<=v7 zMn;bo%x!0*g;P$C7hm=Ru3&t=U^Ql9s1A^Vkkcya=!H&jF5Xu*5$z%{F3*10y?vH?cZ56&y~T z$h+__lKp;tZoeC5F|K8mL39g*RPHE39!Dy-VWnK8qM5}wh?NGA3cs74#po2Giy@U+ zsANC{X{6FLSK&wnxh{@WZeffV=;BC)_c)Iw(ztVw3b!zQB@3kT01!!$%15w7kP0as zU8Hh#N#LL!wVSt*E$t1}dIV;$?d6x0qJx~#i@lG4g|#$rz*>@oEGQ(8D3`w#JE z)dSXSmzjQw}y&%N^j2bYDqtq zKJeQPRelO6@}I@aI7rt9T7HtLh!I*Y%t^XTPZp+escYxu>Y4#UzJgU=I0$)p5%M^M zyc8>CL&)r7da>RBirmfa0*V|srneAv3`pJxl?;F_4J3D&t8gHRycY+O7coW*ba5cb z`(2L-Q%b{^!?-=^D_H=^w*rwANWKkA1W1z7F$p9Sr^Xfll8JgM{3{70@uXhteFaGF zC6lE2iWdYSrj)hsp1_94;8=%J*!?QE#?CxWgaproFF1k}kps@Fh* z6_nJIFd8UnZaZ7PUpFvk1ts+aB;>0(ke6Wu%`Y;*|E+<%UrpJoU=rO^5ikiKUteku zJ?l+(%7t@a*va2^Xz~Fd$$uO#e+L&EG1tCQhcj>fLDy z9;C6(Vpe(KFy)#e=D@QzGxh zG3BX@5d&QuQ}TZ2N+Uf$&g3MwDt#pjOnDa&Nik&=O9WGr($U3~<+fPCX}$K#sLA7c z2lDJD$J|+ShxCL}KftaoyL3AIdA&^0xDu2?Z-+!9qepM%wzJX2`vqM?pf^1M33MUO z=Vf6+{4L%30|rv8kc6HT6~!sX^DIpGG0yGgsj#1Z7Yhg*?F+G0??P2=9NcJklBDpb&1I z`brikaAq&auQU=F-I={e#js10 z7m7wkk4VgIXCsomg03MDiJpK2B1xRj%fd_Io^<)IH;`n7O!OorkV*1*UPe>$rXv_wg#1ZVcbTkS=^opjjyVJwk=LrTYDz=8Qb`+$>7w^;Ja zBATF$C0u+E`>*WaceLmBGELH}q2*rTM?@o|4?E_zv%}7p1YJXf9X$bwu#-BWm-&*^ zU1|DH8OX8k4lMT9rvWF$0=;$>wP+DQtTegVvfSrlm{5~kFH2W_`?jaSs=4sbSiXC=1i|4;{L0k&C0AfD?^#}89*>K>z87Q zm^CR4XV$U{WnNtU7uiaxVp9g)qREPvKw??10-t2^4EOSeG?8_MdJGd3zY=Qj-aA4zfW>(G5cFe?spDO5+&d`TgiF*)(++)wi4#8NagH!dKuhB(pLz?zXzui5dfmamihNSf0w8 zHZAUOjUaFLop{4>v!(wuC8QlDjn$jUk9>FCx+dD zl2!dm;l!{XEz&o9E(S#?^8gQ<7;HFN5m;YSU+;;Zj!_$H; z-RR9S6Re(q#NvZC83_ab+TWyi`+?{LFty|ek!O|QNgR$<`YmP`QbYPR1^+K!! z!~SGqR(=nGwB92_>6C%;1;Q`WU*gw28g7C=mwU^AexlQ4x(A~E<0__z=b#l+7iLc!Dsj9 zT0j_hPQ@?-hktQ@nuTHJn(cZpSLvd&>idVWhs(m3b1HLPJiu6O(t%MPzMx88pgp7V z1gOT5GAT=k^G>F4Tp5y6F_yUHZK4rw<;RZ& zrPP1lK$sO;(G!+HE30+N0nT&az9j9F2GXoBik39#oF<7C#2amlPc%|QC7yH{1#@n<9+F=av_tbXZg6hFnKow=J?nDD zYkTk}56FNU=nWu+G@Ud*=IEBH_&;)0Q8&A+MA9$Hj$I%y^lTCGI2igiRw@dH{t+t; zfFXW24TgSNh%N?(egc&Ypd$^2er&G7!4Ps?91K0p7%|Yr!4U6p9?GP@$pJ&${`HkC zz|gt>hJ&G3Vu^quQaZX|Xkc%R38jcUX#IG-gb-SQz2#lpCAc3(KRRSK;uqdTFV<5l^OX&$vu~hk)H*?$B(tWFeIV&`# zCm$9FEo0bF7emqM!}(Y}l;)B{OV@1zO9=xeCjzaT-Xf^mN(Kxi!wlw-1Zl z)`~_(kKD{{XJd;?1zkfRH$4FfY$0-Kuo(&Qw{+q=45V103Oy+*hO^79akGIKE6k-O zM!K0v9~C>Ev>0g>$*S>kXw<(RE;hL0rHoG_t~hF0EttX_wf9Q}Z82GK-(Lu2G^L;y z2xS~8LLNsMZ^260C?hwk#;;@D0i?n20@BcB)wr(^l?-kC2dHF->S?s`@6A;>+CUi; zM;mWsj2P(RXoL4ZS03pGa?l31PJJZ{wDIRaBweNZ3oH?|K}yFK+JJl-HfST6Nu%)W zmy$!{tJt|^7wAToL*v^_#d!B89ggLk(KkgSqemX*wzHAPzX-a9KpuJm638QwFM|b> z#69WYPdH-)NKa2v0)ZscWiXnOHziRg8Hln%B3h!P3!3y%;jQL;rIFZ8b$kaJ_Q!w+ z8#M9_rW0B;^8a%7j92A$vS9+_JXYBhi7v#iGS~QA$Rg~Q`D$@Hypsl&tFc4^3n?92 zfd%qr*aVhj#*BePk$f63Yx4)pm34X%%aySYd#h|{8ELMJJDJ`L6<%H^8X0|fF}Ix^ zULrx)5aC5nKq9=PvSKi2p1Lc&`P&U-Sq*aaWFOnK z`SX%Va!bMqbzw4gfu;&g`|pH{O`v%#ym|hh3wuxU<~VR-4I}YS4b;~ zKvUKD-a;w0A0p{TnSu*~ji10@IWd{8m|AJx*;w(Rg)f#?w zW(?a^^X$wR{|g02m&FG%V|*`HsFs79?}|o7AAPiKOK0YP3*K$@oi0it^E+K-x6(6= z8Ix1e)d!nPZdLIw#tvkrNFS1#aVhIueQ>Ze#S29vqc=ru z+lnb}gm+t+B1*x=6gM+w7RVHD6SC5QQ-dkqB51RU#+;R*Ofi6WQd8_;iI^fO9aU4j zuvk=NUyH^Siv<@kXdcroqfnA)>zh9(^#Rd#Vd`D*I+w+ z89xH`d25iMnn(Y>}@GtDSBD9~g#VAJPWIV^I*f zt^V%g;${39uMU6qkmTdzRkdEX3*RYLSzCMJ75q-C+4lN-;w7OM;dcM9AD>hYYQ3o0 z3O7u5gLdS#>-~8AwQj5Dh5Zlo*S(#*aGZ{g`+FLz_ry!tzW<;LEiJ8s2*Svn?Z6+) z;V|O}NcE6-XHan!EG;_~dD5 z26vMwKi(a$3}MSyyEj`s3|~3S_V12Yg;BTJsn&woS*RF7gKOv=ujP?D)wyQWsMcC; z7y>i!K2|~8Skd)5@U3RG6f;v3akC*nM>B^;*unFZelRs9yZa3&w z8}M;P%Y!e(#*x$-tU|4(l2=+8Bdzq~wW(iHP52XQVCG{LZCBF3YoD3?Ayqj(5qSXJ z3mYJ!7Vy-MSGL^tOwXP1K;m`ydy&`f$EUzPzMxyLLKY3s9C%HWNP4^$w5NehkVv!6 z6{0a7uX1})P?fjhMNLq*mG$0irz%tu1WRtf7b#x1?Y6M%R+BqK*|GQKtxo9m>OuAJ zEGpEA-r-IVdR4V1(UMwJJ=6@F5mDLI)p|2@r&`DeqjG|q3YgsrU?v3PAa)0hu4Io@ zr<*Nc?#_OE8kXQCA$(Q?dl;c_u(djL`SPwiC;r@he0&nx8)!~@1{AT?oNY$^8&5nh zUe)nBRj?8dtQ59L!b?`*ohcV+N7Ddj7)70M>&A_6JKWHjkHCLz2)Z+1QK#aQgaCN5 z8hNwOJ>Z1mC2+rT?xqVto~ydkwN&$XM>hXT-aHtuiz<82>uzXz(KLAnIE0OjXto6} zTN=4jU`6$)(cir!UJE)oTNTDB7^sFF)R24P6T^A`YXa& z7YywUJ+SH!1a%7eoBmma&#PS~+O@TY3-mz8Q+op`6A?n~gS`&CViiyqH6xHebp!W+ z_5`(Ndm40r`Gu3wQG~sz)ML$A)ZJD9n@W+Q#l$6n%FIrAb+F)hprGM-5xnEn8a#Ed z>dm^%R@JT7(eDzfPr{b5$3w3*O?}!u@d;l0P#;z_;w99Zfcb(Z!sk$Ak83poVCR8% z0=+p2hyu-uz}-R{b#EHId3Zrh!OSHW#)ZCd;>jxM!M?oZ%NTK1p9Sp0Rkgz-|m z9nE)0W%9#4VdHEF7UcKF3V%1|#as$bb3O#6slr=AkcV*bjWM>>{7UNb8)NYeyNK)^ zVol)GBd_j6-r)#0<8~TdP*z8%fCEml8&%M2!S`Y4cfmV3;1bv^v1xa-jY_d*Rd6cY&%5UCD_{2d@SHy#rqVlfK2A5Yx6eczs4d#tJb&mgceaR=oTrUcQW%H7CHu!OOwLaOvXZQBk^J z4F24Tmm{L|JeFR-%N66i^bnRF#mm|WUOG#Z-iM_R;pG>i^r9#QOW=n?czH~eDof$d z3-R(sQF;(dkKpA6QMzOq{J9M;cjM(=ygZ4QZ{g)t%i*#SFK@!j5xjUS;L^g&Bck+O zEd3BKn^y8tfTaj8y;X2|GhQASr3+TWpIh;AM3kP#(hGRG0?#2QB|IqI$8+TUwRoB& zDV-%sc=Dx>M}zvm5TzGI2@j|8@dzvbF;T+fAbdPD!hfSEVUBJeGkNK*zVxI%~&vr|D!1QYV;OHwz*(@PUAF6D0}l}=8yPux%+ zBJZi`w%9KKnE`&(f*yhkz^ApK)uK)v0O-Uu?EVM91N*0f1@B%IzN^0vLTbnDLU3kY u6JJdHhZ~eQ)I|2kE5>J{_fc)*+k=HUOL6`ko?y}4_HU#&J<)u7Xl7FAo7-c-=+ z_V4Pie`Wur{Zh2J?eFZgdhJTkkLJJ|m0G<~Z3oT%4gF|2zTT}jIvY6s!cI`>)>}AOu=ibtfzrSGGhp)j~E2G6@ zg1y?jXaVPHTXbNf-VFNNdgFey#P4?7_3>U8YJ=R*t5-Y7>B36G?{pv&(({}CRGeB= z?M=%+#{J5T?O+1m=|u~>{v`g?udS#ZSzB5=sy45-Hac%(tu+;FZ1J6 zG=tsaK~S!=+Cl0sV7Ife(x`95dTwZUpcd;cncEw$9TW>!O6Oq8h?Y@-o)pfSbS@VT zaCUOc*|yp`tbgrjsC4ZZkmu9kzvJM)6X3t~P@&q1tRm&w+W1uv_+pT(KiT%DYigSu zx3x7jXz#eu)y1z_M1i1?VuC1XCOHrqzYMkqD2kAIob0kF|Sh#8V%@9 zwfbbO0snQ!{PrX&FgDxv+S(elnW%W4?o?XMnV{V*_nP%?huUaaGFP@m-M%fb6HEx* zIZtS7X>0sN&-X4v&G5P{NKV#gf~Loq@H)FY-C#-x+MYo2xznCc)R`lbt)Hwt7vu!f zpe1NH2GmDbtlB!Vg0=b4{4LNVn@FboFUezM&*QpiLA_Z;n|8?@5bLXz`M7}4$1b|~ z(hI$7wq1PnRn%LHlE;DrmcNl_>T6@Q9W{SXZJZ2wttu_|EeV6Opxqm9*DLB+wQ&11 zA|_$2#ow~k9=C6`$ADR|)54(4iRPoN*`<6jHZ7U06fFb|Y}Xk;DwU!Gr~P`nADvAN zP)1Y&SVtLWpocQV;Gs43TC6(H_R8f>#Rs?-omiQw#+l`uLipRY1>3s)Qn&;VYIJ(e z>lxn!F@{TlRxRc{_hQP`R=L^ga-L*~0glJNMiGN{&WR2L%&fL08SOa$jNzBDP8}d* zx7SW!-lMo+PV&l4=b3CtA!3U;tDZgBFrd8Dw4)iNA%eghylT8Ccap!cw#d zm@2b!0qg^lEE%X!5!D&$8Lq{WjtrkB3al|*W;I{R*u!}PLS)IIMz>1QLHJ2PK=D_X zAt^)S*`MB+_37|r_(fQSxhHwl!!ap^uvze|6+(Cx{2rbS4{gP>zrIfW`aEbq`aDa^ z??2!0{b%C$Pt5v$rr;B`*NM7t#Z<9|=OXtwCtDLG#p)ZXH4?Ed*YpVBB%LjV-868u zuL)ZYkR@hWqLQ6~1Z|5>wR<&Tz5<*J!b})?VLw`eeX%tj!Zf{~Q2uC<-)LZu#OZG- zJO+dsUW$)tcm&asv2Lp}1`|e@R;-7KIR3@@Z*2kEio>uC*2V?`Y{nt@Cm12cR=|kS zMaY}B6{VV-Ok8(S!=FSb2(~u>JQx5NY%7ScQ)~4aRm6mBXsLRB$E$a}dPibJq(%tY z40a{}rhrnj`VFa+Z{`x9DN{alf?11@9k^#mc8jAW6ZN1`9c$FVb&!@EdQ{lY1HYiN zg;TONl9bWHYB1sV8r+FO0a?m_ zq`z0f8{ABE#7irhEy|zr+eKpPV)QVA#d46O#>BSj$uGe?AW33*ixjZ@_L6-U&}FvN@brwKpF2@lCcyL2i5n z%1pVV0;GMtQ zm<;PeQweuY?bV|AVRD#nc>pu+#yN+7r%Y&w1>5AbZYd&jswc5TBYs=SQRt z(PD5Gvvo8vLsW94z;1%`O=G?>UuxNc8j|ne@SY?6TD4n zrjcw}%U<_0QOJmU-C)5=ulq54)vDKF{f)iuC%g``)a#Cz=Q4Vzz3wnhX_x`i)RF2@ zyw{xqAB=n5shDEDj-`g^b+Xyyim#><^;vtO4U(_1Z4Kl!;)~_Jx>aHcOe1lVLC#wH z3Ruf*_o_j)Jl<+ogEkq;fqdC9wm3ByEV+m0A_eW(5YCdQyro+8==)y${SIP5@ZkYW zY*t%4!86wMcEaCsuZAO)42 zK?BKk*i&=cRl5>P{h|nIEEixn0!E51!G<@WbP^gTfx1|2v;utMm7uYsOH0*@_Qsv~8rf`T7!eHJ=Ml~ArG{85{Ve6Cy#rn|L%crOY{^+oXx zZpQhm%T=}#isg8lS#cRIC}5XdP*ueR_1WAuvVDyGgfXVEi)2Y zl$cgWW$W(5x`Lh8=`Vr*@CWe7@;V7M1ec(-0_g8fm21t-5*3A|D;xxqVaqPyN}wNLWu z6RZi3Fp70>aO#pIx$J z#|bBIICbiT!Iiv|krIq___qo{NV(9L7sQl``98ymL%xJ}Di9eaFz91cWxc^nLaTUK ze*;9~t9a@Mj^GtB@I?!G)b<4NrQOL{$RkUjC(2#Oi+!IJU^1SJRWZdTV=Ps0GDbLl z7@V`2Y=aBV!S$O39HH?Uh`QNym~?3QIioQc;NLA|u07 z=CZT#)SCrgL*OYr0|`7ew_GP7V^T`@-3A7%P?Vm5(V$gx+1b*)-%vR#RHkPjA>Bm@ zHAjdjGNh!xU|?q7l(ZZMO3WQq5MWEsKmrb=woGvsRw`H8`d1m)vH}Kr zwp0i2s^uSXQP9AUI|QYN#`g+2=91B>E{R>hgChH=J`3NB2co~g z6dQ`d6e&BKqBCtfV&0A_Yj=UVRSG4V z^bmwUKtVz_U_A9rDd`{PO4@R``kp9c^uv|5Y-#<%Z^E~&HhG{ZvNm}Lw!t_5ZC)9Z z0n_ZE;*!?n>Ebd>A$&xNiD5xY6oCfQ3$Zd^a3b=)rj=-hhKY$o4zgsr_)&P(1+du||7q7}=b%)vqa=8;{v=8JmCS|cq zpV|kaZbNb2(80CBnNAAZcdim{1bK0?N-_??b7R?$F{Rz)ZSkgCoq89-bbv3V8%!#z zg?#Z476KJbn+zb{jo+0~B}P`BtZ{1uHI^nqGyAUL))#DagHwRL$8}O}eG&6by)J9_ zzIc~zzvcxOUOBdP`!(CHCQ~tdL9xuBGJBvhg}23Ait{dUF&X=lvGvF3@LF|m3* z1v_Ito!d;7Xze~xNJv^UvXvZj+1bv8uL{0~a4zT>NH`ZPcE)_$z>1YaLC;FUp&&QH z@UAH{WZ(P`12a}m1T8btz?MSP>g?r)bQj@$!Onm102Cd57ap1Z1JXmVE1%%C)xvLe zYs{YvY>i&q_KjxIDVt>s3$-LCb#S6g(W_mewvlyj`7jR-|;#pc;NX?S*(vK zHj8DcqO({IDW7`W|dK&&!|!;k)2rgL`_swnp6Z z&H>zmTZ3W$FJlcoN$pk_X7_Aw1xG=+XSW(mwu7Lv!MmKC1+jAg&lXkd6{PSzIBV40 z>9?zK8MwgdfkGH(3IiGesez2Quce zvw_SNg0CTfjGlo6kb%9SyfL|qWrnopFE%h^1!eTiB%sXVq#}TQRB|Lc4Ffw?U`ET1 zv^*uI+u7Ua(>;ZxXoqGtLk+?m@UTHMr}63<(afV;nmouXMAu0jb>bZ@>ClOTFOT~W zhWR3htb>bWTc#mOIs|6jM}0lN$yJmJeoL-`8}QTbN_Ckf{Pg=S>=Ayt8;P><(?awJ zY0gZ&AISy~6y<`2mtt}_5^(cQw&3~)Lz6;Vihso0g*P;S&*jIYS(XuP^>;&H<7vj zFI^bK?G{uF2k`?>#a7{F`r%{P>dMKfR2anc_p>U4S6#p~w4oFz4o}%Gut7L(Sv$aL zGl(2~#-x<)Is*e%fKAVU3fPLD`Zt%IE!{H=l^d0Gm!#Ak1{*a?O8a~RL;I$*Rji9< z$6*J+Og}r~WZFbYlVJyqe+8_B9!NC203J5@_$S;781eDh+VfPLVTkL7=kUp#BNirO zC!BD_3y{hZc(df9MWowdFYcmkYX6s8mpP7H!^iLYUJ#`{9Gw?8C!5#ur2|Qwns3cWcXKSv`Pu z(>oF0iIVmBPEru=0DPxpN;CH;S8!6kLip}sQOM}=ow@961oC6S*AUJ*Jp&1RHxF8c z1kKV?zE2uhu)-XA7Dj{c%w=cG_s}IHz|VRH67mH&mr(c^;fX9M?PCoL?VHk;qeO{W zp6m;!20$C=odd)Z60?JNUkBX{=YUAVXTZY-;(eKGyAk4T(?UEv8BZ`z9+{`D+f@(v z_k4Ju;}d}&{*4hL1@Ienu~M@x%+)Ld96X;B&mJ6nkqdhS2Va0h1>j&E=?35+IPB3K>1}Gnbu>Odb+^4T1dh3?z_AW`v}FGB99;MDz@d2KSlE&X(>^ z4VAO;x;{Yt+Ms+&hg| z#K0H9J!*FvQDq;`fqT@0^h6eL?K3f?QYMvavyL;T@3Y`qgjI%7Uq*yXhYkKY8lX;~>)m_i)!c&X$_ z+x8Z&)ueHSfZyGskkJD_bJ^L@({j`AvD?p-WVKmUs zTz0m6ziOzQ74*|HkdQCvM}z<2*;$|)-?JI+x5v>mr)4{_}1bv?nFfiWgc3V?O)d(iK0(I`! zb&$Pg{?fdOlL6z-<;1gxai8YG9%0-yNK^phu1C57j7zy1jJv^!JC1Qr1R?{LOk>;= z%p`3tLdSEifxHn*mVO*Blix{_DeJlT!mx)JpA-!?`VmW8wlsj@FW}o&F+))lnK46^5GcRo zl`)wxO=M86)S6$Uz>m!pc&dM=QS;H9*aT|%ZR}K)q0GXw;G3~o*n}x&7FcRXvrs77 zO58~cxi1qD|DtC(b<+eb!YFqSziO+j63V?m|~rkrH1RQvI%A6SpDW>CBm;M#;j|I-&G2j?M(ZXdUKLI)w-W# zw|R?GD`J@6HzCD77v}eUPW8Yrzi^ zAMa5aTmE2S<0K2n!3!zF8l19RdtSkhie4VBSPl|M_{U;}GUJxR%4~&}YPXpuGD4+@ zwZpkk1=(ar;O8@&%raEU8c|3{8U(|>>Z2)s9@JcRwqNWN!IussSl$AyXCUDhgGFyH zeCowYj+FJe26n9cVS08{Sw~B}q%PnTQ^}GHU20&+$`7VxNWzj5)9~n2moCO3gx%8N zQBaBSIq=Bzf{{*wy;;p`tVN}2+}ryH;=hUeoyUXj&LC)dfnTZdf!jSM%BfF9{M-Gz z5>iitTs=*XD|pMG(&Xc^$!F_itP6XzZa9NPf>A&k$vC+2WzpI&xOAApXA#I;tknQT7=O0xgx+)RfT#yFf|#nvu_jaHYdcxW|_Rlb@1lYxtX=>YtpT!25CTL3O~;*sN@i-E|1 zGt&6yLNf{BAC!PQ{yBwL#K0HfA8LIX#iSX^!9Qdb^h6f;=Vo9s#y|fDQw;yG)P9J6 z;2r=M{FA&1pfLW4}>q=LBZD$_(#t` z8vn#C$wwl{)JL^E(7fD4*Q-UyJr0ngyg z;bG*%i$Q+H;LHf_1h^VMp4n+E9XgkbLPig0%w=Z-ni~aQLjW2*0|`JQuK?h~jm(f% zeV2h5D@dbfCIM-b8vr;rN{(dbRs%a$phnA%v_B=L+g5S0$f?6Sg&nGS0n{P986GyM z<}zMkBdYmL4w=t2;y1a9QpNuuSH)AKX?m2uN2<##;i!+hutzxRBS@5uqq1%V_)8=k z@D5QfAgR=?0H1f_jbo|51|ml+^;t6sVJWP+JC^z&uZV#!@(fX{>tRt!W#}*iSr$E! z1(y05Fd1X1|Hc%vDEoRxA4f2(EaEPhwTjt9YaGyuF%2V01H=gV8x5d-i2*I zY82O6DN-EUv)z_7ySD=zf>j+B#vLpQ89j_Mmz@pcP856%0ps)xBw$?T?Eq&R7_fqF zdInVJR(v;@x$JD|ZZ}lU3JB^MNJv+`3V_29HA@cL*BcnxH>ItjUNk&TGfKE0z~%}S z0?EQ2*}>#Bz)rXcA1{W74OU(T@1Z#{V&#KVQ6xlYhQS|X1HYV?PUB^+mm`hKULskW zC0urw3wwmiUXMiCxGXcG{~sdV05GFm0A}fk{_k_*jw7>o1Cap%rRDriGYKIxth+lh zdo8bsfiFU4)b6A-vcKhcxk!)oL>9>GVPG;wX8(XGhRj%MFCw#|dzPl$yj)X>Jxkd! z4-D98%HLJ4w0cd5!1V)c@j~l%N0z5>-;yZH+YHGuR&2)pCE%X+FHI@?m;RG09VtZ8 z^jNyPek2MRJx(&0ojsB-UKLyItjbx9v`B|TU2I15f8#o99MN}fXWI?o zLd<%z8%#oAcevCW?yhBlpn%2tRBwvz%7n`?`4P7`Ruqf$G#+>&P&^CobaE;bRHX&@ zg%uYxyLAX4KLJ;13gEEUzAyFToLv1#IRVn+<|a-If}SOOa)k?fgip31Q8qr&ufO?7 zGyqO0H@*Hg;lvk5CKVtuAb_-l$IK*zOt9AO$m9}U5d&X@OsK`l>`Eh$gG{JD>WM6n zNgtSuk;xk|#gGY0?L}l#*k{DiEA*ph zK}A2s{YK`pv*r7kp>kFzO3y$-zThMhT}k?lM3x-3pD-}AZ%SK^7A0nTqOya}9B&;Nw^Duz{H$;B8=pnWMfSh-=2Ei5BDOcmPy2yz;4h^>gkpY6Gq2YOE5`upveaILhJ_;n&^1C%N2Q5K1#(5*W^nt^E!gS` zCM>+=i|!v11v(?bS-5}bPOj6WZ-r3c>qH@=M}g+Dvr)?X1z$s;Ks^Hql#+S>(7gr* ztWb%bfze<^a}yZKfX!40!iZ+2FH;cYo}{9^u^| zAyEOmd%&SOyi2(nyt@DiGIwI9gh!`P=K+xcSEljq|3HNdB!qXd?(TT^-?*4fAK|A^ zsohCwq#?_}yJQ{oL>74WbP!yOchA5S!@DfC7x8XUMNx|0;U{udQ0xYHOAL2t)Dpwl)u7NEp zxTI%G1*q<~68)}$F)MJXWlWl=Qiz%#o$269bHA79O87)L0}mVAbTO~B7B~Ixx|is! zTog1&B&VjS5j8zbzFEjImyC|`k=O-PC~_~+$Kadsp!9J}u|bKYh8&b+&~fD!BHpi+ z9NDKo;Uu|H1s*qDd6K(fT)mmd=E@V=Jezwrk?k2h^~NETYwE(2M^K!Q4X96jQ_B0% zTzOlLTMvsuMn7(8%a&#^dg@ zWnL?jJ=0u8#6_<8MN0k&AvE2fYOoRiEqJrC5mXgX!6G(dzi9%i zI@Ap(Tbwwe8&1w;65cm&IJwffMtH-?_C$?xyEwbK1SMdYF0=P|1IZgsPSiJO?!6{X zG_kfpl^Vce;oD5kL3zZtneZw|U?FZV;YL^dEfxJGNS--4OLtlX75J4A-Da|ZL>wD6 z>N6R4m_U^7W3wPVkwSQDb$RDBrw>p>?z^#uiFtD@S@UfrLr3I(XKr&?Vve_oLPF9G z7^u~GTk$={=CZTr%6}&K(hcjDHqC+Aax)375MbR6kcVy^Q9kg5Xvp05ryViW?$j#M)a0xXkPXliS*#Fj1u4YN zmr zQHU@%BSSIfva?aljNoes6r*P#jbh@KB=9~MSNl~4R;*Bro|QC;VXWlF)qaD487mZ{ zWk#Bo64Po66cbC%ZX1LTjEA?t!v@7%%WJ9ie5rS)`%^kr0o$#xKQHh7n}I`wXSCgA7u(a}+@SCGW_;B0Mkr{Au|g}{YE-p*Pb zifsmyeg;j`>rE#}gui5eU{#`(Kg!j!^o%uyR^BU{Z4&ZfWrx=%*7PLDJ-=Yamq#~XUGhM(SEvdwg_*j{+85TAi}I=+<-=r&&m`$dld+) z7-lJzXIdCkC{?7lnKH)WZ)gJy%>!ccY_qhqHfxciVWG^^L?NSxGUl?gq0H%muOXm} zo`D3ESvk-yByG(vQubR6>{-DZJ$ngwvnoSNz=Z04k_>J)FlYsNv<#|{2RlXfRU*{K z(wcAS!Z{iW54Xa@2K=ny^)-Q?YmbH%!!1pI*C7NSYWAkaAxaP;AcQ;AC%w2&!aqqA zG|_HNv7ByentqH|dvM){1sEDcM^hjPfH-L&G}WpG3@+`PZlm9dsvUHLDgs~B3>u<5 zY_^8iYu3A+4T`s=#x;-z=3G}r+JzEG^_?Z~_YxQO2>k6vqHOS&6$Cs&vH|!P064=dV&IDaAhkNFj5Mt|jw-TrdLjz|_!(d_ zc2qrpDFy&pYA*u7)K*p+IWm^p;y5jAjlCb8Xhec67)kuLiU{36Cx&eL5;m`LMC(kl z308}QGP;Z`NF2+uUB;W`KuzD^3QWqCG-8(Sv9F0jMvp1YWoKi`{}Ox+fhqM2Brs)8 zpr!+!HUiA9XFe@%hjfoyCw}iF66`@nppyP*SoMs0PjUe zlnwAQ12Z*{ZUEs?F0Msh-R=bnI=;z?I}Y)hKxBYYX*q{x5`uVGcXx>Q0$vdVUj*@} z-DyCTojV8OQ9sfXSwOr$048II_YO=kh{sZU5#pWU29_wYQdBb9HF{NrW^OB=5PIn& z*scn;JKc?4gqN+hQj9aQn}vW&pW?bodQ=F_eNq%MdNgM)I~#3$MesEQn$t6oKpU9> zm%e3SzzSXH85j+^FqfSz-JcsOXNBeT3?!s0<16vCWSJpH-uXw205$8GnMFxUQ(t1% z#bR>>gjqVlXzsYFu>*0Rfp!ePgO7zEL>mxyFK>Axh}-T2;$R&Zy=XD>9j{Tp5f_Ua z^~qWnpkC0J5EyRc{MiZr;F!62J6ZB@c`AMqO$M{vfB^iad)@K`Y%l4Dug6v`v^9RDN6O#Im5Um_ z5axQ5C}i}Q%UpIgD)^Y-YY5DxXCQ$JQisPmG)U!2v;G+aTUJO+&z6c0+>ew$Xkg3= zMQIt6MySLzKRcoWb)rN720QTZHef&eEIe#*L!Z}GiyM@K%-TN9hmVC&iWyI~vJgx_m)y?PgZh2wYNBASMGajg!DV%NxY ztB|6V{HO4XQYXKk+w=yg@f{({r1?mZ(Vid@y?_Bl4vPL7z8McVPhyGcR2Ed2!`z!8%?UliAXo3g?p6 z{2~Q@p^%ks#7rx5YD?((f;THOKvfya3|tT2jLpCem||vtrG_&DvI*sJ)>5@j6lro)ix>LlM9^ za&cfOdhgY>dM6&D8I?&4LN39sZqV$&*6|K(Nv|$}LVBHGqSt^8R6*0L^``tLG^$_q z$8le|KNY}xuprb7f+}DD_7eIU;*C1>&XQo)bgPZ<0B@Lsd*vFi5gq&yL36U+gzfC4 z6Z;LnvN`v-HfQ*1q)0T_ZFIscUNtV&Zl{cB{+9M+XA{YX|0Tcv7N@V%!T&cQ)mn># z|7WuX9K)Wl$-AfrNN?H)Fo;1Hyyvx=!S3-O;Ju~vyz>z>uJ;n%rg#CejvsKYBZdNa zU!sn=)|(yiN0}HL8SFjY$7Cn~v8ocsb{OoPxj_L6QpeJPYW_8_T{t|zpe9PFD8d2o zF;@I78|JG{4TCT-w$VcIhB;W5x@ANo_Kbbyv;uBBi71br^~6L#R^!gwB`^6&nQ!Iuw5Pt!(H>d?(zeJus2#P zUL#YbD_4V_frM*je%#Ew zU-G}Cj6DMzR<0O58+%{IXBjFtDjBa5`kYjInAYijlG4Axz~H_qeK|KMF~byPPNoN~ zT&#`Jv$Lk(8j1mnV&@Ed5;}f(EC@Kf2p*XpF=bTyDK{0SspTWug|ud{v$4A@Za7BZ z&1Nxtvfy2Ofx1Vk8nod&COE*FjoltQq~Lp%M&LIguUhX+H~igWIPkFOR5jXf1;`pc z14YqpE5Ffcc{Lx7EBLs>{ia^Pu4IP!%Gq9}=C}Py7w0ej^mNcftPNNU<^=GZ?7@%V zf`fAoj0|wK1lGT~6_j0XGPmpLCi;q|R5`I}Md~gLcXwn+iUkw>xR4_LzL%jY{|^)x zz8q6*qR&!AC;A+l4g;%F+rS4qZw9Ezi)cJpNIALal!|CP_ z8R_!VTev2XFCsbhu*5ibi$X?^am;0BW1No)zI4ts%P38H1`-%2wa~<|PAXS+{ZAX% zvKn>uY^j*XefjC{42)Uf6)j`xkd2z39npBOJ0<#!-Pn5%d?I`R9yY`7UA)%XVONcV z&=o6Dwehe64k68gl)4nf&jMCjO*|zCqaX86B$lMQ!sBIHl-fHVmrDCRE+xI8FpO8< zmLi^|-ORsmVUM=L{0xa`OuPgfD#^%7cwDWl39PhuEszcDgrQsj-SdD<*~`2f-_M+C zr9?+JFB}9!hT)xUgi%nzLNf_%gu$8{{6`d5N%_D}L^CFbiF6hC%?s4(q%zV73#=S%u`LUdfR?W($1Yy4l&ftyPYrIP=yjtGV*FgfcrsA)|*f+OlP*2(N>0Tdh^1 zC^FY7mHv7IuZ(tNQx;w{E0SE&nqQ=X|DKSQ4ql~OgHDhIoYvTA8wD05xET+wMYW`eR`4gE^ctn4Q5=0Lt| z!w)#MA+B7$4=Dy$E;n3--}c0}VV6yJX8_A@SGHPH@k*U;rP7s5a{fst&T(aOEjg{@ zwT}T|#j9LczoEigf6<9CTIKpY6RTKkNG-A{Yit|sSGf|4Th4S+)L(b55w2-{Em5P~ zUe4C4Pyz-_!rtQzB-gY~&287*1+5~av0R{nKLdsfuV(!XN++Rl5@3kcD{h6w-?B*- ztaAkyC^lsobr`oxDmGH8Bk7?7SINCEh|OHs8X@W2f&EEz-+ski zqLO<}cG60`nX4#GRPxa$ZlhK7`;Ah+XUSXn$1d!VxAOf+Bp3y#ob*;^#$LD|=?2`D zlndrI9ed%kPTcW>d!Gg(8-JxD=ljegkF1p zf3YY;n8J}keRJ8_Q2!Z%uOXnmo`D1y%?#Ucih%(uz^P|oG*I7McD8h%XQ-SN)YmhR zknTZgorhs3ktenJ8UsuFro81?QDWx89^gX^hf{1#rL-G%*nS1bGCU0*FNB8;wqL-d zZ^HIbPm4|w?B-&6Q3Jx=urD7FaSI6BDqY?z>HkjBY?RFi3$MBdysAbU{bCIV7}9dI}R}44nzhZ$JUq>{Pz|!2?0#3yF0+V zl~=^T7XeIacTyT@G;#nY^+-LD1;G4!U@``nU&0gvm@KtF0!%!ezO!BLf*08ZU`jF- zV5Uy*rraqRp5zt;cKs%{yW&bNhA<^lvOs5q8GDgMQGhO6I}u`voNS1hd}(KppqG!Itw4~TfdmMe2Ten0o~5OHR~lHb0zG;b zMguaMmb8OXNv;pJ8BW-;}o;FG|c}M9;JZj-Yt&8iQ6SlDX`hmP4vVChGu z`oJM!0U$?TuvD&VbCpZCFGj&E*KlGG%`9QVh6{Uy4eLl$02{sp=?1VNsj-5ncF@QN7tB5X+QP9v=B>p9qv`jMW<0vmo9n2fREM=-^( zAxrH=Y?un_Wrxbj7}mL;9n~mRO8mMC;R<0vf4m<)fbFbc!D7BszuqpB6;sM|hJ#0z zS=9gm`r`-#6Xjw@OgS4D#P1U}+K6UBTB7&P6=~ zDdY#5!V$?lXc=WE!H*3rSRoNT3!_1P=CZTpyXcq^AZtAX3HidrWkAv6`Ai~PYW1N8 z#`aCA%Q2zE%#J<&1C_I%FDGPX2Lb;cv^e|;J`MxP+Cae1alJP}z$-HyjcD@4N;*0U z704G~!v!^w*pMN`?(S(BCTBK^mO6HJu8tXC;2E5F_F&+pF6S zt_BABPTX-A_+lV3z^yb4{2en1!9c9LI}E&tSH!>=D}oq^yHG&_(O^My+1b+l7enQ&ynuQJ64C{apX@*! zb0_koynkw7Y2TE$91=>*;MgxU`wmV(DMLF1_+gM`_+@||9AqD}=Nld`sr-b!m8)jNS5_LZC8nZ@??CsS)EjL$Z+uZn>Rn9BD%#BzBu9 zWb{bPTy{2Ac$eU72qdOwAb}N9AzCSfGtn`hoz!E%!Q*j4hB&2Wg*$5O-Yf_WdhU?0x%Rgng1AkGaj0Lgef*OvDA=5 zlRQ(agy`ViT*;A=`%fpyJtoe>i-X&Rw%x};JBl2uRU>wsY1=h(!*$pmUp0j5SpD=E z3j*p>-;|O*6kiy2*ZN9P$mjS}2;WA7yqrg(b83oydG9rZboQo2x!w@>c zHBiUFJK6Q}9gJ4o#^Cbg4;uVIw%_$m?T4W{UW62bp*l8islwpKuSM>#_~@{Z0w5Q! zBxUy_^LQOB(u6k&hZ^D3qQ@8&^XTCUk+lk)YK37u))9t}!*~peGLEW%l}}tR@Q!V* zE}q@=@qPt3un8wOYpp7r+nj<8LU?n)Zcl71lG4G`nkbh}93>SuxW5qAojMzqu-giF zA%3?TOija$3>expXa*oF*wzj-5G_?H3&W?vf!7XhRf0FC0)E#+QndR%qq6ySyEb3A z3n>y!l!|rYaG}6!oW4$>R&GP8%nJq7&pXFV;da=WP73s`&Q-!#D{oF#N#4kCE>o>d z-WIRfn;K_lEaI>{C$n?Nr+B4txB?5#U*O&76L9bujxPr{_523v=PB#SE)83Ztl#@b zQNNVNDA94whO^@Ae0DYH)Z1{#gwci!L#qv}<6XJs>WjCN+6+-bEKLy0qriUQ zC_973M$QOCR2|-F#ow|a{}r1g6Qiaf6V3+WA$PdhKuLSISbChxIGzB$vCLh;=^|2r zjZ-_<(r;&cFcF?LJn$JHv4nRlRx5KjoRNCRRv;Uh4QF{?;UH0n7_)eJ!!;$C%5_2MjT^-C~|zEkYnzE zOwKS8yC|fHGwde#W<2k0V~WjtS*qx~myhgn=u=!@dCssIC&`U!_=`us)Yh4F|IrUd zsyFPcEN@u4sQl=)w!@d|Q%X6^JbTUhTx%uQ}ERbjWYP zx2-xPO2MW>eur0PmOA8;0kjG+*bx4*Pu0zTu zl&(&F|56;(Ca0*Yhx*WgUf2fb5Y6i|ewCf)6sNXCU-bs0*vEa<=Q-61ebrCT_f^BK zv?$cr8;TN0IIRD4#188%;Niv(`prpvUUF^_$Uy zrjQ6<_L3e%Mx11xwi&-&Z}spp;^|&jL@Z*y(!@G_)GG-k?Csrr@;cjb;b zeVts}*CW-w>e`-mt`fSor;=6Lhh5t*8%6z68ndstw(oGRBf7SuL>nfNRC-{)mAAQ# z%No_)<~?p&rE6QvF7>W$W|uAe+rt(U8yl$bhoK^co!odpK)qZ zoaM)3^+=rDsZ%~$)S;h7l>J&xBzbK?NTMFkc|MKKdUzFULB_?*G!m9;L4C5;?T24O zF(y3UvDTUACneyE9nj%R^1MiIGks$${>HfsekG?c5gaFmO2u;+mX;0s-Q0$?oWXok z6e5PVk+~GiWoJ9Ve<}FVP2Vk@;CcoUPVkj*oFv&UByG(vQud3E2W=R30YcAS!Wq6Q zLrY-WmF_3W;2HyiR!(s(gL3{-Vx1y7$J!HzP;)@scHZ&tgFb{ypi-IMam7r2gDa1A zCaXp;e2EIwD`8cxR?!|m`bqXaTiOxFb?}*x~-N6(}BsrqYB0~JBbw+ zzsA1T^>0LGUwl zL@c}e#@z0n#$dPzqI8#&I5BjWS&B)t)rCDert};n5{v>690-Vh!l_f5`x~!9Iv6p- zzg4`1A?4yRC8Sf%WnSyV9Y3aY4Gy(>ux~46cAncz&X4k2EOQ+ z616+|Wu#@#Ii^ImRZnDbOzBo&GIp!ohAHM&W2vHUHIDuZ`MLRCj3HoZ#~r2ui3(FM zB9mSKrgmVU5D@iE*!+bcs#oqXh^iFlZN@+Hp($2`pedxKIeHgYL{gIEl+Y5IzFia| zjMd1Xsk!WIX!=RP*AUQD&p-m2!Z{_SJxJ22Tq*O<8Q8MgpP^?f0ZEr@Gy{xkI$JXK z6$4{dP*ls9G+3n&l|Rb7)KouTRK;rtL;o*)CHy=*Y+&eHdBu$|v}=Z;{y6MnW^io0 z)dklrI5q&$aiGavxD9xr5?u}1**Nn|StSjq)!yC9}ihTJty9C8r58i)*FF%4o@m`Mo4V*TAg>@P)QCQ(CL z$ov*^YI{-~IVR+QShCD|A`1|E0Z1VRu@_>BfmoK>KS6A*fXZ|kR;r9%zTESjDs|nb9c&^@nNzQ&j zGJB_iSt}^4WmcNK66-k8RyVJ#>=SAqv;)QCP^<7(c-VmA7jY37K{3iA%Qq{#tvLDv zCob#YMpZqP9^8@+_dR-zdNb&3@Gi!nk>C*JC#4{jbX|h;6Wp=QF71c_I6dxnf|I;f z6HZOBi)=Wc7BClFx78l_OJ~6wJQS{qP1d!)6=7kIx?<@+klSffup|wa-Y3<4mZ0fp zT-YOMdOs3nLsPhH@`TfL!1V8tZUC54F7vGdog%!iIB~~e=|e!|2umL{lMpP$y1T>D zPx6Ww_#)pbwYwf+rj&+`7m#h#6IsC0xg~<7^DxC=DNF62uyn>9mI8?iOScUHOW`Ua z2-2AXrK>@%#X#xFDh}cj&-hig!TAO@t-z?B%>)=-lcOTs)xi^&geTQ;}{x7Pq><)FV4K(oPdY;k{Z$hflEJ3`Ny0AwO z?`9;*hIk9n`>0txe=U*?AUw(i<1!D(lws#iC*C-~y90;}Kq@We+sz~d@UZ6Y0BqsMUOva>PVPXu2>U^qPk2@IEt@5!-S zDp%V6IqOG&oAqoZFdHn8$0|35kt$<%GnmtKwq$I%fiWwLre#dps#1uW@49ZTb{#ux z_D}GYa4uBH2Ah4AD~cAIDX~AFvS0&Tg`TqSNgX&LR|isVg!GX43{Gqs(fFZB61xBm zMS>fg3*U?fsPizz1}K&qa)6RY9xQ_!Y;}^{sE$3v!40++9ud_D2bZ^slf5G*yMfhe^7 z(<&B8&N(3->%cx1NqhpLJz3TTJh1Jg*#Qs!6dN?|p9298KEWG%C~Wz0QOM}KrnYRQ zYkmm6ZPhhV3N~HyBfK)R)HVM>$f`is{EFbss%uhJhU%I>f^WuM^KneEuE|ovbxqlX z^1OV`R%a#Zfz|PPUFZYllgkogu~NABft?YBA5MUKvDV+v$M7RdYDd#PqrbNZ2zVGQZ&EY zg8ec5OXfsN=$)VnfA)~w1ES@XUK`i0$9P%WqNS9BtKa=?(V|Y!#Y?qeNo8fVRq1u> z5af2E4cl&lX0;zJcmWh$mG$FWwT1u@9)Z>z1?7A@vMZ(D6BX>k=ipRmhxY8w7H zsNHIHfz@E5zN;S{u(2N<6tge}-@OrDSi=A8wHxr)vTmy~Httt$#9x7x`M`5~cRyM+ z0mVR=(m?s~)zPvJ92f(i>)0+hx-`{)b+o+GZP%yA@XRIrT2k{H;?McfN{A5*QtbNOUWZtbws4{K)_$UWH5d<_67vv>L{+R=YY@4W>bJ;4^SFC&*y|+|51#)dY#u ztE3RM1<`W9*KLi-tY~f>)NNU{H#H55U0fwWuq=a}cWe3$EN}(OVakrJFSDjQL9f~x z+ckv>b#Sn2y44BBR7$2LmG0O~y;JWpm0d9gXYu^;23CY~xsbXFbi1Wc8N6{m-gpLD z!(U@F^-lkWezXSX?C_Bet_il9(85?+6`K5@w!c&SdC39MO6+f-In7B>#72DzY{g{< zpAapd4yMPTmjuvDAw)EAz7%tCgUJ|njp*=Nw>#b0v~eS3cQ#D#hTzrB4XySh^r%De zO~wGcIfjv_!9qZDEQ0*MYKXBstRPjql+H*DP7HCBUD(hYV}Iy$h? zLe*aid%&Ti-PD6#-2p+ZW`D5Zpet52csHd=5^7;N={Dqhqr^7|i z#l!jV=tPS#8!x=Ym)H+`I<;e9uwcK}mWE4V2UYkqeB35duNJ98=E4t0;=>oIcVOz> z`1mnCeuj^G=fUGs_?UMfrMj4UDL%d}Qr{7&tLMWH*Wu%xBK1v7eGeZWUjUE$@G)m0 zrEbF1E_{4iq&6;sKhMO+OGN51O#KWW*Da>h^^|(!Pk{scU-%$qJ&ccMFQL?Ck@_H} z?#0KE2T|%Mk$Nqr?#9P2Me0`~HMJCe=;Gr(k@^Lup2WxVm%(E@K2|J;#~OTGFH#R; z>MQs-Vg;pc$JCwpctoTwJ{bPI93OX!)WVhU=fU{siPVfp{Qy%x!pG^WDD`ekeFz_` zS5xW`k-7y_ufxYrMC!jpDmVmwXyW6`BJ~xKy6{l=;Zl6uDN+w%>S27`y#^j{!^d|- z>gvPb&+G8|U6I1Q z*dcB_4c{eFxVj(W9)NI%NTD}5M4xlGZat;Yr4pjwCBzwAh||1Yv`igSn3Y>rsl&*G zW)du4oP*GT-iyttniIbVBM6K^Q{%0M7^c{(homya+lvz=E~c+CqE(6V*-5HCjOmA_ z%i_NP7zbceY4vcMDIniU3l2T8;R2xT!mT|2E-=rx^sj_L8upjMa1YkL1LIQsL4j`) h*$0ViHnbeXLkz%BHi<*#k}5(lj#hA<(Hr0J{{al|lhptK literal 0 HcmV?d00001 diff --git a/docs/.doctrees/cli/index.doctree b/docs/.doctrees/cli/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..c366daa18dc22cbca21fc91e6a2291ab8d69045b GIT binary patch literal 4022 zcmb_f&5IqVPzc18b3zCqB>5{0z8L%u<&>XPA6?z?4k4tWq4f0h^xo6&{hsve&L949 za3}oSfyo$`%L|euQYF+BuAitlPpP!U7sXqj7QZUa+(46SqjDY7!rg&J%(zH2mBojJ z+xP003v*Ge?-?3fu4J>Eby%16J}l1Iz;!IQg0`ky|LISjjen$KQ+OSy-2Z?s{obva z&x+EIZbq=HE!dG8M2(wl$8{_3rtZGrk`~i^M%<8CtNARqh{{K?!xQ5@?!|%_10lXU zlBDHVKgqN8U`FCgP3K-GcRfoMeyU&x>>(SmM{I|kx+fE+QaaJOlvGcymA-^P($$R8 z^H^!RHG;cl5(_@zGNH>0Z4k!m&+p|kwp(U-our-u57?jBpV?p7U)kT--`PK@>!)Oy z(9E*p`CSk-$pZ0#))zv}iW}EuJW0@aZromFsuA>Mp3bPIN%8!S8-_k(loTuI4$;5X zVS57neTAeEPT+UjZ0QcFB%fb{3^S?=vQ41B-8?xEZVQP106j4ptgFZuiC)WY0U!{t zVMy?E-#9i52|li5TZVR8P(ovQIjuDPlD+L-wVFs%c9B6*4sg*jelh9edz;^rBL`!55 z8YsgQk^zn^ramO^AD75kL}jcJXccad+xhvs=LQAr9&JuWRBNRp25btT8Zba?u`S#| znfaELPOwtA)2*2;6YO7ZzcjjbpkDfDb7E_yJM;knc!nWA0s$3nPY}7t$$}!?3C8zO z>FyQWACyia&;nqCZ9I8RUAH1Bq=P3l8d%ruliaFkEpqobu(p@vX%;njL{@_!Tv{X% z-rzxyglh0dzZPYN=81}ysYlZxU1rMAsJ${kB(~8NH@w8_L6mSqX2J&&sC4Rjb)BH* zMhM2BGRjT`$W&@k&5Q2De_<0twP!#ajJKBHym!H6%@8Dc5pP!^s39!nvta`jtBJb z`jDT$@y-vB&wV|Qx6FIV+Whxw^Qc_n@p?)11*di%_5d49m`w#X8(1HL`|cEg zOrxeUn*bt{d4$}!L$i{WEF;DjOyCdj-WST_eq>UDD*I)Qk~T=xD`8v?BcWnawj6gF zGhB0H+~LY%LzY7dvHCL4u!Voog!WN!0D281T+V@kiWH7LOPGANrN&c_U7<)>iT*8e zSpYKVO9{$%1rHdd7JEF1p>-Kiv|bV6?d3@~czsm8o`6*`FA43&?NE8;-!!gYQVD7o zNW?>e`@3~yiN?h_yl0N!6p&@XwLlFTt*3H#ydf=LIS|9zycu*opQ2?!-t)rp`;2|V zzGf?S#lB)+=5F9;>?(t+{&n%q4O`u?uWoYo*bl$P+vo}xvoG1lx!Y?WVlcZGb3noS zg{?}7uhm+w^uH}B_3%o=p{Fw?8e9a`SGR{tfgWA0Yq$ literal 0 HcmV?d00001 diff --git a/docs/.doctrees/cli/lib.doctree b/docs/.doctrees/cli/lib.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e0873ede1a756ef006599f8ecbdc0a012c361e72 GIT binary patch literal 10803 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/cli/setconfig.doctree b/docs/.doctrees/cli/setconfig.doctree new file mode 100644 index 0000000000000000000000000000000000000000..95783762a40c51cf27e5b0c08c021f532f34e777 GIT binary patch literal 6130 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/environment.pickle b/docs/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..4f4ee96549c7e7c939ea1a841af9c636debffbee GIT binary patch literal 1308893 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

1qr(u185+5 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

st*h6%?Jh{nfQ#&jYR5+rLe3~$T$Kg{ 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 GfBJvNg2NO5 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.boundarycondition.doctree b/docs/.doctrees/honeybee.boundarycondition.doctree new file mode 100644 index 0000000000000000000000000000000000000000..3c9b4c04c05b2d7dfa34495925756a96ff496c2d GIT binary patch literal 69135 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

FI^@1Co) z&uo2McaYq<944iUM?)vJ`csWbcHqMoc`#I9U!Z1q;3KVx&nO3R;L47iOQ$~5V)DqO zqY36YCJt_}8M$ z!47|KLqrG!5N3{?Gd$VZ_}~OAiC~z&cvplVQ=m^lgdo}8J)o`0A0cG{s8i0QkuKH5<8l3sg;;a;yzGbvZ3o6r{+4Zh-Nr7 zD@oOZ&{s?NmpXODYX_l|N?q}4s^m*u!TuiklvNf+@sWT@f2R3UoxE&*AiQPni8d-h z@-w~%KyU1j63UF8yv%JhU*Cy1!YcfqVjUeV;&f7@DYbSehNu$|8q{EEN;^qhud#m3FI*d zyAbvko%eHW{e+QUju4{bZBk`xulCWZOjANi#pj_z##J`GSM<@UOjDxtsG44Qq2{{^ zl!?o((K}7aUjsNXL;Wt@@fj+=8)1ejCw9Ze~?IbIU_gPn#tY!@|?F{?etCtF#w+f8-_ULZZo?S2oVl748AdzKeD z@2qzURR@^$K7$uunpyAl!((x^0IQ!_?<@Sh_}0Z`FN4f_XZ*blG3ymT;>p^ZBGeHZa=f!&Wk*6cS!%h2Y`ZAKkENb3KQsuv)O`6nDti9|+O$HmTwVf7C~- zGJZfx);CA8;s>AXqg5F{P}_40~_QcTjUvq(A#x3nnww^5ca1+nchnU-Y# zr1C~xH+k!FE*NWCX3S~_-8ExyVgaGYn>-cshOMq-WXu)}a9y*7>jCVjvxSp{@B+I7 zf2`Sp78*WB$jIcb=maJ3B5EP?;IF+-Hc(b}DY^sIG2(r<1V|02w0OIEj6Tz|Vk8;l zyi=2NX}{6)!9l2`y!!{JlFz%hl7M_<1txM&=W)+;%e`sb9~y{g(mDE9sFdx7(;Hh6 z!-0BW1*LI!sbz+k3%J+8!S3c=>=T>_-l3?HxRa3e>D~NVAFWF7MvW__75pHRccTel1JqukS*1Hzxx97Ky`1IeA(XVI zgwc_EH0Hu_OOw{`WgDuo0yV=uQlqih&!A97^!$>3M0SBa2i;qap$Btv71?DduA;{Z za;Vau1Kw;O(Q+6rQCY((WgK9^CtK*~iU{I~6D%g;hK(6K)P{V5`dG`b)eXmvcsZ8g zII{muc!4=U@sO6eH8hw=(ZpkyZu(_cAl*^)xeRWa;fp-5DsoH?p5_YNVB6lx=6In||%g zaos_(a=Ggm8sF)0IR*9=F^VhE$PaF64B^;2sTtSQgm^frsp(5>7ubX7%Ca>++_|y& zD9S5iqhN=2jR=jN0f}oxDzdoUsA6m0OrhPNuZ&%+k5XzIM2kHE7JaaTPp|l7*`LL0 z&@lF2N>tPo#2Gf}^fVcl8-8smTR4X`pGHEoVJ$YU1T|ST$#bjM}re zQ1VTY`#CtRkj}emP^k&5<#D#jMLAxq0S4jN>&0e>14pBeCGs^Fe3Q7))bl5jzV${5N8eH7pd7j%K{xC_efMsYzkJVU#n z&+7TDx{Qd%-aeeoj4#!h<(uS=<#a0rXuTZBP0E23#h2by{4b6`_jVP3;M8zzUbd@9 z-Sq1!en)q(A~@zah2GE9t=leKn{0o;A5$=Bv$fQW>*zfWvW)8JIpVdz&O%R?OJ{wg z?i{>P&YOYI{J1YX8+vjlR@Ab& zWiD=@8p2%MqtSPUj1wK;OPabPCR!NETznL*2y^i+o*8}epEW*%+X6!i_82we+JaBx;i$GCTl5y#_tCax22$8@3-Ch} zP!>Qz2Mh3T3D8~^;5@awNb+95@$48eJs!vn3$snit*63jNk2smwf~pwy?^cfJ5)nx z?;mN<9jVUH-U>}P`=W)RwD*=BN_%gmJFdO?-6+~y!!xw@e*R!zk;n+(^mAmltCM_9 zzO09TGT`i`&-Ed+jJiv&)%QV`Xb7r7&|9lN)2ZRef3{YqZu-^gPuCqR@9E$SesHB~ zZQ9QGbb{3I8E=f{xmsg5xSluEVK1a+Ts?m-9*(N#eImKQUWFbkZJ&WD*ZH@in9}(Q zQt15i2oKA2frJ|atMsN;BhBCgoVoQtjLvK<>>kOh`TiScWdzZ-7w%U!sjE7%!YAs zx>V#Ra2xd&|5^iOtH43Rxq7*cb?N+B2|g!*nMUsCRI{2+o4WqLEpafbu}K9mzAGWT zr(!v5#LG~^Z4-CJSM>FCsoA%@b}_N6(M^`rHWX6kwOc1 z2A7}tdl@1{gy=l2)NM16$uNKMt`rfOLVgO4da;KRCrnoyt4%aRDS)v3v)2FVtba{0dj6(ev* z1{FAVm})%j2HMACSebUb2Icwb_H1!BtOFf<`QoN}r50a&mD~*2f=X#L z!xl+=ZI)zl;&$X(tdv69oM^s_A!KZlU11Z+ayR7k&U#`U zpCKs{{Y%yrp19+_g5@1i5r@w&T2#ah3T{`uIs9%8zaLeZzd~@>+oZ~0QS75tnZJTm zh%brsU!+PtZD(2I)A^2Hz6Y8_ zHK-x4t1@qy?+k3;7z8$cp!P9N7(Wh@+=RnG;P7A*yoq`^?aLy&V#G7$w;{c~Ni zJv>n4 z3p;V&JZiMUcDY_WIY$DuEj$UoGA!CPxs;UR;_VfLTe-+?EtV^-V7f|(NGR820i#58|_YMwrELLz%SY))0ec!u`@ zg>W#6=c?#zJPxKYipp`+xnV=H8!|ap)PqwaP;50wLhebnwdQMaaIzRxW}_m>S{T5|yg+UwdF)h!U}bpBiXELQ8KK$3QMDZ)&q1jdW;1}bwBqW1B216^zZba5pH z{e>F12hvk7RcbSk0jU>ukfOlB8K+ofj%2r555!LEv((%!D>dbL1+^UUr1sF-(tqth>LO1 z#H5?c&2|6<$%>(F(MCC(A#I-QNIj)p`us6ko6$eUNTrtf^Y!#l+_PUUdUt2N>j#O~YnStyS+X-5JGSK5-k8k>W35F-(Y0D%y)WZ@tqBz}ODpacm>FgE<)j{}ha5eX#zK#2Ly zeblY4uCDH$wAX8FX?v>f^W1a3d+OeE&pp04^Tq#a?h^m;LrK^5!V9ZTyB$VtmSlXs z9kqHL7N*%#+3}BOk7mn!A$GQss28_b#&@Aa%k_eG%);!$8DFI0sTU-xs{UNUTB#R> zd3ATjopt9voGrTxd?xkMfEBX%o7^a5+fBw+TP|yDwtHQx6SaFNM0HSQ-#K=HXsIdr zsZ7#2+jT%ynz@Jhf}Ib;-OFbc^=o`z;Dsz(>opzTaMCpPn!OaGrcv(o+6j$lt`#^* zf}1>vLl&Rh zisDTq$f2&ZqL`K5KyH#J<-Ayp6Ab6ZvwM0?cNd@W!Zy25;GSfxdlSfaZw9yCihpm% zza{)TPD24VVowZUneXd5UYzkaOZMJnX=?J$z+#!VGMMGguBDmNbKmK%6vpUGHb&j- zNiFKt?)IHDa1a@8SkZa~P40~l7GSUd**Y7s({&5u=Vw0z=y@rIXr+-QnzgoEmbxsq z=!aQAgyn?W7Q`2LEhlBxc_-+hycb%I6?jQX{X+Ds5^&c|w@n32@a(k2#hMt9GgM~8 z;(OdmG}f<>S^exFKaf zD1ze|9|VL1O?7)&C0OLZf#Q8oGp&LUwRYGAU4k4t@i3dxUfic9{-BQjsOdxJBz79v zqSy&5cD#hy>_UrmNf(_u7x&l+3*~H@sHc{ePFQW0I$prqr|xxv1eqahwQmv#Nv^sTX_z^u5 z^0}9zuPV!cXmdD-mic~gZlwziNWJlc)VWY);+^#=hJ_2A;LfD$kVczB?LZ*w?@Z>TZG0 zdZAbu6_nIIQkuFO`C@wd`njNx@DeaaDQoI3SFLyo4T2A;k>m$@<|` zi{-Opisd)!8?P3NYTSrrRxXeAF!ZY#!!z~WOe7N7`%Xl%Jnrg!KvWG=QxCG3WCr^6 z`hivp>(9p&)(iEGR|`uuZiIELcH^RlH=>jo@yqo@O(a@L>)4{LF9;(C)*qftOBy?0 z!r~Q6Z?V?+JU+8(m!nte_(Dok7^ddxd5>)geaR2$N81ToZr>_wl=Wo+7NXRNH&~kS z>utHcHa4Ez2m&h;3VQ9#{RE%I6AU65KRmEQq}`eS3UNFqU2drhta!*F6A(;UST|<8 zK^qsjRL}aif3uR9%5M0K*fe4j&*#^BK_Ip}AgzJzb&HspCYk@HJ)q+gpUz-sqg1&& zI##nGTRtv!mn~Q}#LftVc$gMO_=f9!aw`h4 zWTS}LEiVYHCX?1o)|OBubJ8L#o!ANnHteNQxKSXhVizr}=e65wzc~?~AC`Q62!Fue z>-dcI^2MjD!aAOEim*qSwJCGLV5HnxK?#S5^560-q7=se%CI6q`et&CAIY zGq5rxqw(=cF{-KIV;eJGd>4g62(3sMqMg7ZwFs$-^9iLE2r$5d7q)_4n*kAkkjtdO zxqE;K%? zjUYvxL5L`vTv;)LG(&(vemN|URxx=+b#B#Yd-PG+@={l#1<+ZKEHvd<>QGJOIaZD$ zqez5Jqgs;~GmVCe?zzCne=Ny&EV%r`P`FS|2`(Sky5qHDj+q^0`bNX%#p%N47TS;y zWavOV*C1kdDh{uT9|=0esupdn8EAHIzYN9_=^j+7UJ+1ENurR$LFqTB$IaH#QQ@dSC(=!?w%VKQxY?xpf_(#S%Gyn}cDkkRwQDoIR z=R${@)nD6-u_Fk!u~!H;S-XKXK>pDe^BHanZCyU`@Y&y{MS^3wy^a&E#LQ_s%>eEU zIKjs;H9Bha*DvaW4~3gyv=v%EPG{KFfGQfb6rzerhUX8KFi_7+wM;lC*j}|}q?{6@ zeye%$vMBAC>yCYBLv)8Mdb=p< zzXyN%H$=<+dkblN?g6oC$@lm9yJ6I?l*C=n0JXX2R4L!w`)h?h2R3H^aau2S^b!bO zQ{?$WN|t8Gkj>Vzw{F%~n5lAk)DUYawcN63xrMprkWZCdbZmKZQ@7v)d8{E706#ir7_*k{Dvrd z89dMYAKl4N-XX~w>DY8fedE>V(W-HC9$n{R=HFZ2#YCsevghGnWvx%(7&s`QAKJUj zx9f*e?Hce4V~V0v-*~ksRO3bzL*2|iTHpLcVvxP=Pz+OXHp}WqQ!Rid@HEtxMeaw_x^sAA|_4VCMBo*2F z4yAG#yw2WTKh|n_okS(9P)B~{PuDkIEicu$k=F=+G9|_lrHpj%uP16E=}KBBk#2oi z|9|12r9I55m)QQULF?7f3w)EhkoiBrQa<-0^B2*TaT_bpQ#LsG|AczddCWh8O8(XO z>DxN^KZ2Ahw>1CF$Z%)<>!})b?;oY7MaQWsOlM@PGZNw$E)D^heN?v)${M_*?#HO^Fo2)5Gqw`8OkYvVM?BVMMg~S z`B$cEG&Bx~G1jwV0%-g{@%+2HB;R`eD7f4)6fTrgg3A@<`B$cIG;D64E^ID?=N~J{ zU@Vb3Lq$qCC6VsP^RL{_Xx4vZx~zZwdj5T`B!aOd`pZKlN;xHozNVgkWqL*<<1^Dm z#v9P{@A(o2#)8yyLm@>uB}lyvJ^#w17!AZ{Ck0|{liKs|t7EKUl{*vd)W>vZ`idwz z+O&{+`YF3Y{%$sI-z$l`9zDwQ@876Wol&7+hI#|~zbS6N0Y`3d^~xl;5}tqGA7cWl zsY3XhXsXoDRpt4ot*F|~t-g}<{LAg&)s^a<|NOrq!~F6be*T)Cj?>fM;zeN591 zbEQq*Ik_T7+>1(ABU)|H!a~ROj z(^o^!!0GFIP;UySuhhLfeSL=_Y+ z16LB#EnGI$kqvMk0m>XVoaL3%5a)7;%!+q$@S9&)Oz8fz7bYpb+Lw}|%Z%Vqj)fh0u zp`ImDTL_JGNOHc=%8Y0w*tt8t_Y#{|30xq?6#NC?NAIvQ8}ll3Z~rw3?{*?8!_)t{GcjkuOlF`hv(DQfvcAIVwZJo%o5yEgPNzo9H5k@ z1KMe7K((Z4H@WlVNhBwT1CDd_a5aiIFr%)el7aw~v=M*@;z>oIV%A-G`@3!fKNsWm zR;hVPG0ne2H;>8d5M(!5yy~%ZUGxEkaMDdX0XkbqohD{cJ9V?O^ZXbv*|GDRevAOf1&Dx&G*2q$I&oZ3Ou!X8Jk7E!Vg2dM?Y z%lQT_3l^gEX0MAIRTNQQgvnQG;1bXiwdkT@t{0AwqDXqpQZcVX*bO2_PDYA#znK9t zohEBz25*A`mmwP2C4OxSr8aGb3t@qc0M(>-LEhv1u!`OftOn~+r(NQES$Lje=JR=} zO)!0dM7mZ3-^vVC8G_lI02yzqpVo=+=6pH_@Ley|8f!JvaJ51=LvgK08_ zw2m$(B~eU~mD98~mie6Jn%u6rywYZ>r6_t+kwT}--oMuo5*OuE-Irxr4 zC$E^!%x`$wKvSrwC9=a@HTEU%&yxiz_bZ<> V%z_R2A2>AHq`j4*lZ)Hc{{#0CTHF8t literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.cli.compare.doctree b/docs/.doctrees/honeybee.cli.compare.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d16c3e5aa2b2134ff83087c6372d8efcab1b72d0 GIT binary patch literal 3159 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 XVY2}7SwP!%7Fu)N#lrAmC&Rx19!=e& literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.cli.doctree b/docs/.doctrees/honeybee.cli.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b7c2f6b06d4b16a9faa31bc59bf62bce84430f64 GIT binary patch literal 10973 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.cli.lib.doctree b/docs/.doctrees/honeybee.cli.lib.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e9b9ca288af1e32650e2a15fd2788a1896fafbb2 GIT binary patch literal 2852 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.colorobj.doctree b/docs/.doctrees/honeybee.colorobj.doctree new file mode 100644 index 0000000000000000000000000000000000000000..865cefc0dcdb88e0637f5274f0d3acefdabeaf2a GIT binary patch literal 61480 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.config.doctree b/docs/.doctrees/honeybee.config.doctree new file mode 100644 index 0000000000000000000000000000000000000000..66cb28d984867a9ed79441d1c095eed2aff9b65e GIT binary patch literal 34594 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 GJO2g6L}#P` literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.doctree b/docs/.doctrees/honeybee.doctree new file mode 100644 index 0000000000000000000000000000000000000000..05628509ab9df9f0d3e4a7b7c47ba8b2b2a99043 GIT binary patch literal 4782 zcmcInZEIvn6;3AUPCD<&%mi^JYZh5ItDDY#*blOTE36-cur0d2tS{rG`rhh3mE3#l zTDR^b5rp-_$~2US%w0r8L>3Vd5fOiYupsyg{0D>LPgq!=s=6=TJ(I!t;6R4HPraQw z=Q+YFie2QgP$4hP z0%n9H;z;qdyjPknJ6(%7?^o+ravo|S(`Gq!s7ovN$|LHTjutxRQ$uElWXi9GoF8T^ zJZEEG+PRpz{55`QZFs_rcS~jClGPB0CR$^Fa z+|u4^NkqB5!AcmjJO_y1os=d1*J@N`?Z*(dDL%4u3bUfw*bbGnO?PO6?$Qz+nAcB8 zCj3MdY0A~fg;eJN{MC*_srcL%%*`99uX5btxziiPkk-A^Td(cZfLVX57*<}&y_@!D zvC1*9>J@L*fS$8=r%&L*^gR6fN&LNlzZdcM5-vlZahEvu)9Gax(SZ>?1X(7TEYfHy zSU!%l01wDeD?S~_YV5j$=#E*f-2s;)YDzdq9}Ub#J8nxkee)A$N=*FgE!Nb9CI=)k#W1>XI_yid(`<&onH#j*?*vw1gv9_yyujIi(~ zEM`5QiY%+6G!IV&ZLMWq6SSu=XAR6rWK>wsx%}EU(@@JB^=!P6Q@q&%Z(gstTG8Q) zbKlp~g9h|vXvDzmHL+*0_5pI7*llt6R~L#q_~Q*cv}|SSDwJs?90@Fy+GQc}@Eln^ zw_7M7|`wax`;%N>Ue8Th*gOJYJW+8o* zdAO0pek{k$`mJVf1d@9bZZ()hI;EO5*S^_|WJ+3p*=)0CwpJ@C69=`I&N)*dIj}u0 zCl-0b+R!)*O6lje8{iHi^&k8ZxlXkTwBl(Wm5}CI3_MZ~IM`e1~8acmZ!zN%$DvX5v4dEffDfm5HB* zF$<<6(uiL^F5lPX;EXDp<%|i1;_H3#xx<=IrP=n-af48Ipi5>o@}G!AWr%tEl8TDD-QO zUpL%3{y+b_Shz? zRST-_6Mc~4nN&K6`F-g7=?$|+D1r57$L#V;BnED$i@ZfU5g!&~9Jh7BR0=O*hT<#% z(nH8XZm(qR6DfQa@HCW>)o9Zz^yv7r$2qE;xjQ=;aHXUQh^0}CUIsM4-9nAr_nx2H zrQ>!f&B5Hr+!klAE-oyXEx&JTL%sU$?7-Y&vt#c7?&Sm*#kPE!&6uU*0`CQQ9OcQ} zK#ON?DvqR&0`!9%;+KZD>J3b{D(3Krh-yMm*KDyu%biZUdLeksQ9XgEiH(pl*ZBzWs$ma$DtPirCoQB7}S$O>Fadx@dN7zJWRE7(|Rk zB6RuY&WmO%<5_?#K_{Gs&S4uC88X;zQ^S0Ww9fL^PEG*l&}9v=?n^aBM%}hEodK8` zXr3TE8sS(4e*D5Kufm^OY81|GZ;^KUPu1Had6}i`Iahtb^~jw8K{z3u#5k;{*$`P2 z*%dxc7-^de&MEib$tj^)6o9^3x z2C)p8e_@z|kWgYmgwN+2yzE?v)#qp=C+_v@-VK!u;E@4)MLGfpDqYyKLV@ODZkk9e zcVo$XGTL|QIm#`^gCs%*U%>+6T;q(}A!eNiJYgaZ@J_e7>#W|bUfSSlJo1`0F-ttX zZ{NFS)vF287feJeAdnk6&`gav)Cq6hT^I#s*@hOZ!Mn<;x!IdR{RyTJ~>*H@&U@v*$=EW2mjY*WV-qnW^iXk3U_VI1j@kWZl9`FQpapjE)e+UA+TYeQ8jz$bxf%iZTQu_lNah!qI c8`$x3y?T)&55|^~YmwFOO6qKrQVje51wGqG>i_@% literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.door.doctree b/docs/.doctrees/honeybee.door.doctree new file mode 100644 index 0000000000000000000000000000000000000000..5fa7d2dfb543520d1826127beb64d92f37971926 GIT binary patch literal 161529 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 A6#xJL literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.extensionutil.doctree b/docs/.doctrees/honeybee.extensionutil.doctree new file mode 100644 index 0000000000000000000000000000000000000000..eab0f46cde3f8666fde00bf63ed3b9b01cc519d3 GIT binary patch literal 40635 zcmeG_e~=}`S@&!AcK7b~xPx0rjy)a(!aKO#gDQ-0f#C7uOgLEJjsgsvkJVmOoN{ zU;mh%nb*_%X7=rJXsBXuUUz@p->?4q>+kF7IWzLfm!IFj{-Zm?uI+fIXRTJt^IIg0 z=~&Be_BzCi;-};NABi80>vTM@PKACiXp)$2fEG>LX}1F6#V2AqiOnOY9nK2)ts!Yf zj_)Pl_J}=dZ#@y$?QuF1IZ>OWs_3-sdt`Z@kXdp%B3=lP*j=sTw|dYL0Re8yeNYQv zD>Z*S<`|E5Ex<2|?Ok-dkq~5WrlW$6Il86ocqE?d&0BQBilV@o??pgA(!1Gdg-F}h zX4?uwD1_$`&+71}u~x6Ee#~3VrGPA8n;zX7S&LW|+dJ*O_ICSXd$T=F?>cDv9da<} zc^(N4p7MhwDBwiTH2r|&egV2+Qk3P&Y!CuX`;Knv&D$I3h~u@$=@c_LpY2P42K!Rr z+q>ZZE8zbt;s5h00FD7Jd`)%Hw^ zWTdbJ$+GW*86BAIE+0Z>0M6cG&0i=&(cTAA1SJ^ofr*)(=hAkO;(o#Q7<5kgziSmX+~jv zf35C#Vs<9n$?DAhm=@`8QMa*HjX3e3>07`uHB&;B24w@7AE;@B4oo{lH`RtdR5VyU zsc1W4bU=x=u|$>+)RI~tofCba7TQ*e@q!oZXDUz!%(k=f(R$*vmlo3=p%+S>&hjQv zp2B*i0!zgzP^a5~=9w-SIUJYnKs1=OV!ugd+K->^v=4<{3(fZ!fWUM(Nn+F-2Q-EV zEA`XsIAv$kJmyB9GZu~8MrPc`8DsNYy{H%v7m6ub+(7a5jES#f$XCwPF+`!CpY~7K zKZ(ryDaAbd(FE_^3~#hV9TJfMH7uRzIHT=kQY(xdFijKb~J2CgJHR~mV? z>e^4yT&ZH<^TiCL8@<>{YaepzIpEZ@u+SD-A<5ETf`-2c;(tb3FS&v3{i**1Hq_CpILHdSR0(s;g2&{CR02zEX{dojIeIr$Apn1ukXQ zSjGzXe<+Rn-<80f81;+3qtk0gP6OS(Mlx&QCrr?@sHMNqKcDIO!aW8t&YpD0sV4Zy zG2JO28o|V39;Iy`;fiE9LEF{U2~Tp|#VB?T^w?cmiK2rc?TL z1vMTPmHwTukU9IQWIPmW=nyLM^IVVTEG|C zrtiT9A#F{i8}K8EK{)oK1iZO+yLMRkFSTyqiTCR%dbxy)2 z2Dc{-*cNwK&ag+|A7IoJ9jU!}=INR;@GjP*)fn2WOqCK} z9z12da(h`c*f)dhPB2u8Jqt984{@v?WKG?N;U8%)gtb;Onaj8iC=(1k)E4{zHj1PM zE(q=-@iA#wtCPjq+GPax_KVAx9jILvSS<(E1#;PbAuyMuhRk~>Qb0+6xCu#d^yd-z zK@Ec|1oR{$RVN^Y7*BX4>GYwF$v|76vu?%t9rqg#&=*pYgP!AgEBM*T7N zIIwJmwfYhQCDzJ4mKw89oqy$UE$VgKq;|@Q>{@inuaP#v*j|{}9?(0!^*SUcDr=h< zphPeAE9vaSM9$sI_H!J4!PI2YF2~Zasd@O0Ld2#0H?&X;{@XGP#yE=m9)#F;bQIL* z8v?jD?>^AS#RrDgwPf88dsM9cZdF!~0js|Qz$QmOvEqq<5bE0u zDl3Rvhoy~nA^~@F6X*mFFASx7#k4W(c~Aq8*3Stbe+vMYV;VwnrWIQ{I?BD9m~Nb5 zn+j%3GkjMQqqrNnKL6DKk`*=>4O=N2Y#iPFVdxI%m7b|R-M1g=cPZR=F(AJ6&_mSe zrtUJt(PRWUzjtc+9n0}z_co9Y-3t3F+(g9g?f8=gl+wRFe}>2K&(f`)FCQmm@eIc6 zm*cZ^yQq}EcR>rW9SW01J3U{P$#&Qiju(Z^jL&zEZK}R6?3=KU}w;w5gUY z5R^@^#XX7L@R0IT31VDrt7rgQLF=jT|%02-HC+*Y^u$<)}b9Y$=?CbdloGbQvDWNai~c$P^n` zaVOgsLfFp~wm(A2bWIbT%m%wsYo4GsRicQ!z7(+{$aNh6>7$TXlh!W?a$T%qs~XG| zCV9|elP7mL*D^E)ie1gJrkM?EAHUDN2&9$crkPYBoD+;xT?7(qa>5yU1TsIy%2NCw z!`Dojh$C|;8oQJc$g2nFRqTFo>JGU3y^u9s+14ZxM=|x1-%8z|g|5=VFf%|zAU}yf zCM%O#n_egk$Q)sGKY-l3U<>@Y1E2Qb)6wMVPIx-&-o^gTvA=h-zxS}e_p-mo@Go+3h>^er zI9)j8NT9CEs*%7@*IAtvYU4n%c|jyle@HZIHsu-7p+*a5LE6RZwK-aNRRX)d+bPM* z^o~~(Ez~y?(L!ydS{iOjNGl&LRBUl?#BTD@!V_%lwbGLQh+;BaUqmri0}(}4qIhxK z$cuuA;@tpbS{~C8#iOk4T16C>s-VBP8uTX_7ZXo3&vtD!L=l>WlDR0dT{L@FEU8!uucigg=uAuQUwl^)40Rm5U5` z%2xsyuI7VBc#nXawFVL1A$6;4;P(Y((!({z6>$4|j<_Tsl>bsfS=$Kj`6DJ@F82JAuy*uk0(CBpl2&{bL(W(J4|?~@2*vN9^d z``|33!7@SK1$a|DIcF*tL){ruw(6`)ly_ocXon~#CbHZ7>~YuIFax_1Nn+2Jg#YL} zi}}ZQBU8pE%C@~&M%XOsyd5EU)cFMgJW$km^>XEuDJC3Vb(fM?L+DAd^mnSV6ywLg z3BaapH3mSL&6#$EAQ0-;8B}Hwp|=g;TPeI$&B7l+Wf(%cQBB^KPY4W0zj|GPB9 z5Q;Ob*k93RTv7%{S^nZaq%-{702m5~2fc_=4v%qknQ@W(Gr6@i1Br}_+-d892FbV_ z0)jkhfSa-VT>oAWRCB(U@&>v>vRD~A3A%$|aF+(Z`CDzn#2s4Jg>QJit-v73Af z#$GR-VGdIIeD@X{nY&FY44o>Rf~#q;h2q1qkq-swmmUC_{KRznySVqAeX`fl0vF4fpiq$hLu1<9C!lhJ-}lZf64^Xh1!KUl|hngBzXRJ0o*_t zq`T!i0(YU?IJ^|n(EC+}{6@3JrY<(*dz0yN#jOIl+#qm=>_xKUq<=Z*M}%KEh&M?1 zL5l=6xJ>Vq?KJI7rUmYx>k^AqvX;H5+l$!cAYskHI}6D~2=|MLE-Y4}uC3vh`h>ER zQ#SEx0r^mmgb`eDvk*X92YY2|Hal^IMJ%ljToZ7BmFFT&aGeg^t|x8~NWfSlbrs_O zMbeZe9xbbh?i~oR@95@?Dy;DvBaJdx%6#I(2xN-%m(M5Ojvg_;&L(+3WEm8Y-8|?; z7T&@n-$(Ky2d>_fyHR!VaZLZPicz?JQ`67vR5`gp>MyyHaO(4;A(_uA9D-fjg zDc^VTqA8;;A;Z(0yAjE&E^C^J9={DzkT2%gZ6;Mn?*&GxE(M7-Iq3~O1(_dXWhp+# z@HLZ`k)p9nnS$&L(5r~Z;cOo;BKKpg=}=OTZ$MXRVVD^pQjp(3Ad_KI3+sdU?q)WH z=A48}XT()E*_~pNuY)%tkKqZ26|!|~y`IRefq0=X6ybewd=bPw zIY=UQFb3cl!qG{;beqfBrWK9{0Qz#anI>v6_~$aSgXIf^bAdUle-yxjt-;{fhOrDcs!I$8hhxw8=DRpIP8gPPQoa|k1)NY_+&OkCQjI4rN!9riMw*P4@W4IWZO-m2l1KHOPVANGJ`-(OlE5K5;H?mD|y z%A=?2KJ?VO4yi=lsw(P>KxmJY7Bxa~Q5SD5wWmc={)X~7i~Epqi*GUC#Ju4XdsE!- zmD-ycN0+BXWFS_5@FRc7UYr(@QFT4gAg4uM0Lk#vBEO7J?6e4bdW%kr+#vn$>`N&F zeaofjraoPlRnLliOxIbR6>8tSl+Dle^CGVrr?>gM$ZsXE>-%zyGL z*VR@ktM?}fY2^=#D7Lt-V>kK3A{{pNdT9-F8qz05#*^W>KcP~#`5JhCSG85V`KFOK z1qVpp03g%OF@1pK>#Xfs9U%E$74-jgHR$J$g5+Pdl)A`mh4k|BP)Y!k?HD6ui3%1(&Uc0{sCIrThAN;{lTQRUzWgYKSO29ir$cY_ie; zlKZPrb8I!#XitbJO0?Cc10-G*3f$5Z6nl032S~I_!8#lu`7)TR!UH4DCaOh@$iH2NNAkqLD+pvt%#}Yeu%B_G z@*Btrv|Jgre$`h?5i2sxe+EGM^8r|sPHL8T133>`Z1Utb`pXOr^EO%}j$da@GueQ* zLHhqcbKEqODunYrMyf9Tk2N{r3_bmyA7f=H{u{&BOj<^Y#x7<0|BnXfRfJe@>JAuU zd6_jGO8WoWiL5Zp3=rx6Sp+g!85Jyiu-Eqnayr#2Ev@biWIP6UY=A=m#hHEfv793V zJi@`C>k#PGb}_wb431=-VE zlovdd9MH+eiUvvy7QIET?XzlT@UXVGIxp2`c@hBb@vq4}ygRp<_B7_a-nImGeP38g z_>vZNe`0S>K|AptxV~1omirRw%BS`eXWVJ*CZF27iVr@B)R|wH&dZ78(g@3aMimP0 ztAejftC3P(+;v9U3Q}{|0FcRDPN(J$u(oTJn!B?K`tM&2`uenw;=I1zm=xtJ zL=-O~{b>lT+O9(yq6SnIrXdtkeQAhMfE!jC0&(DJh^O!gf66q(g<4aQ%0tLG4!*}2 zzzvj#NZvO+&f+CQOGFI4Uu6-W5wuCK!5II-SjM@sEPz~MC6~2LMf_?RCdpL9O9*5N z5|&RzT&)a0e}$1{CE$e;u5ZZ;jSjr`!q=GW2d~l#hu9aSiC+Kd zlZ$vyt506(kXNYWVT)~_bl-oU;bBx{c_Zp;tZ63h^ESvwd^g8VGpRy4-(jTc@)1~* zlg`ld5&1Dzmg2V=zGl)yK7vcp*rm)z{O$m~ime^a-vPIFpJPpjl8?A@dsY}`28evb z+>KNXn3u2=#L>b&4Lz_x9$Qr)y$rm+4N;_v_0r02ZXZ?hgTk z$%n;|uaGG+s+3I4N+rJHE!QErhMIxIF<$9Z=z#{=u3JD1->%Q&6Wgw{r`2uO74~)e zMmn9m{+_&8(Tkk+47_RCYZLgsxcE-FYB-x|h_9exL(9GrK83sg1b(&Mh6u2|nVTH@ z0Boc-nZ!p&L%6fINn-l|y&wuKFKn~7^c&z_Ee0eE<45B<9f|zNYR5-6&n2+(ajA ztDXEDp}WXw2e=3qCGOjdjh@(l6B*f40;I5Dc z@tS@MKlx6_d(pzo^)sOZ&lhJa8zczev&gpPwb~>A2_UM?D5g6(=Tp6muwG(1ovX=p z;XVuVgii8)6%G>m;%r3@n4X6;fbNAhu&50*#dJs8@)mp6A_0!K;P)ot#q|7uG~xD? zMvHVob6^Gjz-=)w17kV{=FrP z9TF|DF~A@kw4+WN1{;s8d6-45$c~SW(P_}hP9vF|2?33;iyCs4o)<2|ts-e z;IL#faw6bAHv?xud;F&3Er1RPyRaJ#McA9qHFG+syKUd%lW_|(NuV;FdD4OzybKuF zghVjLo+h+fYLJfQv>R5dg?5)=y$gFriHD@Uz-`)Dx|w(<Xo4sPv#}@Nm#BgD9&BgR@1bRc#kJ|T+gu}I_1t=^D1REX>hbs(*nzGU sfJFg?3PJVxfQbps6mLt4nf7jTyk@)C!r8KjiaXIlD=!Qpm&5G;0?J?v`~Uy| literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.face.doctree b/docs/.doctrees/honeybee.face.doctree new file mode 100644 index 0000000000000000000000000000000000000000..baadadce2943e202127b54529fd9d488baec9881 GIT binary patch literal 320655 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%0As6L_#82GXco7b*0I%K~@ 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 hM+os@`mr!T4wKs%Nb8S2WWmCAMW{{w~nt5^U4 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.facetype.doctree b/docs/.doctrees/honeybee.facetype.doctree new file mode 100644 index 0000000000000000000000000000000000000000..92ddedb13159b1451c222e5efdcd3480dd1b1e2c GIT binary patch literal 26494 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.logutil.doctree b/docs/.doctrees/honeybee.logutil.doctree new file mode 100644 index 0000000000000000000000000000000000000000..fab9f56e8daeab2ef6011451f58fa1189bc97ad1 GIT binary patch literal 8660 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.model.doctree b/docs/.doctrees/honeybee.model.doctree new file mode 100644 index 0000000000000000000000000000000000000000..40c1a04f389f752ac815a6d330b36535c868ebb9 GIT binary patch literal 464086 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�L^ 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 QibIq&=yjhRdwsu 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 z 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.search.doctree b/docs/.doctrees/honeybee.search.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2c628e9af628f9774343495c48fa890e19c04fb9 GIT binary patch literal 20424 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 Dzq*+7 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.shade.doctree b/docs/.doctrees/honeybee.shade.doctree new file mode 100644 index 0000000000000000000000000000000000000000..0992f3c02e2358ef6817877cbdc070d45c189939 GIT binary patch literal 109303 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.shademesh.doctree b/docs/.doctrees/honeybee.shademesh.doctree new file mode 100644 index 0000000000000000000000000000000000000000..655f420711adb4914bb0adf42f49553e5f9bc396 GIT binary patch literal 77760 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.units.doctree b/docs/.doctrees/honeybee.units.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4f411df444738a47d9ec4c168c5c22e1095ec41b GIT binary patch literal 12180 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.writer.aperture.doctree b/docs/.doctrees/honeybee.writer.aperture.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2821784be50d5f81dcc4f6e46e99764a5f17add3 GIT binary patch literal 3852 zcmc&%&yO3o74~{9?P`B%*NKe+@g@q2)N3@7a>yZYjI=?Ii^@RJHq9XzQ!|uEXl6Ji zIbQ9-Kyom!26zj5=&k=m|DpaHz4Uv-nbE9TH%%^GK)~>ke0)E?_r15@_WrUnyi@(T zp(%vS*Atc`xk|Y4Za-0Rnep8E@BNeS{40Oq2AW+NRqB{~cLyh8A=5*Udmq7A%y|MG4*7k6Aw<_TYSLK>niK7beEL&Waq_;~a0aPXijJ z4H_oJ^-~H8EYFuCwRpRs;(g>3fEghDY^hlxI*0UcsBr{ez6?p6 zRjS!rBTKITN}P)?kei(*1hD1Tp^QY&{cWZ!A6Yd@_)DHDm|~tD{J}sZq^Wa2+kiUH zlh((_X4IM;;xbw&J<9o2IB8IBW^!=Bmy;0+nIiN;CW{xOs;e1$1_G28w?ZYO7me15 zRTH}Kq>9Fcc<5F?&C-8-`_~_DtKUTWc{kEX;;`b22*t%w%iy1elMu{aV>G~6)LBD}l8frENk>J+PEtKx{-2<^g@9&z-wclQ@ilY=xmn>X&5T5Mis(Hb<6 z`5SjayjVoB%BXQ0D10wSc*-kDbS15bnpTGQ>I-#mo4F&+3#Dz85;6J9yY4`+v|aYx z8DC38(K1__<`7CS;q!8d=T5Ge&JjhN(41wE43LhPlS^cu%n`E)6|9Jzyc?8uG5&09 zB)%Wr-i)}`N=Jg_Ny^ch`ebTsy&HzeceL~>E#94P?QE$Ke|INA>BfNO>Z98mTQ}V) zIRM}pf%v3w$h+f|<;#*SIl`S_eHU|(dq;D0@gz!k0odRf>aR1`k5#^aj|hiM8Z?N$ zJ7J|&(MII%N?`3cDYGJK@rbBa0tqPUoTa32SV=0RQ|dRO!tgRt(K;hEo$_^|43D}u zD~QB4dMS+zcpXNGG;E%dBej)#O`V|Tj^K9I)1KIG$%KKT^!Jkg7IOFc<8>VMIwN98iY>k9Ly z}_uV-FnMG}7w#_Lr1tH{(J2lt2W$Q@DrAYAuc<-f( zaDQYnhAR7WiIO%5)H~HWETdG#tPbsYEHJ&qNPH+ZM7atfZm-G$Pte#MdSl>#H$aby zWxfCgYErmQEMdy|)-jn8c2mVdCDI7I@_=LyR98Wsr7E#7z#(~c7{0}gcx~K(1opasg|EE0d1J(fGy%WH2>uL{L_ZkN z5_$7q$);64V@+FYdKPADgO=xSsG0l|Q~dv7nC(uIr91ATu8PBPEP-7LBw`aJL@v#_ z5b&-foI@Ib(rm8M7Rc4ncejM?>A@|HgXY!h(*0Zd(Im9>sQL%ny6PSDYEWOSN+LEi z##p5(AOauI`SyNO%fCk&U;E#oj4{ZA5b&Ru0dm8GEd$;XAGYEOe1|fR(=s8jF9~-C P36XToXEcVC^U1#eV&~tP literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.writer.doctree b/docs/.doctrees/honeybee.writer.doctree new file mode 100644 index 0000000000000000000000000000000000000000..6af7c4bdc1857a46908c25926b63e63b3d739067 GIT binary patch literal 4762 zcmc&%TWci871nJ=Go#B$+Fd1KSI(H=tW2yKKja~7AOsA~gYZD&IL3sfUDI7NRjcl< zPF1yL1PM3~4y#a*2Ui}JTz-KcL!R;@41O{3TYgEt>gvmAcD2NLumytYQ&p$Vz$#{!CwGjHinsiK0|QR9VxBM3^Tu)%Fwn`tR-U?5XKWGFKv(A+=@=J3_|e zNYd0kwr1aL*F09k^8B`Q#r^; zctK{=x+6HT^-H>Nrrf^qW9zMKX9PBB%MML9sGVS&rd`@THd`@IsU7DNVtPbt$tSsn z&(6n99x3O~b{G?-AjI!hN)rF86XjX+F@cGaPTii|Y-=)eOP2N7eYVRUuuXPi-X1ZL z(2>m3l*-Xu$O{O(qi3Ozbma@?s#;V=Vki}ydF6Z~pRgUDi6)c>mB94g%_oV7@)(vD zF+08?Dx(9_-t?x8*()vp?7Q%qy^0ur5C5;>{~`WghezxOg(qizJ9`5rv|vIPc^640 z@-$k?pHD4YLl{J;C0)*Kxpvz{?7rz&F)3X}_>n=$i=dy5&9_(9ha{s?=aSk#*s;00 zx*7=~U%WCUz^*%UZ}kj9N8=YCl0qaeKBO3lyuRMNFj8ite9?D8~>^N3ElOOLC8 zpR;$_d+dGo0sA$3Oid>ti-=~L+4C)6k7PyZ0I9QBOzgF3Gaf~#v}?0hs;UK@G*2c} z(#W2#nO;#?N~G}>_V!S)O(0!H-(n|4Cbt2EpRT6g^vmR(%_YeYVoO#L@e`a|LIe;* zYXq5|Y9L4|JgrEV(A8_|q(;|E0N#J6K=&XNsfJTE%Ab=rQ2*^$gZkAH)b9Z5Yo^81 zh%TPT`E6Lffm^ec5iY@4zAS${Siy)j$A0B(b%C|V+7g$qKO#n@S!N1m_zGN7DIIx2 z9R&eTxekJ1cJ;{d4C*VL4aD?0vkGEBop(W`WCkR#r2v@2pHWz$<<;Q*f~eK7qMH}2 zG^zOe|DKA!0;7Kc+pJf${^@ekfvA4LP62u*_$mbzSEB`MnJpKc3Q8MVEUEeDvYMB7tbYJAp8_w(=D|xN zeT$6^nN{?)+zu;XZZ^Pd4xF-QreD@`O;NN`Q!O>@MV2+MQX$x<(cFwY;AJ-(omI0@ zL$bGyPtRSmxkPdpDQ*vEJuk60%v~)>s$$~0Qjke8Lpk_)silP`v2Q))o}v@wj=k2+ zewa%)jRp1WwOdL23}!ltY7HjB$az@LkW*QZd}K}gS0v8SGb^N+w#apsYddEBvFXkz z<|?Am@9_~4OmUhd89sKpSg_jwTI3ZxOvX4!jzV4 zn^)ExO`#?Q<18&cHG6KhMcWM)V35Qg$x);qZlIqU;y7jZB5@teo0HK z&|=NW%F2q0C!O`RHM8&aHa1kJAKYA6IcyG`55S&c2vO_?II|a%be7|FfQVxNGaHzU z%pFNFQAYvBDDXb6apU9Iv{8&xxQU4Hr~(9Qn|+dN5i}yR!2!3uC{MDWh9m-82slO# znUdHk>=%-vAYAqvQKo1fiC~d9KpoIUCKN@_ZB7;_33YJE759+s2N73f5<5pqE4Qms zLD}uX8HM5~>JCcx%56b4N19{z3zsO&!>%@I>a;~j`3`2k`ty9<9J+b~a?%-q81sZ{ z`_92bv!BtdA!O&wu9Hj%Yti z9mvmKd-I2g=f0eVE9#x3QUCo)J&Kn&$X-x6P=jE5z?DCp@ex0*d-RBp09xFT}KEr7H3}Zpt8&-3C z^}MZL7VKHw>8h@Y(OjY1+NbC)jP$y}NruW4F4sICOMFKRSoh7CdloRad!!w(E literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.writer.door.doctree b/docs/.doctrees/honeybee.writer.door.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9b6f738314fdaf7485f4158292973dac27d8825d GIT binary patch literal 3780 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 N=M|69_)*O#{{dlbzQzCm literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.writer.model.doctree b/docs/.doctrees/honeybee.writer.model.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2bb9221cc0cc76436bc3e475e9abfdfc0314fa24 GIT binary patch literal 3798 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 literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.writer.shade.doctree b/docs/.doctrees/honeybee.writer.shade.doctree new file mode 100644 index 0000000000000000000000000000000000000000..70e6e6a025e15e0851369d45fb70036a22cec248 GIT binary patch literal 3798 zcmcgv&5j$z7S3d1&v<@3nLr{WGGK%t6M=0OEKrE}(OnMLNSDh67N}G1F1t$8-PKf8 zXFQ8Yu!uB~YDckv_uwh+Tksle_)eF*-L`Jv!h(@3b)Bj@b$-6{oipEde)w^BJ8f-Hv5*+VbK^yetmHU9l}r+$Uq9GCtO2o^w6E zQ2HE#;PNn5ns2ONu4zPTF&SwCmtHx$UQWd|*O7U`7p+K!Ad6Swf_M#4dmXzw*!dTdN+2^pC6b zkBZ9&6bKlc&j)Ju9Q(v8NFdRe;i+P3aOcu>a$buSunp zJvWZz?uX(;e1J@B)o#Ozk3y}8j{9k%EFV}kNcdx(s)B3tVDEDSk&tEyY}y8-d7d<` z-7|w=a0tX;rt~1^7vY#eL7CCsDW8u9C{>EeBbm$|k)F0%>=_79KimqH3?5Y~M^=sK z^!+Lbr{azif6c~UzWwn}TIp8-{Eha9kheoQgi-S?A*HF(y(R-|GzM~y~5<` z!l`(;qRwFe*w9dU43|X9Yra^WTjPS7kXg+qR0n%_Ydbh8-VV(4{B$(rE8cc5TFr8k zGU^jiq19Y-6Uet?m1U_vyXN-lGd#hvr1!R5KQ1*w00RobGoej<)0t~ci(X=au7SR@QB!LqEtVqYs|VJe@=g?C$H z@AiWU5#Bw=fxYFj)G1bnR>cuD2ik=x9U|XL?{3YYCI>&XHm}?vwamQCq6LaR^H;7< z%vVIQ%BT?=D113cc*-kDbRn&X>IQ}PmKT;CYvK+xFO;@XN*v_RuDdO&~Igip&kp6g#Qog<1kp*hPS=^-64Czr@RnImQqs#XyfdDkoLZ1~>LNPOR2 z-;B7{N=Jg_Ny^c4x@2l>y*mn#Z)xdNTF{m@b~aRqpItvFT^Uecy}Q1#ans!-2LL=H z5T6tdd3Ttyd|t9SN4OKLuVb!pFKCY5oJ0vP02@3*jdS9$M z9!nzwUXP+g8a7SIk)@S8b)BH*4&aPIWmH86rH9L7(M+b*RN(H=7alQOSB1%Q(v~3K z`xpR`r?5QRa>rC`fK5IJ3R9U$>;HN4p6eI9Sn)YIb3l?QgY8ro?j>PuVIGXf5F0dk z^r(EK^c>}Mn@&~+;ACWZhV)pZV;Az_8}Gb}c=q)y-cV1HmHIbp^{8A%cs<8FDY>0h zZ-5QP!e%KR>sdBM2_;tevt4%rKxR=>nN35AOhE{F=5CtH+_FU^qfwyhfw#Qw-J*F+FsH0S%GY z|7EP2~Xw7O?uXg26~{)(E(ub9pM)>*YZE|%`FjkhWShp_}|DTIhhkPxlZ=R&C4 zl5h?Q06w#+N*f4QM_=3!Hm7@Q8hiDt)umf&`q3V=^{DsTo4S@e=+Yp)Sd~O+Xo;~( zQ-A|Lpy%!UV=4b034H4Rg#yN$4l2NZQU;g}4>sJlCf;wv73}t99;anOFrO3R_7bA! MC6mzrQcg#|0ghtFHUIzs literal 0 HcmV?d00001 diff --git a/docs/.doctrees/honeybee.writer.shademesh.doctree b/docs/.doctrees/honeybee.writer.shademesh.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9685317741c5b58249ec83ec72bea942c9b696c9 GIT binary patch literal 3870 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 Gs{IeAiGeHt literal 0 HcmV?d00001 diff --git a/docs/.doctrees/modules.doctree b/docs/.doctrees/modules.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b79a68a0b49bb2718e08529953915bc043a6d24d GIT binary patch literal 2771 zcmZ8jTWcIQ6n1Ry)w}CUl2S zXde<{&|B31)SuN)GqdB}H7p(-9i8j<9qI4RzyA$)s=sh(OD@#%oaVXGIkPeJbDjBu zDHlJ-SO3KK@nskodSkUW8H-^D8W|TdH%!HMF-(%W6VjeH=X;iAPH5F0=N;bVy?5~? zAB2t*PO`PF(C1pQ+Zkgq=|E-wPqs|H*LFU{I*x8h;nhWc90sHflkbIY6WwLlmqM|4 z>1Q+ysdGlmyhBzgi#?Is6mc(;)LIDf-BGltzxuf^?-w(gT^Tk{IzIFqU8JqZ5BU>5 z;!pV=KMlW3xh~k$c%_(`-e_|LL7mE3rVZO#AzV8xbnYdy=f)z5uP%1|3<>u$U6k6Z ze61{X#rO_<>&zKcXVr{VHTl=bi9bWhzQOM~elPHQh2N9VYy2Qrl*@=J!^^dTevCAX zgvzAP*<2tZO$&SybE0}@*I7?3*+W=E9fg<%$Q+$ zyx0lDs?Am_c?;bk;By~`=il)k_$hyl0_>xnQ}k*hnQ++Te0F1KSuzvpdVcBr*?k|9 z9kiRZCf3rVtJ-YHnmQ#rL)h7?`&q?N?zlx6e;pnU>?^euBvs0FBa+;VGfv~mm(3EekTdNgc>htSpD zmEOfmes~!M3kEb&r%l8nr@+3WMTy0M(b^$Y^m`e@gJ}#0bqEB0ub?n&mflFL#^?b_ zEJ(WurIQ+X8^g&QW|VepZSzwYC(Z)^WI5NSh@Zm50(K<r>wQ)qUYld>}h9Rf2U3S7TTMAUsQRnSSsS`RmoB0LYO>U@Bs3J5B zqXi@bv@ByOr4*k~s2O1@(>b(a7u7n=e{UOi$_$o5(q%iC@Pb| z!%9-IA+`QqR9fb9O_oJM(-B*i+A^|!vVutF$hEMd#_J);g{3o@5^19Bt#|^?jgX85 zGb+--=(tfMs|gmqNMCSbnW>1$RI-+%-v<~$=u^GCco2>g*#H~001Bljgp0o)y$F+% zl>`*Q98+0Uuu+oCC}K~%2w!sNO8fJ43b8#eZyiSdxi$;X>2cDm0)QrQtU!Al+R=yn z?D_XUqMj2o&$i4b$-Vh+SLVT7n(%tX%(-B0UirW@m~vN0I2$-R1BLQ5sr%s+fGkMM z%r*gH%Y=}-aAa?lqf5fYf=m1W-hHVP?nkzuVA)?Dl(s0;!)jeGiPRabFNbiNaf*1* z_?m2}a#cc{zVanpq<26y^_v-hD*_Us=D-UzxiAK#)d%> zxZ4sDzK{Ivo#oH){|z76FkbIfb$Xl$bUe9-#afamxzek{T$j{(2p+vHW?HuGuT&px z30v*KhQ-0kYjx;k!#+ld3ylt!5!8MP8k>TY6RNy+vw3H|;a=?Aj`>m0GM)Dux u9{@idZ=eyLTNeGU9kz30LwwMRtCk%!PYpn1k-9a^(`aj^K)SsB?EHVBgi~(- literal 0 HcmV?d00001 diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..ebfb3665 --- /dev/null +++ b/docs/README.md @@ -0,0 +1 @@ +# documentation diff --git a/docs/_modules/honeybee/altnumber.html b/docs/_modules/honeybee/altnumber.html new file mode 100644 index 00000000..0562be95 --- /dev/null +++ b/docs/_modules/honeybee/altnumber.html @@ -0,0 +1,1181 @@ + + + + + + + honeybee.altnumber — honeybee documentation + + + + + + + + + + + + + + + + + + + + +

+ +
+
+
+ +
+
+ +

Source code for honeybee.altnumber

+"""Objects used as alternatives to various numerical properties."""
+
+
+class _AltNumber(object):
+    __slots__ = ()
+
+    def __init__(self):
+        pass
+
+    @property
+    def name(self):
+        return self.__class__.__name__
+
+    def to_dict(self):
+        """Get the object as a dictionary."""
+        return {'type': self.name}
+
+    def ToString(self):
+        return self.__repr__()
+
+    def __eq__(self, other):
+        return self.__class__ == other.__class__
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __repr__(self):
+        return self.name
+
+
+
+[docs] +class NoLimit(_AltNumber): + """Object representing no limit to a certain numerical value.""" + __slots__ = () + pass
+ + + +
+[docs] +class Autocalculate(_AltNumber): + """Object representing when a certain numerical value is automatically calculated. + + Typically, this means that the value is determined from other variables. + """ + __slots__ = () + pass
+ + + +no_limit = NoLimit() +autocalculate = Autocalculate() +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/aperture.html b/docs/_modules/honeybee/aperture.html new file mode 100644 index 00000000..d88b3311 --- /dev/null +++ b/docs/_modules/honeybee/aperture.html @@ -0,0 +1,2029 @@ + + + + + + + honeybee.aperture — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.aperture

+# coding: utf-8
+"""Honeybee Aperture."""
+from __future__ import division
+import math
+
+from ladybug_geometry.geometry2d.pointvector import Vector2D
+from ladybug_geometry.geometry3d.pointvector import Point3D
+from ladybug_geometry.geometry3d.face import Face3D
+from ladybug.color import Color
+
+from ._basewithshade import _BaseWithShade
+from .typing import clean_string
+from .properties import ApertureProperties
+from .boundarycondition import boundary_conditions, Outdoors, Surface
+from .shade import Shade
+import honeybee.writer.aperture as writer
+
+
+
+[docs] +class Aperture(_BaseWithShade): + """A single planar Aperture in a Face. + + Args: + identifier: Text string for a unique Aperture ID. Must be < 100 characters and + not contain any spaces or special characters. + geometry: A ladybug-geometry Face3D. + boundary_condition: Boundary condition object (Outdoors, Surface). + Default: Outdoors. + is_operable: Boolean to note whether the Aperture can be opened for + ventilation. (Default: False). + + Properties: + * identifier + * display_name + * boundary_condition + * is_operable + * indoor_shades + * outdoor_shades + * parent + * top_level_parent + * has_parent + * geometry + * vertices + * upper_left_vertices + * triangulated_mesh3d + * normal + * center + * area + * perimeter + * min + * max + * tilt + * altitude + * azimuth + * type_color + * bc_color + * user_data + """ + __slots__ = ('_geometry', '_parent', '_boundary_condition', '_is_operable') + TYPE_COLOR = Color(64, 180, 255, 100) + BC_COLORS = { + 'Outdoors': Color(128, 204, 255, 100), + 'Surface': Color(0, 190, 0, 100) + } + + def __init__(self, identifier, geometry, boundary_condition=None, is_operable=False): + """A single planar aperture in a face.""" + _BaseWithShade.__init__(self, identifier) # process the identifier + + # process the geometry + assert isinstance(geometry, Face3D), \ + 'Expected ladybug_geometry Face3D. Got {}'.format(type(geometry)) + self._geometry = geometry + self._parent = None # _parent will be set when the Aperture is added to a Face + + # process the boundary condition and type + self.boundary_condition = boundary_condition or boundary_conditions.outdoors + self.is_operable = is_operable + + # initialize properties for extensions + self._properties = ApertureProperties(self) + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize an Aperture from a dictionary. + + Args: + data: A dictionary representation of an Aperture object. + """ + try: + # check the type of dictionary + assert data['type'] == 'Aperture', 'Expected Aperture dictionary. ' \ + 'Got {}.'.format(data['type']) + + # serialize the aperture + is_operable = data['is_operable'] if 'is_operable' in data else False + if data['boundary_condition']['type'] == 'Outdoors': + boundary_condition = Outdoors.from_dict(data['boundary_condition']) + elif data['boundary_condition']['type'] == 'Surface': + boundary_condition = Surface.from_dict(data['boundary_condition'], True) + else: + raise ValueError( + 'Boundary condition "{}" is not supported for Apertures.'.format( + data['boundary_condition']['type'])) + aperture = cls(data['identifier'], Face3D.from_dict(data['geometry']), + boundary_condition, is_operable) + if 'display_name' in data and data['display_name'] is not None: + aperture.display_name = data['display_name'] + if 'user_data' in data and data['user_data'] is not None: + aperture.user_data = data['user_data'] + aperture._recover_shades_from_dict(data) + + # assign extension properties + if data['properties']['type'] == 'ApertureProperties': + aperture.properties._load_extension_attr_from_dict(data['properties']) + return aperture + except Exception as e: + cls._from_dict_error_message(data, e)
+ + +
+[docs] + @classmethod + def from_vertices(cls, identifier, vertices, boundary_condition=None, + is_operable=False): + """Create an Aperture from vertices with each vertex as an iterable of 3 floats. + + Args: + identifier: Text string for a unique Aperture ID. Must be < 100 characters + and not contain any spaces or special characters. + vertices: A flattened list of 3 or more vertices as (x, y, z). + boundary_condition: Boundary condition object (eg. Outdoors, Surface). + Default: Outdoors. + is_operable: Boolean to note whether the Aperture can be opened for + natural ventilation. Default: False + """ + geometry = Face3D(tuple(Point3D(*v) for v in vertices)) + return cls(identifier, geometry, boundary_condition, is_operable)
+ + + @property + def boundary_condition(self): + """Get or set the boundary condition of this aperture.""" + return self._boundary_condition + + @boundary_condition.setter + def boundary_condition(self, value): + if not isinstance(value, Outdoors): + if isinstance(value, Surface): + assert len(value.boundary_condition_objects) == 3, 'Surface boundary ' \ + 'condition for Aperture must have 3 boundary_condition_objects.' + else: + raise ValueError('Aperture only supports Outdoor or Surface boundary ' + 'condition. Got {}'.format(type(value))) + self._boundary_condition = value + + @property + def is_operable(self): + """Get or set a boolean for whether the Aperture can be opened for ventilation. + """ + return self._is_operable + + @is_operable.setter + def is_operable(self, value): + try: + self._is_operable = bool(value) + except TypeError: + raise TypeError( + 'Expected boolean for Aperture.is_operable. Got {}.'.format(value)) + + @property + def parent(self): + """Get the parent Face if assigned. None if not assigned.""" + return self._parent + + @property + def top_level_parent(self): + """Get the top-level parent object if assigned. + + This will be a Room if there is a parent Face that has a parent Room and + will be a Face if the parent Face is orphaned. Will be None if no parent + is assigned. + """ + if self.has_parent: + if self._parent.has_parent: + return self._parent._parent + return self._parent + return None + + @property + def has_parent(self): + """Get a boolean noting whether this Aperture has a parent Face.""" + return self._parent is not None + + @property + def geometry(self): + """Get a ladybug_geometry Face3D object representing the aperture.""" + return self._geometry + + @property + def vertices(self): + """Get a list of vertices for the aperture (in counter-clockwise order).""" + return self._geometry.vertices + + @property + def upper_left_vertices(self): + """Get a list of vertices starting from the upper-left corner. + + This property should be used when exporting to EnergyPlus / OpenStudio. + """ + return self._geometry.upper_left_counter_clockwise_vertices + + @property + def triangulated_mesh3d(self): + """Get a ladybug_geometry Mesh3D of the aperture geometry composed of triangles. + + In EnergyPlus / OpenStudio workflows, this property is used to subdivide + the aperture when it has more than 4 vertices. This is necessary since + EnergyPlus cannot accept sub-faces with more than 4 vertices. + """ + return self._geometry.triangulated_mesh3d + + @property + def normal(self): + """Get a ladybug_geometry Vector3D for the direction the aperture is pointing. + """ + return self._geometry.normal + + @property + def center(self): + """Get a ladybug_geometry Point3D for the center of the aperture. + + Note that this is the center of the bounding rectangle around this geometry + and not the area centroid. + """ + return self._geometry.center + + @property + def area(self): + """Get the area of the aperture.""" + return self._geometry.area + + @property + def perimeter(self): + """Get the perimeter of the aperture.""" + return self._geometry.perimeter + + @property + def min(self): + """Get a Point3D for the minimum of the bounding box around the object.""" + return self._min_with_shades(self._geometry) + + @property + def max(self): + """Get a Point3D for the maximum of the bounding box around the object.""" + return self._max_with_shades(self._geometry) + + @property + def tilt(self): + """Get the tilt of the geometry between 0 (up) and 180 (down).""" + return math.degrees(self._geometry.tilt) + + @property + def altitude(self): + """Get the altitude of the geometry between +90 (up) and -90 (down).""" + return math.degrees(self._geometry.altitude) + + @property + def azimuth(self): + """Get the azimuth of the geometry, between 0 and 360. + + Given Y-axis as North, 0 = North, 90 = East, 180 = South, 270 = West + This will be zero if the Face3D is perfectly horizontal. + """ + return math.degrees(self._geometry.azimuth) + + @property + def type_color(self): + """Get a Color to be used in visualizations by type.""" + return self.TYPE_COLOR + + @property + def bc_color(self): + """Get a Color to be used in visualizations by boundary condition.""" + return self.BC_COLORS[self.boundary_condition.name] + +
+[docs] + def horizontal_orientation(self, north_vector=Vector2D(0, 1)): + """Get a number between 0 and 360 for the orientation of the aperture in degrees. + + 0 = North, 90 = East, 180 = South, 270 = West + + Args: + north_vector: A ladybug_geometry Vector2D for the north direction. + Default is the Y-axis (0, 1). + """ + return math.degrees( + north_vector.angle_clockwise(Vector2D(self.normal.x, self.normal.y)))
+ + +
+[docs] + def cardinal_direction(self, north_vector=Vector2D(0, 1)): + """Get text description for the cardinal direction that the aperture is pointing. + + Will be one of the following: ('North', 'NorthEast', 'East', 'SouthEast', + 'South', 'SouthWest', 'West', 'NorthWest'). + + Args: + north_vector: A ladybug_geometry Vector2D for the north direction. + Default is the Y-axis (0, 1). + """ + orient = self.horizontal_orientation(north_vector) + orient_text = ('North', 'NorthEast', 'East', 'SouthEast', 'South', + 'SouthWest', 'West', 'NorthWest') + angles = (22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, 337.5) + for i, ang in enumerate(angles): + if orient < ang: + return orient_text[i] + return orient_text[0]
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier of this object and child objects by inserting a prefix. + + This is particularly useful in workflows where you duplicate and edit + a starting object and then want to combine it with the original object + into one Model (like making a model of repeated rooms) since all objects + within a Model must have unique identifiers. + + Args: + prefix: Text that will be inserted at the start of this object's + (and child objects') identifier and display_name. It is recommended + that this prefix be short to avoid maxing out the 100 allowable + characters for honeybee identifiers. + """ + self._identifier = clean_string('{}_{}'.format(prefix, self.identifier)) + self.display_name = '{}_{}'.format(prefix, self.display_name) + self.properties.add_prefix(prefix) + self._add_prefix_shades(prefix) + if isinstance(self._boundary_condition, Surface): + new_bc_objs = (clean_string('{}_{}'.format(prefix, adj_name)) for adj_name + in self._boundary_condition._boundary_condition_objects) + self._boundary_condition = Surface(new_bc_objs, True)
+ + +
+[docs] + def set_adjacency(self, other_aperture): + """Set this aperture to be adjacent to another. + + Note that this method does not verify whether the other_aperture geometry is + co-planar or compatible with this one so it is recommended that a test + be performed before using this method in order to verify these criteria. + The Face3D.is_centered_adjacent() or the Face3D.is_geometrically_equivalent() + methods are both suitable for this purpose. + + Args: + other_aperture: Another Aperture object to be set adjacent to this one. + """ + assert isinstance(other_aperture, Aperture), \ + 'Expected Aperture. Got {}.'.format(type(other_aperture)) + assert other_aperture.is_operable is self.is_operable, \ + 'Adjacent apertures must have matching is_operable properties.' + self._boundary_condition = boundary_conditions.surface(other_aperture, True) + other_aperture._boundary_condition = boundary_conditions.surface(self, True)
+ + +
+[docs] + def overhang(self, depth, angle=0, indoor=False, tolerance=0.01, base_name=None): + """Add a single overhang for this Aperture. + + Args: + depth: A number for the overhang depth. + angle: A number for the for an angle to rotate the overhang in degrees. + Positive numbers indicate a downward rotation while negative numbers + indicate an upward rotation. Default is 0 for no rotation. + indoor: Boolean for whether the overhang should be generated facing the + opposite direction of the aperture normal (typically meaning + indoor geometry). Default: False. + tolerance: An optional value to return None if the overhang has a length less + than the tolerance. Default: 0.01, suitable for objects in meters. + base_name: Optional base name for the shade objects. If None, the default + is InOverhang or OutOverhang depending on whether indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + if base_name is None: + base_name = 'InOverhang' if indoor else 'OutOverhang' + return self.louvers_by_count(1, depth, angle=angle, indoor=indoor, + tolerance=tolerance, base_name=base_name)
+ + +
+[docs] + def right_fin(self, depth, angle=0, indoor=False, tolerance=0.01, base_name=None): + """Add a single vertical fin on the right side of this Aperture. + + Args: + depth: A number for the fin depth. + angle: A number for the for an angle to rotate the fin in degrees. + Default is 0 for no rotation. + indoor: Boolean for whether the fin should be generated facing the + opposite direction of the aperture normal (typically meaning + indoor geometry). Default: False. + tolerance: An optional value to return None if the fin has a length less + than the tolerance. Default: 0.01, suitable for objects in meters. + base_name: Optional base name for the shade objects. If None, the default + is InRightFin or OutRightFin depending on whether indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + if base_name is None: + base_name = 'InRightFin' if indoor else 'OutRightFin' + return self.louvers_by_count( + 1, depth, angle=angle, contour_vector=Vector2D(1, 0), + indoor=indoor, tolerance=tolerance, base_name=base_name)
+ + +
+[docs] + def left_fin(self, depth, angle=0, indoor=False, tolerance=0.01, base_name=None): + """Add a single vertical fin on the left side of this Aperture. + + Args: + depth: A number for the fin depth. + angle: A number for the for an angle to rotate the fin in degrees. + Default is 0 for no rotation. + indoor: Boolean for whether the fin should be generated facing the + opposite direction of the aperture normal (typically meaning + indoor geometry). Default: False. + tolerance: An optional value to return None if the fin has a length less + than the tolerance. Default: 0.01, suitable for objects in meters. + base_name: Optional base name for the shade objects. If None, the default + is InLeftFin or OutLeftFin depending on whether indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + if base_name is None: + base_name = 'InLeftFin' if indoor else 'OutLeftFin' + return self.louvers_by_count( + 1, depth, angle=angle, contour_vector=Vector2D(1, 0), + flip_start_side=True, indoor=indoor, tolerance=tolerance, + base_name=base_name)
+ + +
+[docs] + def extruded_border(self, depth, indoor=False, base_name=None): + """Add a series of Shade objects to this Aperture that form an extruded border. + + Args: + depth: A number for the extrusion depth. + indoor: Boolean for whether the extrusion should be generated facing the + opposite direction of the aperture normal and added to the Aperture's + indoor_shades instead of outdoor_shades. Default: False. + base_name: Optional base name for the shade objects. If None, the default + is InBorder or OutBorder depending on whether indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + extru_vec = self.normal if indoor is False else self.normal.reverse() + extru_vec = extru_vec * depth + extrusion = [] + shd_count = 0 + if base_name is None: + shd_name_base = '{}_InBorder{}' if indoor else '{}_OutBorder{}' + else: + shd_name_base = '{}_' + str(base_name) + '{}' + for seg in self.geometry.boundary_segments: + shade_geo = Face3D.from_extrusion(seg, extru_vec) + extrusion.append( + Shade(shd_name_base.format(self.identifier, shd_count), shade_geo)) + shd_count += 1 + if self.geometry.has_holes: + for hole in self.geometry.hole_segments: + for seg in hole: + shade_geo = Face3D.from_extrusion(seg, extru_vec) + extrusion.append( + Shade(shd_name_base.format(self.identifier, shd_count), + shade_geo)) + shd_count += 1 + if indoor: + self.add_indoor_shades(extrusion) + else: + self.add_outdoor_shades(extrusion) + return extrusion
+ + +
+[docs] + def louvers_by_count(self, louver_count, depth, offset=0, angle=0, + contour_vector=Vector2D(0, 1), flip_start_side=False, + indoor=False, tolerance=0.01, base_name=None): + """Add a series of louvered Shade objects covering this Aperture. + + Args: + louver_count: A positive integer for the number of louvers to generate. + depth: A number for the depth to extrude the louvers. + offset: A number for the distance to louvers from this aperture. + Default is 0 for no offset. + angle: A number for the for an angle to rotate the louvers in degrees. + Positive numbers indicate a downward rotation while negative numbers + indicate an upward rotation. Default is 0 for no rotation. + contour_vector: A Vector2D for the direction along which contours + are generated. This 2D vector will be interpreted into a 3D vector + within the plane of this Aperture. (0, 1) will usually generate + horizontal contours in 3D space, (1, 0) will generate vertical + contours, and (1, 1) will generate diagonal contours. Default: (0, 1). + flip_start_side: Boolean to note whether the side the louvers start from + should be flipped. Default is False to have louvers on top or right. + Setting to True will start contours on the bottom or left. + indoor: Boolean for whether louvers should be generated facing the + opposite direction of the aperture normal (typically meaning + indoor geometry). Default: False. + tolerance: An optional value to remove any louvers with a length less + than the tolerance. Default: 0.01, suitable for objects in meters. + base_name: Optional base name for the shade objects. If None, the default + is InShd or OutShd depending on whether indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + assert louver_count > 0, 'louver_count must be greater than 0.' + angle = math.radians(angle) + louvers = [] + ap_geo = self.geometry if indoor is False else self.geometry.flip() + shade_faces = ap_geo.contour_fins_by_number( + louver_count, depth, offset, angle, + contour_vector, flip_start_side, tolerance) + if base_name is None: + shd_name_base = '{}_InShd{}' if indoor else '{}_OutShd{}' + else: + shd_name_base = '{}_' + str(base_name) + '{}' + for i, shade_geo in enumerate(shade_faces): + louvers.append(Shade(shd_name_base.format(self.identifier, i), shade_geo)) + if indoor: + self.add_indoor_shades(louvers) + else: + self.add_outdoor_shades(louvers) + return louvers
+ + +
+[docs] + def louvers_by_distance_between( + self, distance, depth, offset=0, angle=0, contour_vector=Vector2D(0, 1), + flip_start_side=False, indoor=False, tolerance=0.01, max_count=None, + base_name=None): + """Add a series of louvered Shade objects covering this Aperture. + + Args: + distance: A number for the approximate distance between each louver. + depth: A number for the depth to extrude the louvers. + offset: A number for the distance to louvers from this aperture. + Default is 0 for no offset. + angle: A number for the for an angle to rotate the louvers in degrees. + Positive numbers indicate a downward rotation while negative numbers + indicate an upward rotation. Default is 0 for no rotation. + contour_vector: A Vector2D for the direction along which contours + are generated. This 2D vector will be interpreted into a 3D vector + within the plane of this Aperture. (0, 1) will usually generate + horizontal contours in 3D space, (1, 0) will generate vertical + contours, and (1, 1) will generate diagonal contours. Default: (0, 1). + flip_start_side: Boolean to note whether the side the louvers start from + should be flipped. Default is False to have contours on top or right. + Setting to True will start contours on the bottom or left. + indoor: Boolean for whether louvers should be generated facing the + opposite direction of the aperture normal (typically meaning + indoor geometry). Default: 0.01, suitable for objects in meters. + tolerance: An optional value to remove any louvers with a length less + than the tolerance. Default is 0, which will include all louvers + no matter how small. + max_count: Optional integer to set the maximum number of louvers that + will be generated. If None, louvers will cover the entire aperture. + base_name: Optional base name for the shade objects. If None, the default + is InShd or OutShd depending on whether indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + # set defaults + angle = math.radians(angle) + ap_geo = self.geometry if indoor is False else self.geometry.flip() + if base_name is None: + shd_name_base = '{}_InShd{}' if indoor else '{}_OutShd{}' + else: + shd_name_base = '{}_' + str(base_name) + '{}' + + # generate shade geometries + shade_faces = ap_geo.contour_fins_by_distance_between( + distance, depth, offset, angle, + contour_vector, flip_start_side, tolerance) + if max_count: + try: + shade_faces = shade_faces[:max_count] + except IndexError: # fewer shades were generated than the max count + pass + + # create the shade objects + louvers = [] + for i, shade_geo in enumerate(shade_faces): + louvers.append(Shade(shd_name_base.format(self.identifier, i), shade_geo)) + if indoor: + self.add_indoor_shades(louvers) + else: + self.add_outdoor_shades(louvers) + return louvers
+ + +
+[docs] + def move(self, moving_vec): + """Move this Aperture along a vector. + + Args: + moving_vec: A ladybug_geometry Vector3D with the direction and distance + to move the face. + """ + self._geometry = self.geometry.move(moving_vec) + self.move_shades(moving_vec) + self.properties.move(moving_vec) + self._reset_parent_geometry()
+ + +
+[docs] + def rotate(self, axis, angle, origin): + """Rotate this Aperture by a certain angle around an axis and origin. + + Args: + axis: A ladybug_geometry Vector3D axis representing the axis of rotation. + angle: An angle for rotation in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate(axis, math.radians(angle), origin) + self.rotate_shades(axis, angle, origin) + self.properties.rotate(axis, angle, origin) + self._reset_parent_geometry()
+ + +
+[docs] + def rotate_xy(self, angle, origin): + """Rotate this Aperture counterclockwise in the world XY plane by an angle. + + Args: + angle: An angle in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate_xy(math.radians(angle), origin) + self.rotate_xy_shades(angle, origin) + self.properties.rotate_xy(angle, origin) + self._reset_parent_geometry()
+ + +
+[docs] + def reflect(self, plane): + """Reflect this Aperture across a plane. + + Args: + plane: A ladybug_geometry Plane across which the object will + be reflected. + """ + self._geometry = self.geometry.reflect(plane.n, plane.o) + self.reflect_shades(plane) + self.properties.reflect(plane) + self._reset_parent_geometry()
+ + +
+[docs] + def scale(self, factor, origin=None): + """Scale this Aperture by a factor from an origin point. + + Args: + factor: A number representing how much the object should be scaled. + origin: A ladybug_geometry Point3D representing the origin from which + to scale. If None, it will be scaled from the World origin (0, 0, 0). + """ + self._geometry = self.geometry.scale(factor, origin) + self.scale_shades(factor, origin) + self.properties.scale(factor, origin) + self._reset_parent_geometry()
+ + +
+[docs] + def remove_colinear_vertices(self, tolerance=0.01): + """Remove all colinear and duplicate vertices from this object's geometry. + + Note that this does not affect any assigned Shades. + + Args: + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered colinear. Default: 0.01, + suitable for objects in meters. + """ + try: + self._geometry = self.geometry.remove_colinear_vertices(tolerance) + except AssertionError as e: # usually a sliver face of some kind + raise ValueError( + 'Aperture "{}" is invalid with dimensions less than the ' + 'tolerance.\n{}'.format(self.full_id, e))
+ + +
+[docs] + def is_geo_equivalent(self, aperture, tolerance=0.01): + """Get a boolean for whether this object is geometrically equivalent to another. + + The total number of vertices and the ordering of these vertices can be + different but the geometries must share the same center point and be + next to one another to within the tolerance. + + Args: + aperture: Another Aperture for which geometric equivalency will be tested. + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered geometrically equivalent. + + Returns: + True if geometrically equivalent. False if not geometrically equivalent. + """ + meta_1 = (self.display_name, self.is_operable, self.boundary_condition) + meta_2 = (aperture.display_name, aperture.is_operable, + aperture.boundary_condition) + if meta_1 != meta_2: + return False + if abs(self.area - aperture.area) > tolerance * self.area: + return False + if not self.geometry.is_centered_adjacent(aperture.geometry, tolerance): + return False + if not self._are_shades_equivalent(aperture, tolerance): + return False + return True
+ + +
+[docs] + def check_planar(self, tolerance=0.01, raise_exception=True, detailed=False): + """Check whether all of the Aperture's vertices lie within the same plane. + + Args: + tolerance: The minimum distance between a given vertex and a the + object's plane at which the vertex is said to lie in the plane. + Default: 0.01, suitable for objects in meters. + raise_exception: Boolean to note whether an ValueError should be + raised if a vertex does not lie within the object's plane. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + try: + self.geometry.check_planar(tolerance, raise_exception=True) + except ValueError as e: + msg = 'Aperture "{}" is not planar.\n{}'.format(self.full_id, e) + full_msg = self._validation_message( + msg, raise_exception, detailed, '000101', + error_type='Non-Planar Geometry') + if detailed: # add the out-of-plane points to helper_geometry + help_pts = [ + p.to_dict() for p in self.geometry.non_planar_vertices(tolerance) + ] + full_msg[0]['helper_geometry'] = help_pts + return full_msg + return [] if detailed else ''
+ + +
+[docs] + def check_self_intersecting(self, tolerance=0.01, raise_exception=True, + detailed=False): + """Check whether the edges of the Aperture intersect one another (like a bowtie). + + Note that objects that have duplicate vertices will not be considered + self-intersecting and are valid in honeybee. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. Default: 0.01, + suitable for objects in meters. + raise_exception: If True, a ValueError will be raised if the object + intersects with itself. Default: True. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + if self.geometry.is_self_intersecting: + msg = 'Aperture "{}" has self-intersecting edges.'.format(self.full_id) + try: # see if it is self-intersecting because of a duplicate vertex + new_geo = self.geometry.remove_duplicate_vertices(tolerance) + if not new_geo.is_self_intersecting: + return [] if detailed else '' # valid with removed dup vertex + except AssertionError: + return [] if detailed else '' # degenerate geometry + full_msg = self._validation_message( + msg, raise_exception, detailed, '000102', + error_type='Self-Intersecting Geometry') + if detailed: # add the self-intersection points to helper_geometry + help_pts = [p.to_dict() for p in self.geometry.self_intersection_points] + full_msg[0]['helper_geometry'] = help_pts + return full_msg + return [] if detailed else ''
+ + +
+[docs] + def display_dict(self): + """Get a list of DisplayFace3D dictionaries for visualizing the object.""" + base = [self._display_face(self.geometry, self.type_color)] + for shd in self.shades: + base.extend(shd.display_dict()) + return base
+ + + @property + def to(self): + """Aperture writer object. + + Use this method to access Writer class to write the aperture in other formats. + + Usage: + + .. code-block:: python + + aperture.to.idf(aperture) -> idf string. + aperture.to.radiance(aperture) -> Radiance string. + """ + return writer + +
+[docs] + def to_dict(self, abridged=False, included_prop=None, include_plane=True): + """Return Aperture as a dictionary. + + Args: + abridged: Boolean to note whether the extension properties of the + object (ie. materials, constructions) should be included in detail + (False) or just referenced by identifier (True). (Default: False). + included_prop: List of properties to filter keys that must be included in + output dictionary. For example ['energy'] will include 'energy' key if + available in properties to_dict. By default all the keys will be + included. To exclude all the keys from extensions use an empty list. + include_plane: Boolean to note wether the plane of the Face3D should be + included in the output. This can preserve the orientation of the + X/Y axes of the plane but is not required and can be removed to + keep the dictionary smaller. (Default: True). + """ + base = {'type': 'Aperture'} + base['identifier'] = self.identifier + base['display_name'] = self.display_name + base['properties'] = self.properties.to_dict(abridged, included_prop) + enforce_upper_left = True if 'energy' in base['properties'] else False + base['geometry'] = self._geometry.to_dict(include_plane, enforce_upper_left) + base['is_operable'] = self.is_operable + if isinstance(self.boundary_condition, Outdoors) and \ + 'energy' in base['properties']: + base['boundary_condition'] = self.boundary_condition.to_dict(full=True) + else: + base['boundary_condition'] = self.boundary_condition.to_dict() + self._add_shades_to_dict(base, abridged, included_prop, include_plane) + if self.user_data is not None: + base['user_data'] = self.user_data + return base
+ + + def _reset_parent_geometry(self): + """Reset parent punched_geometry in the case that the object is transformed.""" + if self.has_parent: + self._parent._punched_geometry = None + + def __copy__(self): + new_ap = Aperture(self.identifier, self.geometry, self.boundary_condition, + self.is_operable) + new_ap._display_name = self._display_name + new_ap._user_data = None if self.user_data is None else self.user_data.copy() + self._duplicate_child_shades(new_ap) + new_ap._properties._duplicate_extension_attr(self._properties) + return new_ap + + def __repr__(self): + return 'Aperture: %s' % self.display_name
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/boundarycondition.html b/docs/_modules/honeybee/boundarycondition.html new file mode 100644 index 00000000..67c744cf --- /dev/null +++ b/docs/_modules/honeybee/boundarycondition.html @@ -0,0 +1,1516 @@ + + + + + + + honeybee.boundarycondition — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.boundarycondition

+"""Boundary Condition for Face, Aperture, Door."""
+import re
+
+from .typing import float_in_range, tuple_with_length
+from .altnumber import autocalculate
+
+
+class _BoundaryCondition(object):
+    """Base boundary condition class."""
+
+    __slots__ = ()
+
+    def __init__(self):
+        """Initialize Boundary condition."""
+
+    @property
+    def name(self):
+        """Get the name of the boundary condition (ie. 'Outdoors', 'Ground')."""
+        return self.__class__.__name__
+
+    @property
+    def view_factor(self):
+        """Get the view factor to the ground."""
+        return 'autocalculate'
+
+    @property
+    def sun_exposure_idf(self):
+        """Get a text string for sun exposure, which is write-able into an IDF."""
+        return 'NoSun'
+
+    @property
+    def wind_exposure_idf(self):
+        """ Get a text string for wind exposure, which is write-able into an IDF."""
+        return 'NoWind'
+
+    def to_dict(self):
+        """Get the boundary condition as a dictionary."""
+        return {'type': self.name}
+
+    def ToString(self):
+        """Overwrite .NET ToString."""
+        return self.__repr__()
+
+    def __repr__(self):
+        return self.name
+
+
+
+[docs] +class Outdoors(_BoundaryCondition): + """Outdoor boundary condition. + + Args: + sun_exposure: A boolean noting whether the boundary is exposed to sun. + Default: True. + wind_exposure: A boolean noting whether the boundary is exposed to wind. + Default: True. + view_factor: A number between 0 and 1 for the view factor to the ground. + This input can also be an Autocalculate object to signify that the view + factor automatically calculated. Default: autocalculate. + """ + + __slots__ = ('_sun_exposure', '_wind_exposure', '_view_factor') + + def __init__(self, sun_exposure=True, wind_exposure=True, + view_factor=autocalculate): + """Initialize Outdoors boundary condition.""" + assert isinstance(sun_exposure, bool), \ + 'Input sun_exposure must be a Boolean. Got {}.'.format(type(sun_exposure)) + self._sun_exposure = sun_exposure + assert isinstance(wind_exposure, bool), \ + 'Input wind_exposure must be a Boolean. Got {}.'.format(type(wind_exposure)) + self._wind_exposure = wind_exposure + if view_factor == autocalculate: + self._view_factor = autocalculate + else: + self._view_factor = float_in_range( + view_factor, 0.0, 1.0, 'view factor to ground') + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize Outdoors BoundaryCondition from a dictionary. + + Args: + data: A dictionary representation of the boundary condition. + """ + assert data['type'] == 'Outdoors', 'Expected dictionary for Outdoors boundary ' \ + 'condition. Got {}.'.format(data['type']) + sun_exposure = True if 'sun_exposure' not in data else data['sun_exposure'] + wind_exposure = True if 'wind_exposure' not in data else data['wind_exposure'] + view_factor = autocalculate if 'view_factor' not in data or \ + data['view_factor'] == autocalculate.to_dict() else data['view_factor'] + return cls(sun_exposure, wind_exposure, view_factor)
+ + + @property + def sun_exposure(self): + """Get a boolean noting whether the boundary is exposed to sun.""" + return self._sun_exposure + + @property + def wind_exposure(self): + """Get a boolean noting whether the boundary is exposed to wind.""" + return self._wind_exposure + + @property + def view_factor(self): + """Get the view factor to the ground as a number or 'autocalculate'.""" + return self._view_factor + + @property + def sun_exposure_idf(self): + """Get a text string for sun exposure, which is write-able into an IDF.""" + return 'NoSun' if not self.sun_exposure else 'SunExposed' + + @property + def wind_exposure_idf(self): + """Get a text string for wind exposure, which is write-able into an IDF.""" + return 'NoWind' if not self.wind_exposure else 'WindExposed' + +
+[docs] + def to_dict(self, full=False): + """Get the boundary condition as a dictionary. + + Args: + full: Set to True to get the full dictionary which includes energy + simulation specific keys such as sun_exposure, wind_exposure and + view_factor. (Default: False). + """ + bc_dict = {'type': self.name} + if full: + bc_dict['sun_exposure'] = self.sun_exposure + bc_dict['wind_exposure'] = self.wind_exposure + bc_dict['view_factor'] = autocalculate.to_dict() if \ + self.view_factor == autocalculate else self.view_factor + return bc_dict
+ + + def __key(self): + """A tuple based on the object properties, useful for hashing.""" + return (self.sun_exposure, self.wind_exposure, self.view_factor) + + def __hash__(self): + return hash(self.__key()) + + def __eq__(self, other): + return isinstance(other, Outdoors) and self.__key() == other.__key()
+ + + +
+[docs] +class Surface(_BoundaryCondition): + """Boundary condition when an object is adjacent to another object.""" + + __slots__ = ('_boundary_condition_objects',) + + def __init__(self, boundary_condition_objects, sub_face=False): + """Initialize Surface boundary condition. + + Args: + boundary_condition_objects: A list of up to 3 object identifiers that are + adjacent to this one. The first object is always immediately + adjacent and is of the same object type (Face, Aperture, Door). When + this boundary condition is applied to a Face, the second object in the + tuple will be the parent Room of the adjacent object. When the boundary + condition is applied to a sub-face (Door or Aperture), the second object + will be the parent Face of the adjacent sub-face and the third object + will be the parent Room of the adjacent sub-face. + sub_face: Boolean to note whether this boundary condition is applied to a + sub-face (an Aperture or a Door) instead of a Face. (Default: False). + """ + if sub_face: + self._boundary_condition_objects = tuple_with_length( + boundary_condition_objects, 3, str, + 'boundary_condition_objects for Apertures or Doors') + else: + self._boundary_condition_objects = tuple_with_length( + boundary_condition_objects, 2, str, + 'boundary_condition_objects for Faces') + +
+[docs] + @classmethod + def from_dict(cls, data, sub_face=False): + """Initialize Surface BoundaryCondition from a dictionary. + + Args: + data: A dictionary representation of the boundary condition. + sub_face: Boolean to note whether this boundary condition is applied to a + sub-face (an Aperture or a Door) instead of a Face. Default: False. + """ + assert data['type'] == 'Surface', 'Expected dictionary for Surface boundary ' \ + 'condition. Got {}.'.format(data['type']) + return cls(data['boundary_condition_objects'], sub_face)
+ + +
+[docs] + @classmethod + def from_other_object(cls, other_object, sub_face=False): + """Initialize Surface boundary condition from an adjacent other object. + + Args: + other_object: Another object (Face, Aperture, Door) of the same type + that this boundary condition is assigned. This other_object will be + set as the adjacent object in this boundary condition. + sub_face: Boolean to note whether this boundary condition is applied to a + sub-face (an Aperture or a Door) instead of a Face. Default: False. + """ + error_msg = 'Surface boundary conditions can only be assigned to objects' \ + ' with parent Rooms.' + bc_objects = [other_object.identifier] + if other_object.has_parent: + bc_objects.append(other_object.parent.identifier) + if sub_face: + if other_object.parent.has_parent: + bc_objects.append(other_object.parent.parent.identifier) + else: + raise AttributeError(error_msg) + else: + raise AttributeError(error_msg) + return cls(bc_objects, sub_face)
+ + + @property + def boundary_condition_objects(self): + """Get a tuple of up to 3 object identifiers that are adjacent to this one. + + The first object is always the one that is immediately adjacent and is of + the same object type (Face, Aperture, Door). + When this boundary condition is applied to a Face, the second object in the + tuple will be the parent Room of the adjacent object. + When the boundary condition is applied to a sub-face (Door or Aperture), + the second object will be the parent Face of the sub-face and the third + object will be the parent Room of the adjacent sub-face. + """ + return self._boundary_condition_objects + + @property + def boundary_condition_object(self): + """Get the identifier of the object adjacent to this one.""" + return self._boundary_condition_objects[0] + +
+[docs] + def to_dict(self): + """Get the boundary condition as a dictionary. + + Args: + full: Set to True to get the full dictionary which includes energy + simulation specific keys such as sun_exposure, wind_exposure and + view_factor. Default: False. + """ + return {'type': self.name, + 'boundary_condition_objects': self.boundary_condition_objects}
+ + + def __key(self): + """A tuple based on the object properties, useful for hashing.""" + return self.boundary_condition_objects + + def __hash__(self): + return hash(self.__key()) + + def __eq__(self, other): + return isinstance(other, Surface) and self.__key() == other.__key()
+ + + +
+[docs] +class Ground(_BoundaryCondition): + """Ground boundary condition. + + Args: + data: A dictionary representation of the boundary condition. + """ + __slots__ = () + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize Ground BoundaryCondition from a dictionary.""" + assert data['type'] == 'Ground', 'Expected dictionary for Ground boundary ' \ + 'condition. Got {}.'.format(data['type']) + return cls()
+ + + def __eq__(self, other): + return isinstance(other, Ground)
+ + + +class _BoundaryConditions(object): + """Boundary conditions.""" + + def __init__(self): + self._outdoors = Outdoors() + self._ground = Ground() + self._bc_name_dict = None + + @property + def outdoors(self): + """Default outdoor boundary condition.""" + return self._outdoors + + @property + def ground(self): + """Default ground boundary condition.""" + return self._ground + + def surface(self, other_object, sub_face=False): + """Get a Surface boundary condition. + + Args: + other_object: The other object that is adjacent to the one that will + bear this Surface boundary condition. + sub_face: Boolean to note whether the boundary condition is for a + sub-face (Aperture or Door) instead of a Face. (Default: False). + """ + return Surface.from_other_object(other_object, sub_face) + + def by_name(self, bc_name): + """Get a boundary condition object instance by its name. + + This method will correct for capitalization as well as the presence of + spaces and underscores. Note that this method only works for boundary + conditions with all of their inputs defaulted. + + Args: + bc_name: A boundary condition name. + """ + if self._bc_name_dict is None: + self._build_bc_name_dict() + try: + return self._bc_name_dict[re.sub(r'[\s_]', '', bc_name.lower())] + except KeyError: + raise ValueError( + '"{}" is not a valid boundary condition name.\nChoose from the ' + 'following: {}'.format(bc_name, list(self._bc_name_dict.keys()))) + + def _build_bc_name_dict(self): + """Build a dictionary that can be used to lookup boundary conditions by name.""" + attr = [atr for atr in dir(self) if not atr.startswith('_')] + clean_attr = [re.sub(r'[\s_]', '', atr.lower()) for atr in attr] + self._bc_name_dict = {} + for atr_name, atr in zip(clean_attr, attr): + try: + full_attr = getattr(self, '_' + atr) + self._bc_name_dict[atr_name] = full_attr + except AttributeError: + pass # callable method that has no static default object + + def __contains__(self, value): + return isinstance(value, _BoundaryCondition) + + +boundary_conditions = _BoundaryConditions() + + +
+[docs] +def get_bc_from_position(positions, ground_depth=0): + """Return a boundary condition based on the relationship to a ground plane. + + Positions that are entirely at or below the ground_depth will get a Ground + boundary condition. If there are any positions above the ground_depth, an + Outdoors boundary condition will be returned. + + args: + positions: A list of ladybug_geometry Point3D objects representing the + vertices of an object. + ground_depth: The Z value above which positions are considered Outdoors + instead of Ground. + + Returns: + Face type instance. + """ + for position in positions: + if position.z > ground_depth: + return boundary_conditions.outdoors + return boundary_conditions.ground
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/checkdup.html b/docs/_modules/honeybee/checkdup.html new file mode 100644 index 00000000..572287d3 --- /dev/null +++ b/docs/_modules/honeybee/checkdup.html @@ -0,0 +1,1310 @@ + + + + + + + honeybee.checkdup — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.checkdup

+# coding=utf-8
+"""Utilities to check whether there are any duplicate values in a list of ids."""
+
+import collections
+
+
+
+[docs] +def check_duplicate_identifiers( + objects_to_check, raise_exception=True, obj_name='', detailed=False, + code='000000', extension='Core', error_type='Duplicate Object Identifier'): + """Check whether there are duplicated identifiers across a list of objects. + + Args: + objects_to_check: A list of honeybee objects across which duplicate + identifiers will be checked. + raise_exception: Boolean to note whether an exception should be raised if + duplicated identifiers are found. (Default: True). + obj_name: An optional name for the object to be included in the error + message. Fro example, 'Room', 'Face', 'Aperture'. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + code: Text for the error code. (Default: 0000). + extension: Text for the name of the Honeybee extension for which duplicate + identifiers are being evaluated. (Default: Core). + error_type: Text for the type of error. This should be directly linked + to the error code and should simply be a human-readable version of + the error code. (Default: Unknown Error). + + Returns: + A message string indicating the duplicated identifiers (if detailed is False) + or a list of dictionaries with information about the duplicated identifiers + (if detailed is True). This string (or list) will be empty if no duplicates + were found. + """ + detailed = False if raise_exception else detailed + obj_id_iter = (obj.identifier for obj in objects_to_check) + dup = [t for t, c in collections.Counter(obj_id_iter).items() if c > 1] + if len(dup) != 0: + if detailed: + # find the object display names + dis_names = [] + for obj_id in dup: + dis_name = None + for obj in objects_to_check: + if obj.identifier == obj_id: + dis_name = obj.display_name + dis_names.append(dis_name) + err_list = [] + for dup_id, dis_name in zip(dup, dis_names): + msg = 'There is a duplicated {} identifier: {}'.format(obj_name, dup_id) + dup_dict = { + 'type': 'ValidationError', + 'code': code, + 'error_type': error_type, + 'extension_type': extension, + 'element_type': obj_name, + 'element_id': [dup_id], + 'message': msg + } + if dis_name is not None: + dup_dict['element_name'] = [dis_name] + err_list.append(dup_dict) + return err_list + msg = 'The following duplicated {} identifiers were found:\n{}'.format( + obj_name, '\n'.join(dup)) + if raise_exception: + raise ValueError(msg) + return msg + return [] if detailed else ''
+ + + +
+[docs] +def check_duplicate_identifiers_parent( + objects_to_check, raise_exception=True, obj_name='', detailed=False, + code='000000', extension='Core', error_type='Duplicate Object Identifier'): + """Check whether there are duplicated identifiers across a list of objects. + + The error message will include the identifiers of top-level parents in order + to make it easier to find the duplicated objects in the model. + + Args: + objects_to_check: A list of honeybee objects across which duplicate + identifiers will be checked. These objects must have the ability to + have parents for this method to run correctly. + raise_exception: Boolean to note whether an exception should be raised if + duplicated identifiers are found. (Default: True). + obj_name: An optional name for the object to be included in the error + message. For example, 'Room', 'Face', 'Aperture'. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + code: Text for the error code. (Default: 0000). + extension: Text for the name of the Honeybee extension for which duplicate + identifiers are being evaluated. (Default: Core). + error_type: Text for the type of error. This should be directly linked + to the error code and should simply be a human-readable version of + the error code. (Default: Unknown Error). + + Returns: + A message string indicating the duplicated identifiers (if detailed is False) + or a list of dictionaries with information about the duplicated identifiers + (if detailed is True). This string (or list) will be empty if no duplicates + were found. + """ + detailed = False if raise_exception else detailed + obj_id_iter = (obj.identifier for obj in objects_to_check) + dup = [t for t, c in collections.Counter(obj_id_iter).items() if c > 1] + if len(dup) != 0: + # find the relevant top-level parents + top_par, dis_names = [], [] + for obj_id in dup: + rel_parents, dis_name = [], None + for obj in objects_to_check: + if obj.identifier == obj_id: + dis_name = obj.display_name + if obj.has_parent: + try: + par_obj = obj.top_level_parent + except AttributeError: + par_obj = obj.parent + rel_parents.append(par_obj) + top_par.append(rel_parents) + dis_names.append(dis_name) + # if a detailed dictionary is requested, then create it + if detailed: + err_list = [] + for dup_id, dis_name, rel_par in zip(dup, dis_names, top_par): + dup_dict = { + 'type': 'ValidationError', + 'code': code, + 'error_type': error_type, + 'extension_type': extension, + 'element_type': obj_name, + 'element_id': [dup_id] + } + if dis_name is not None: + dup_dict['element_name'] = [dis_name] + msg = 'There is a duplicated {} identifier: {}'.format(obj_name, dup_id) + if len(rel_par) != 0: + dup_dict['top_parents'] = [] + msg += '\n Relevant Top-Level Parents:\n' + for par_o in rel_par: + par_dict = { + 'parent_type': par_o.__class__.__name__, + 'id': par_o.identifier, + 'name': par_o.display_name + } + dup_dict['top_parents'].append(par_dict) + msg += ' {} "{}"\n'.format( + par_o.__class__.__name__, par_o.full_id) + dup_dict['message'] = msg + err_list.append(dup_dict) + return err_list + # if just an error message is requested, then build it from the information + msg = 'The following duplicated {} identifiers were found:\n'.format(obj_name) + for obj_id, rel_par in zip(dup, top_par): + obj_msg = obj_id + '\n' + if len(rel_par) != 0: + obj_msg += ' Relevant Top-Level Parents:\n' + for par_o in rel_par: + obj_msg += ' {} "{}"\n'.format( + par_o.__class__.__name__, par_o.full_id) + msg += obj_msg + msg = msg.strip() + if raise_exception: + raise ValueError(msg) + return msg + return [] if detailed else ''
+ + + +
+[docs] +def is_equivalent(object_1, object_2): + """Check if two objects are equal with an initial check for the same instance. + """ + if object_1 is object_2: # first see if they're the same instance + return True + return object_1 == object_2 # two objects that should have == operators
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/cli/validate.html b/docs/_modules/honeybee/cli/validate.html new file mode 100644 index 00000000..c818e7df --- /dev/null +++ b/docs/_modules/honeybee/cli/validate.html @@ -0,0 +1,1328 @@ + + + + + + + honeybee.cli.validate — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.cli.validate

+"""honeybee validation commands."""
+import sys
+import logging
+import json as py_json
+import click
+
+from honeybee.model import Model
+from honeybee.config import folders
+
+_logger = logging.getLogger(__name__)
+
+
+@click.group(help='Commands for validating Honeybee objects.')
+def validate():
+    pass
+
+
+@validate.command('model')
+@click.argument('model-file', type=click.Path(
+    exists=True, file_okay=True, dir_okay=False, resolve_path=True))
+@click.option(
+    '--check-all/--room-overlaps', ' /-ro', help='Flag to note whether the output '
+    'validation report should validate all possible issues with the model or only '
+    'the Room collisions should be checked.', default=True, show_default=True)
+@click.option(
+    '--plain-text/--json', ' /-j', help='Flag to note whether the output validation '
+    'report should be formatted as a JSON object instead of plain text. If set to JSON, '
+    'the output object will contain several attributes. The "honeybee_core" and '
+    '"honeybee_schema" attributes will note the versions of these libraries used in '
+    'the validation process. An attribute called "fatal_error" is a text string '
+    'containing an exception if the Model failed to serialize and will be an empty '
+    'string if serialization was successful. An attribute called "errors" will '
+    'contain a list of JSON objects for each invalid issue found in the model. A '
+    'boolean attribute called "valid" will note whether the Model is valid or not.',
+    default=True, show_default=True)
+@click.option(
+    '--output-file', '-f', help='Optional file to output the full report '
+    'of the validation. By default it will be printed out to stdout',
+    type=click.File('w'), default='-')
+def validate_model_cli(model_file, check_all, plain_text, output_file):
+    """Validate all properties of a Model file against Honeybee schema.
+
+    This includes checking basic compliance with the 5 rules of honeybee geometry
+    as well as checks for all extension attributes. The 5 rules of honeybee geometry
+    are as follows.
+
+    1. All Face3Ds must be planar to within the model tolerance.
+
+    2. All Face3Ds must NOT be self-intersecting (like a bowtie shape)
+
+    3. All children sub-faces (Apertures and Doors) must be co-planar with
+        their parent Face and lie completely within its boundary.
+
+    4. All adjacent object pairs (faces and sub-faces with a Surface boundary
+        condition) must have matching areas.
+
+    5. All Room volumes must be closed solids.
+
+    \b
+    Args:
+        model_file: Full path to a Model JSON file.
+    """
+    try:
+        json = not plain_text
+        room_overlaps = not check_all
+        validate_model(model_file, room_overlaps, json, output_file)
+    except Exception as e:
+        _logger.exception('Model validation failed.\n{}'.format(e))
+        sys.exit(1)
+    else:
+        sys.exit(0)
+
+
+
+[docs] +def validate_model(model_file, room_overlaps=False, json=False, output_file=None, + check_all=True, plain_text=True): + """Validate all properties of a Model file against the Honeybee schema. + + This includes checking basic compliance with the 5 rules of honeybee geometry + as well as checks for all extension attributes. + + Args: + model_file: Full path to a Honeybee Model file. + room_overlaps: Boolean to note whether the output validation report + should only validate the Room collisions (True) or all possible + issues with the model should be checked (False). (Default: False). + json: Boolean to note whether the output validation report should be + formatted as a JSON object instead of plain text. + output_file: Optional file to output the string of the visualization + file contents. If None, the string will simply be returned from + this method. + """ + if not json: + # re-serialize the Model to make sure no errors are found + c_ver = folders.honeybee_core_version_str + s_ver = folders.honeybee_schema_version_str + ver_msg = 'Validating Model using honeybee-core=={} and ' \ + 'honeybee-schema=={}'.format(c_ver, s_ver) + print(ver_msg) + parsed_model = Model.from_file(model_file) + print('Re-serialization passed.') + # perform several other checks for geometry rules and others + if not room_overlaps: + report = parsed_model.check_all(raise_exception=False, detailed=False) + else: + report = parsed_model.check_room_volume_collisions(raise_exception=False) + print('Model checks completed.') + # check the report and write the summary of errors + if report == '': + full_msg = ver_msg + '\nCongratulations! Your Model is valid!' + else: + full_msg = ver_msg + \ + '\nYour Model is invalid for the following reasons:\n' + report + if output_file is None: + return full_msg + else: + output_file.write(full_msg) + else: + out_dict = { + 'type': 'ValidationReport', + 'app_name': 'Honeybee', + 'app_version': folders.honeybee_core_version_str, + 'schema_version': folders.honeybee_schema_version_str + } + try: + parsed_model = Model.from_file(model_file) + out_dict['fatal_error'] = '' + if not room_overlaps: + errors = parsed_model.check_all(raise_exception=False, detailed=True) + else: + errors = parsed_model.check_room_volume_collisions( + raise_exception=False, detailed=True) + out_dict['errors'] = errors + out_dict['valid'] = True if len(out_dict['errors']) == 0 else False + except Exception as e: + out_dict['fatal_error'] = str(e) + out_dict['errors'] = [] + out_dict['valid'] = False + if output_file is None: + return py_json.dumps(out_dict, indent=4) + else: + output_file.write(py_json.dumps(out_dict, indent=4))
+ + + +@validate.command('room-volumes') +@click.argument('model-file', type=click.Path( + exists=True, file_okay=True, dir_okay=False, resolve_path=True)) +@click.option( + '--output-file', '-f', help='Optional file to output the JSON strings of ' + 'ladybug_geometry LineSegment3Ds that represent naked and non-manifold edges. ' + 'By default it will be printed out to stdout', type=click.File('w'), default='-') +def validate_room_volumes_cli(model_file, output_file): + """Get a list of all naked and non-manifold edges preventing closed room volumes. + + This is helpful for visually identifying issues in geometry that are preventing + the room volume from reading as closed. + + \b + Args: + model_file: Full path to a Honeybee Model file. + """ + try: + validate_room_volumes(model_file, output_file) + except Exception as e: + _logger.exception('Model room volume validation failed.\n{}'.format(e)) + sys.exit(1) + else: + sys.exit(0) + + +
+[docs] +def validate_room_volumes(model_file, output_file=None): + """Get a list of all naked and non-manifold edges preventing closed room volumes. + + This is helpful for visually identifying issues in geometry that are preventing + the room volume from reading as closed. + + Args: + model_file: Full path to a Honeybee Model file. + output_file: Optional file to output the string of the visualization + file contents. If None, the string will simply be returned from + this method. + """ + # re-serialize the Model and collect all naked and non-manifold edges + parsed_model = Model.from_file(model_file) + problem_edges = [] + for room in parsed_model.rooms: + if not room.geometry.is_solid: + problem_edges.extend(room.geometry.naked_edges) + problem_edges.extend(room.geometry.non_manifold_edges) + # write the new model out to the file or stdout + prob_array = [lin.to_dict() for lin in problem_edges] + if output_file is None: + return py_json.dumps(prob_array) + else: + output_file.write(py_json.dumps(prob_array))
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/colorobj.html b/docs/_modules/honeybee/colorobj.html new file mode 100644 index 00000000..91ead000 --- /dev/null +++ b/docs/_modules/honeybee/colorobj.html @@ -0,0 +1,1497 @@ + + + + + + + honeybee.colorobj — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.colorobj

+# coding=utf-8
+"""Module for coloring geometry with attributes."""
+from __future__ import division
+
+from .shademesh import ShadeMesh
+from .shade import Shade
+from .door import Door
+from .aperture import Aperture
+from .face import Face
+from .room import Room
+from .facetype import Floor
+from .search import get_attr_nested
+
+from ladybug.graphic import GraphicContainer
+from ladybug.legend import LegendParameters, LegendParametersCategorized
+from ladybug_geometry.geometry3d.pointvector import Point3D
+
+
+class _ColorObject(object):
+    """Base class for visualization objects.
+
+    Properties:
+        * legend_parameters
+        * attr_name
+        * attr_name_end
+        * attributes
+        * attributes_unique
+        * attributes_original
+        * min_point
+        * max_point
+        * graphic_container
+    """
+    __slots__ = ('_attr_name', '_legend_parameters', '_attr_name_end',
+                 '_attributes', '_attributes_unique', '_attributes_original',
+                 '_min_point', '_max_point')
+
+    def __init__(self, legend_parameters=None):
+        """Initialize ColorObject."""
+        # assign the legend parameters of this object
+        self.legend_parameters = legend_parameters
+
+        self._attr_name = None
+        self._attr_name_end = None
+        self._attributes = None
+        self._attributes_unique = None
+        self._attributes_original = None
+        self._min_point = None
+        self._max_point = None
+
+    @property
+    def legend_parameters(self):
+        """Get or set the legend parameters."""
+        return self._legend_parameters
+
+    @legend_parameters.setter
+    def legend_parameters(self, value):
+        if value is not None:
+            assert isinstance(value, LegendParameters) and not \
+                isinstance(value, LegendParametersCategorized), \
+                'Expected LegendParameters. Got {}.'.format(type(value))
+            self._legend_parameters = value
+        else:
+            self._legend_parameters = LegendParameters()
+
+    @property
+    def attr_name(self):
+        """Get a text string of an attribute that the input objects should have."""
+        return self._attr_name
+
+    @property
+    def attr_name_end(self):
+        """Get text for the last attribute in the attr_name.
+
+        Useful when attr_name is nested.
+        """
+        return self._attr_name_end
+
+    @property
+    def attributes(self):
+        """Get a tuple of text for the attributes assigned to the objects.
+
+        If the input attr_name is a valid attribute for the object but None is
+        assigned, the output will be 'None'. If the input attr_name is not valid
+        for the input object, 'N/A' will be returned.
+        """
+        return self._attributes
+
+    @property
+    def attributes_unique(self):
+        """Get a tuple of text for the unique attributes assigned to the objects."""
+        return self._attributes_unique
+
+    @property
+    def attributes_original(self):
+        """Get a tuple of objects for the attributes assigned to the objects.
+
+        These will follow the original object typing of the attribute and won't
+        be strings like the attributes.
+        """
+        return self._attributes_original
+
+    @property
+    def min_point(self):
+        """Get a Point3D for the minimum of the box around the objects."""
+        return self._min_point
+
+    @property
+    def max_point(self):
+        """Get a Point3D for the maximum of the box around the objects."""
+        return self._max_point
+
+    @property
+    def graphic_container(self):
+        """Get a ladybug GraphicContainer that relates to this object.
+
+        The GraphicContainer possesses almost all things needed to visualize the
+        ColorRooms object including the legend, value_colors, etc.
+        """
+        # produce a range of values from the collected attributes
+        attr_dict = {i: val for i, val in enumerate(self._attributes_unique)}
+        attr_dict_rev = {val: i for i, val in attr_dict.items()}
+        try:
+            values = tuple(attr_dict_rev[r_attr] for r_attr in self._attributes)
+        except KeyError:  # possibly caused by float cast to -0.0
+            values = []
+            for r_attr in self._attributes:
+                if r_attr == '-0.0':
+                    values.append(attr_dict_rev['0.0'])
+                else:
+                    values.append(attr_dict_rev[r_attr])
+
+        # produce legend parameters with an ordinal dict for the attributes
+        l_par = self.legend_parameters.duplicate()
+        if l_par.is_segment_count_default:
+            l_par.segment_count = len(self._attributes_unique)
+        l_par.ordinal_dictionary = attr_dict
+        if l_par.is_title_default:
+            l_par.title = self.attr_name_end.replace('_', ' ').title()
+
+        return GraphicContainer(values, self.min_point, self.max_point, l_par)
+
+    def _process_attribute_name(self, attr_name):
+        """Process the attribute name and assign it to this object."""
+        self._attr_name = str(attr_name)
+        at_split = self._attr_name.split('.')
+        if len(at_split) == 1:
+            self._attr_name_end = at_split[-1]
+        elif at_split[-1] == 'display_name':
+            self._attr_name_end = at_split[-2]
+        elif at_split[-1] == '__name__' and at_split[-2] == '__class__':
+            self._attr_name_end = at_split[-3]
+        else:
+            self._attr_name_end = at_split[-1]
+
+    def _process_attributes(self, hb_objs):
+        """Process the attributes of honeybee objects."""
+        nd = self.legend_parameters.decimal_count
+        attributes = [get_attr_nested(obj, self._attr_name, nd) for obj in hb_objs]
+        attributes_unique = set(attributes)
+        float_attr = [atr for atr in attributes_unique if isinstance(atr, float)]
+        str_attr = [atr for atr in attributes_unique if isinstance(atr, str)]
+        float_attr.sort()
+        str_attr.sort()
+        self._attributes = tuple(str(val) for val in attributes)
+        self._attributes_unique = tuple(str_attr) + tuple(str(val) for val in float_attr)
+        self._attributes_original = \
+            tuple(get_attr_nested(obj, self._attr_name, cast_to_str=False)
+                  for obj in hb_objs)
+
+    def _calculate_min_max(self, hb_objs):
+        """Calculate maximum and minimum Point3D for a set of rooms."""
+        st_rm_min, st_rm_max = hb_objs[0].geometry.min, hb_objs[0].geometry.max
+        min_pt = [st_rm_min.x, st_rm_min.y, st_rm_min.z]
+        max_pt = [st_rm_max.x, st_rm_max.y, st_rm_max.z]
+
+        for room in hb_objs[1:]:
+            rm_min, rm_max = room.geometry.min, room.geometry.max
+            if rm_min.x < min_pt[0]:
+                min_pt[0] = rm_min.x
+            if rm_min.y < min_pt[1]:
+                min_pt[1] = rm_min.y
+            if rm_min.z < min_pt[2]:
+                min_pt[2] = rm_min.z
+            if rm_max.x > max_pt[0]:
+                max_pt[0] = rm_max.x
+            if rm_max.y > max_pt[1]:
+                max_pt[1] = rm_max.y
+            if rm_max.z > max_pt[2]:
+                max_pt[2] = rm_max.z
+
+        self._min_point = Point3D(min_pt[0], min_pt[1], min_pt[2])
+        self._max_point = Point3D(max_pt[0], max_pt[1], max_pt[2])
+
+    def ToString(self):
+        """Overwrite .NET ToString."""
+        return self.__repr__()
+
+
+
+[docs] +class ColorRoom(_ColorObject): + """Object for visualizing room-level attributes. + + Args: + rooms: An array of honeybee Rooms, which will be colored with the attribute. + attr_name: A text string of an attribute that the input rooms should have. + This can have '.' that separate the nested attributes from one another. + For example, 'properties.energy.program_type'. + legend_parameters: An optional LegendParameter object to change the display + of the ColorRoom (Default: None). + + Properties: + * rooms + * attr_name + * legend_parameters + * attr_name_end + * attributes + * attributes_unique + * attributes_original + * floor_faces + * graphic_container + * min_point + * max_point + """ + __slots__ = ('_rooms',) + + def __init__(self, rooms, attr_name, legend_parameters=None): + """Initialize ColorRoom.""" + try: # check the input rooms + rooms = tuple(rooms) + except TypeError: + raise TypeError('Input rooms must be an array. Got {}.'.format(type(rooms))) + assert len(rooms) > 0, 'ColorRooms must have at least one room.' + for room in rooms: + assert isinstance(room, Room), 'Expected honeybee Room for ' \ + 'ColorRoom rooms. Got {}.'.format(type(room)) + self._rooms = rooms + self._calculate_min_max(rooms) + + # assign the legend parameters of this object + self.legend_parameters = legend_parameters + + # get the attributes of the input rooms + self._process_attribute_name(attr_name) + self._process_attributes(rooms) + + @property + def rooms(self): + """Get a tuple of honeybee Rooms assigned to this object.""" + return self._rooms + + @property + def floor_faces(self): + """Get a nested array with each sub-array having all floor Face3Ds of each room. + + This is useful for producing visualizations since coloring floors or rooms + instead of the entire room solid allows more of the model to be viewed at once. + """ + flr_faces = [] + for room in self.rooms: + flr_faces.append( + [face.geometry for face in room.faces if isinstance(face.type, Floor)]) + return flr_faces + + def __repr__(self): + """Color Room representation.""" + return 'Color Room:\n{} Rooms\n{}'.format(len(self.rooms), self.attr_name_end)
+ + + +
+[docs] +class ColorFace(_ColorObject): + """Object for visualizing face and sub-face level attributes. + + Args: + faces: An array of honeybee Faces, Apertures, Doors, Shades and/or ShadeMeshes + which will be colored with their attributes. + attr_name: A text string of an attribute that the input faces should have. + This can have '.' that separate the nested attributes from one another. + For example, 'properties.energy.construction'. + legend_parameters: An optional LegendParameter object to change the display + of the ColorFace (Default: None). + + Properties: + * faces + * attr_name + * legend_parameters + * flat_faces + * flat_geometry + * attr_name_end + * attributes + * attributes_unique + * attributes_original + * floor_faces + * graphic_container + * min_point + * max_point + """ + __slots__ = ('_faces', '_flat_faces', '_flat_geometry') + + def __init__(self, faces, attr_name, legend_parameters=None): + """Initialize ColorFace.""" + try: # check the input faces + faces = tuple(faces) + except TypeError: + raise TypeError('Input faces must be an array. Got {}.'.format(type(faces))) + assert len(faces) > 0, 'ColorFaces must have at least one face.' + flat_f = [] + for face in faces: + if isinstance(face, Face): + flat_f.append(face) + flat_f.extend(face.shades) + for ap in face.apertures: + flat_f.append(ap) + flat_f.extend(ap.shades) + for dr in face.doors: + flat_f.append(dr) + flat_f.extend(dr.shades) + elif isinstance(face, (Aperture, Door)): + flat_f.append(face) + flat_f.extend(face.shades) + elif isinstance(face, Shade): + flat_f.append(face) + elif isinstance(face, ShadeMesh): + flat_f.append(face) + else: + raise ValueError( + 'Expected honeybee Face, Aperture, Door, Shade or ShadeMesh ' + 'for ColorFaces. Got {}.'.format(type(face))) + self._faces = faces + self._flat_faces = tuple(flat_f) + self._flat_geometry = tuple(face.geometry if not isinstance(face, Face) + else face.punched_geometry for face in flat_f) + self._calculate_min_max(faces) + + # assign the legend parameters of this object + self.legend_parameters = legend_parameters + + # get the attributes of the input faces + self._process_attribute_name(attr_name) + self._process_attributes(flat_f) + + @property + def faces(self): + """Get the honeybee Faces, Apertures, Doors and Shades assigned to this object. + """ + return self._faces + + @property + def flat_faces(self): + """Get non-nested honeybee Faces, Apertures, Doors and Shades on this object. + + The objects here align with the attributes and graphic_container colors. + """ + return self._flat_faces + + @property + def flat_geometry(self): + """Get non-nested array of faces on this object. + + The geometries here align with the attributes and graphic_container colors. + """ + return self._flat_geometry + + def __repr__(self): + """Color Room representation.""" + return 'Color Faces:\n{} Faces\n{}'.format(len(self.faces), self.attr_name_end)
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/config.html b/docs/_modules/honeybee/config.html new file mode 100644 index 00000000..1a46c0bd --- /dev/null +++ b/docs/_modules/honeybee/config.html @@ -0,0 +1,1478 @@ + + + + + + + honeybee.config — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.config

+"""Honeybee configurations.
+
+Import this into every module where access configurations are needed.
+
+Usage:
+
+.. code-block:: python
+
+    from honeybee.config import folders
+    print(folders.python_exe_path)
+    print(folders.default_simulation_folder)
+    folders.default_simulation_folder = "C:/my_sim_folder"
+"""
+import ladybug.config as lb_config
+
+import os
+import platform
+import sys
+import subprocess
+import json
+import tempfile
+
+
+
+[docs] +class Folders(object): + """Honeybee folders. + + Args: + config_file: The path to the config.json file from which folders are loaded. + If None, the config.json module included in this package will be used. + Default: None. + mute: If False, the paths to the various folders will be printed as they + are found. If True, no printing will occur upon initialization of this + class. Default: True. + + Properties: + * default_simulation_folder + * honeybee_core_version + * honeybee_core_version_str + * honeybee_schema_version + * honeybee_schema_version_str + * python_package_path + * python_scripts_path + * python_exe_path + * python_version + * python_version_str + * default_standards_folder + * config_file + * mute + """ + + def __init__(self, config_file=None, mute=True): + # set the mute value + self.mute = bool(mute) + + # load paths from the config JSON file + self.config_file = config_file + + # set python version to only be retrieved if requested + self._python_version = None + self._python_version_str = None + + # search for the version of honeybee-core and honeybee-schema + self._honeybee_core_version = self._find_honeybee_core_version() + self._honeybee_schema_version = self._find_honeybee_schema_version() + + @property + def default_simulation_folder(self): + """Get or set the path to the default simulation folder.""" + return self._default_simulation_folder + + @default_simulation_folder.setter + def default_simulation_folder(self, path): + if not path: # check the default location for simulations + path = self._find_default_simulation_folder() + + self._default_simulation_folder = path + + if not self.mute and self._default_simulation_folder: + print('Path to the default simulation folder is set to: ' + '{}'.format(self._default_simulation_folder)) + + @property + def honeybee_core_version(self): + """Get a tuple for the installed version of honeybee-core (eg. (1, 47, 26)). + + This will be None if the version could not be sensed (it was not installed + via pip). + """ + return self._honeybee_core_version + + @property + def honeybee_core_version_str(self): + """Get a string for the installed version of honeybee-core (eg. "1.47.26"). + + This will be None if the version could not be sensed. + """ + if self._honeybee_core_version is not None: + return '.'.join([str(item) for item in self._honeybee_core_version]) + return None + + @property + def honeybee_schema_version(self): + """Get a tuple for the installed version of honeybee-schema (eg. (1, 35, 0)). + + This will be None if the version could not be sensed (it was not installed + via pip) or if no honeybee-schema installation was found next to the + honeybee-core installation. + """ + return self._honeybee_schema_version + + @property + def honeybee_schema_version_str(self): + """Get a string for the installed version of honeybee-schema (eg. "1.35.0"). + + This will be None if the version could not be sensed. + """ + if self._honeybee_schema_version is not None: + return '.'.join([str(item) for item in self._honeybee_schema_version]) + return None + + @property + def python_package_path(self): + """Get the path to where this Python package is installed.""" + # check the ladybug_tools folder for a Python installation + py_pack = None + lb_install = lb_config.folders.ladybug_tools_folder + if os.path.isdir(lb_install): + if os.name == 'nt': + py_pack = os.path.join(lb_install, 'python', 'Lib', 'site-packages') + elif platform.system() == 'Darwin': # on mac, python version is in path + py_pack = os.path.join( + lb_install, 'python', 'lib', 'python3.7', 'site-packages') + if py_pack is not None and os.path.isdir(py_pack): + return py_pack + return os.path.split(os.path.dirname(__file__))[0] # we're on some other cPython + + @property + def python_scripts_path(self): + """Get the path to where Python CLI executable files are installed. + + This can be used to call command line interface (CLI) executable files + directly (instead of using their usual entry points). + """ + # check the ladybug_tools folder for a Python installation + lb_install = lb_config.folders.ladybug_tools_folder + if os.path.isdir(lb_install): + py_scripts = os.path.join(lb_install, 'python', 'Scripts') \ + if os.name == 'nt' else \ + os.path.join(lb_install, 'python', 'bin') + if os.path.isdir(py_scripts): + return py_scripts + sys_dir = os.path.dirname(sys.executable) # assume we are on some other cPython + return os.path.join(sys_dir, 'Scripts') if os.name == 'nt' else sys_dir + + @property + def python_exe_path(self): + """Get the path to the Python executable to be used for Ladybug Tools CLI calls. + + If a version of Python is found within the ladybug_tools installation folder, + this will be the path to that version of Python. Otherwise, it will be + assumed that this is package is installed in cPython outside of the ladybug_tools + folder and the sys.executable will be returned. + """ + # check the ladybug_tools folder for a Python installation + lb_install = lb_config.folders.ladybug_tools_folder + if os.path.isdir(lb_install): + py_exe_file = os.path.join(lb_install, 'python', 'python.exe') \ + if os.name == 'nt' else \ + os.path.join(lb_install, 'python', 'bin', 'python3') + if os.path.isfile(py_exe_file): + return py_exe_file + return sys.executable # assume we are on some other cPython + + @property + def python_version(self): + """Get a tuple for the version of python (eg. (3, 8, 2)). + + This will be None if the version could not be sensed or if no Python + installation was found. + """ + if self._python_version_str is None and self.python_exe_path: + self._python_version_from_cli() + return self._python_version + + @property + def python_version_str(self): + """Get text for the full version of python (eg."3.8.2"). + + This will be None if the version could not be sensed or if no Python + installation was found. + """ + if self._python_version_str is None and self.python_exe_path: + self._python_version_from_cli() + return self._python_version_str + + @property + def default_standards_folder(self): + """Get or set the path to the default standards library used by extensions. + """ + return self._default_standards_folder + + @default_standards_folder.setter + def default_standards_folder(self, path): + if not path: # check the default locations of the template library + path = self._find_default_standards_folder() + + # set the default_standards_folder + self._default_standards_folder = path + if path and not self.mute: + print('Path to the default_standards_folder is set to: ' + '{}'.format(self._default_standards_folder)) + + @property + def config_file(self): + """Get or set the path to the config.json file from which folders are loaded. + + Setting this to None will result in using the config.json module included + in this package. + """ + return self._config_file + + @config_file.setter + def config_file(self, cfg): + if cfg is None: + cfg = os.path.join(os.path.dirname(__file__), 'config.json') + self._load_from_file(cfg) + self._config_file = cfg + + def _load_from_file(self, file_path): + """Set all of the the properties of this object from a config JSON file. + + Args: + file_path: Path to a JSON file containing the file paths. A sample of this + JSON is the config.json file within this package. + """ + # check the default file path + assert os.path.isfile(file_path), \ + ValueError('No file found at {}'.format(file_path)) + + # set the default paths to be all blank + default_path = { + "default_simulation_folder": r'', + "default_standards_folder": r'' + } + + with open(file_path, 'r') as cfg: + try: + paths = json.load(cfg) + except Exception as e: + print('Failed to load paths from {}.\nThey will be set to defaults ' + 'instead\n{}'.format(file_path, e)) + else: + for key, p in paths.items(): + if not key.startswith('__') and p.strip(): + default_path[key] = p.strip() + + # set paths for the default_simulation_folder + self.default_simulation_folder = default_path["default_simulation_folder"] + self.default_standards_folder = default_path["default_standards_folder"] + + def _python_version_from_cli(self): + """Set this object's Python version by making a call to a Python command.""" + cmds = [self.python_exe_path, '--version'] + use_shell = True if os.name == 'nt' else False + process = subprocess.Popen(cmds, stdout=subprocess.PIPE, shell=use_shell) + stdout = process.communicate() + base_str = str(stdout[0]).replace("b'", '').replace(r"\r\n'", '') + self._python_version_str = base_str.split(' ')[-1] + try: + self._python_version = \ + tuple(int(i) for i in self._python_version_str.split('.')) + except Exception: + pass # failed to parse the version into values + + @staticmethod + def _find_default_simulation_folder(): + """Find the the default simulation folder in its usual location. + + An attempt will be made to create the directory if it does not already exist. + """ + home_folder = os.getenv('HOME') or os.path.expanduser('~') + if not os.access(home_folder, os.W_OK): + home_folder = tempfile.gettempdir() + sim_folder = os.path.join(home_folder, 'simulation') + if not os.path.isdir(sim_folder): + try: + os.makedirs(sim_folder) + except OSError as e: + if e.errno != 17: # avoid race conditions between multiple tasks + raise OSError('Failed to create default simulation ' + 'folder: %s\n%s' % (sim_folder, e)) + return sim_folder + + @staticmethod + def _find_default_standards_folder(): + """Find the user standards library in its default location. + + The %AppData%/ladybug_tools/standards folder will be checked first, which + can contain libraries that are not overwritten with the update of the + honeybee_energy package. If this is not found, the ladybug_tools/resources/ + standards/honeybee_standards folder will be checked next. If no such folder + is found, this None will be returned. + """ + # first check if there's a user-defined folder in AppData + app_folder = os.getenv('APPDATA') + if app_folder is not None: + lib_folder = os.path.join(app_folder, 'ladybug_tools', 'standards') + if os.path.isdir(lib_folder): + return lib_folder + + # then check the ladybug_tools installation folder were permanent lib is + lb_install = lb_config.folders.ladybug_tools_folder + if os.path.isdir(lb_install): + lib_folder = os.path.join( + lb_install, 'resources', 'standards', 'honeybee_standards') + if os.path.isdir(lib_folder): + return lib_folder + + # default to None if nothing was found + return None + + def _find_honeybee_core_version(self): + """Get a tuple of 3 integers for the version of honeybee_core if installed.""" + return self._find_package_version('honeybee_core') + + def _find_honeybee_schema_version(self): + """Get a tuple of 3 integers for the version of honeybee_schema if installed.""" + return self._find_package_version('honeybee_schema') + + def _find_package_version(self, package_name): + """Get a tuple of 3 integers for the version of a package.""" + hb_info_folder = None + for item in os.listdir(self.python_package_path): + if item.startswith(package_name + '-') and item.endswith('.dist-info'): + if os.path.isdir(os.path.join(self.python_package_path, item)): + hb_info_folder = item + break + if hb_info_folder is not None: + hb_info_folder = hb_info_folder.replace('.dist-info', '') + ver = ''.join(s for s in hb_info_folder if (s.isdigit() or s == '.')) + if ver: # version was found in the file path name + return tuple(int(d) for d in ver.split('.')) + return None
+ + + +"""Object possesing all key folders within the configuration.""" +folders = Folders() +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/dictutil.html b/docs/_modules/honeybee/dictutil.html new file mode 100644 index 00000000..ae6de69c --- /dev/null +++ b/docs/_modules/honeybee/dictutil.html @@ -0,0 +1,1185 @@ + + + + + + + honeybee.dictutil — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.dictutil

+# coding=utf-8
+"""Utilities to convert any dictionary to Python objects.
+
+Note that importing this module will import almost all modules within the
+library in order to be able to re-serialize almost any dictionary produced
+from the library.
+"""
+from honeybee.model import Model
+from honeybee.room import Room
+from honeybee.face import Face
+from honeybee.aperture import Aperture
+from honeybee.door import Door
+from honeybee.shade import Shade
+import honeybee.boundarycondition as hbc
+
+
+
+[docs] +def dict_to_object(honeybee_dict, raise_exception=True): + """Re-serialize a dictionary of almost any object within honeybee. + + This includes any Model, Room, Face, Aperture, Door, Shade, or boundary + condition object. + + Args: + honeybee_dict: A dictionary of any Honeybee object. Note + that this should be a non-abridged dictionary to be valid. + raise_exception: Boolean to note whether an exception should be raised + if the object is not identified as a part of honeybee. + Default: True. + + Returns: + A Python object derived from the input honeybee_dict. + """ + try: # get the type key from the dictionary + obj_type = honeybee_dict['type'] + except KeyError: + raise ValueError('Honeybee dictionary lacks required "type" key.') + + if obj_type == 'Model': + return Model.from_dict(honeybee_dict) + elif obj_type == 'Room': + return Room.from_dict(honeybee_dict) + elif obj_type == 'Face': + return Face.from_dict(honeybee_dict) + elif obj_type == 'Aperture': + return Aperture.from_dict(honeybee_dict) + elif obj_type == 'Door': + return Door.from_dict(honeybee_dict) + elif obj_type == 'Shade': + return Shade.from_dict(honeybee_dict) + elif hasattr(hbc, obj_type): + bc_class = getattr(hbc, obj_type) + return bc_class.from_dict(honeybee_dict) + elif raise_exception: + raise ValueError('{} is not a recognized honeybee object'.format(obj_type))
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/door.html b/docs/_modules/honeybee/door.html new file mode 100644 index 00000000..36e764d6 --- /dev/null +++ b/docs/_modules/honeybee/door.html @@ -0,0 +1,1826 @@ + + + + + + + honeybee.door — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.door

+# coding: utf-8
+"""Honeybee Door."""
+from __future__ import division
+import math
+
+from ladybug_geometry.geometry2d.pointvector import Vector2D
+from ladybug_geometry.geometry3d.pointvector import Point3D
+from ladybug_geometry.geometry3d.face import Face3D
+from ladybug.color import Color
+
+from ._basewithshade import _BaseWithShade
+from .typing import clean_string
+from .properties import DoorProperties
+from .boundarycondition import boundary_conditions, Outdoors, Surface
+from .shade import Shade
+import honeybee.writer.door as writer
+
+
+
+[docs] +class Door(_BaseWithShade): + """A single planar Door in a Face. + + Args: + identifier: Text string for a unique Door ID. Must be < 100 characters and + not contain any spaces or special characters. + geometry: A ladybug-geometry Face3D. + boundary_condition: Boundary condition object (Outdoors, Surface, etc.). + Default: Outdoors. + is_glass: Boolean to note whether this object is a glass door as opposed + to an opaque door. Default: False. + + Properties: + * identifier + * display_name + * boundary_condition + * is_glass + * indoor_shades + * outdoor_shades + * parent + * top_level_parent + * has_parent + * geometry + * vertices + * upper_left_vertices + * triangulated_mesh3d + * normal + * center + * area + * perimeter + * min + * max + * tilt + * altitude + * azimuth + * type_color + * bc_color + * user_data + """ + __slots__ = ('_geometry', '_parent', '_boundary_condition', '_is_glass') + TYPE_COLORS = { + False: Color(160, 150, 100), + True: Color(128, 204, 255, 100) + } + BC_COLORS = { + 'Outdoors': Color(128, 204, 255), + 'Surface': Color(0, 190, 0) + } + + def __init__(self, identifier, geometry, boundary_condition=None, is_glass=False): + """A single planar Door in a Face.""" + _BaseWithShade.__init__(self, identifier) # process the identifier + + # process the geometry + assert isinstance(geometry, Face3D), \ + 'Expected ladybug_geometry Face3D. Got {}'.format(type(geometry)) + self._geometry = geometry + self._parent = None # _parent will be set when the Face is added to a Face + + # process the boundary condition and type + self.boundary_condition = boundary_condition or boundary_conditions.outdoors + self.is_glass = is_glass + + # initialize properties for extensions + self._properties = DoorProperties(self) + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize an Door from a dictionary. + + Args: + data: A dictionary representation of an Door object. + """ + try: + # check the type of dictionary + assert data['type'] == 'Door', 'Expected Door dictionary. ' \ + 'Got {}.'.format(data['type']) + + # serialize the door + is_glass = data['is_glass'] if 'is_glass' in data else False + if data['boundary_condition']['type'] == 'Outdoors': + boundary_condition = Outdoors.from_dict(data['boundary_condition']) + elif data['boundary_condition']['type'] == 'Surface': + boundary_condition = Surface.from_dict(data['boundary_condition'], True) + else: + raise ValueError( + 'Boundary condition "{}" is not supported for Door.'.format( + data['boundary_condition']['type'])) + door = cls(data['identifier'], Face3D.from_dict(data['geometry']), + boundary_condition, is_glass) + if 'display_name' in data and data['display_name'] is not None: + door.display_name = data['display_name'] + if 'user_data' in data and data['user_data'] is not None: + door.user_data = data['user_data'] + door._recover_shades_from_dict(data) + + # assign extension properties + if data['properties']['type'] == 'DoorProperties': + door.properties._load_extension_attr_from_dict(data['properties']) + return door + except Exception as e: + cls._from_dict_error_message(data, e)
+ + +
+[docs] + @classmethod + def from_vertices(cls, identifier, vertices, boundary_condition=None, + is_glass=False): + """Create a Door from vertices with each vertex as an iterable of 3 floats. + + Args: + identifier: Text string for a unique Door ID. Must be < 100 characters and + not contain any spaces or special characters. + vertices: A flattened list of 3 or more vertices as (x, y, z). + boundary_condition: Boundary condition object (eg. Outdoors, Surface). + Default: Outdoors. + is_glass: Boolean to note whether this object is a glass door as opposed + to an opaque door. Default: False. + """ + geometry = Face3D(tuple(Point3D(*v) for v in vertices)) + return cls(identifier, geometry, boundary_condition, is_glass)
+ + + @property + def boundary_condition(self): + """Get or set the boundary condition of this door.""" + return self._boundary_condition + + @boundary_condition.setter + def boundary_condition(self, value): + if not isinstance(value, Outdoors): + if isinstance(value, Surface): + assert len(value.boundary_condition_objects) == 3, 'Surface boundary ' \ + 'condition for Door must have 3 boundary_condition_objects.' + else: + raise ValueError('Door only supports Outdoor or Surface boundary ' + 'condition. Got {}'.format(type(value))) + self._boundary_condition = value + + @property + def is_glass(self): + """Get or set a boolean to note whether this object is a glass door.""" + return self._is_glass + + @is_glass.setter + def is_glass(self, value): + try: + self._is_glass = bool(value) + except TypeError: + raise TypeError( + 'Expected boolean for Door.is_glass. Got {}.'.format(value)) + + @property + def parent(self): + """Get the parent Face if assigned. None if not assigned.""" + return self._parent + + @property + def top_level_parent(self): + """Get the top-level parent object if assigned. + + This will be a Room if there is a parent Face that has a parent Room and + will be a Face if the parent Face is orphaned. Will be None if no parent + is assigned. + """ + if self.has_parent: + if self._parent.has_parent: + return self._parent._parent + return self._parent + return None + + @property + def has_parent(self): + """Get a boolean noting whether this Door has a parent Face.""" + return self._parent is not None + + @property + def geometry(self): + """Get a ladybug_geometry Face3D object representing the door.""" + return self._geometry + + @property + def vertices(self): + """Get a list of vertices for the door (in counter-clockwise order).""" + return self._geometry.vertices + + @property + def upper_left_vertices(self): + """Get a list of vertices starting from the upper-left corner. + + This property should be used when exporting to EnergyPlus / OpenStudio. + """ + return self._geometry.upper_left_counter_clockwise_vertices + + @property + def triangulated_mesh3d(self): + """Get a ladybug_geometry Mesh3D of the door geometry composed of triangles. + + In EnergyPlus / OpenStudio workflows, this property is used to subdivide + the door when it has more than 4 vertices. This is necessary since + EnergyPlus cannot accept sub-faces with more than 4 vertices. + """ + return self._geometry.triangulated_mesh3d + + @property + def normal(self): + """Get a ladybug_geometry Vector3D for the direction the door is pointing. + """ + return self._geometry.normal + + @property + def center(self): + """Get a ladybug_geometry Point3D for the center of the door. + + Note that this is the center of the bounding rectangle around this geometry + and not the area centroid. + """ + return self._geometry.center + + @property + def area(self): + """Get the area of the door.""" + return self._geometry.area + + @property + def perimeter(self): + """Get the perimeter of the door.""" + return self._geometry.perimeter + + @property + def min(self): + """Get a Point3D for the minimum of the bounding box around the object.""" + return self._min_with_shades(self._geometry) + + @property + def max(self): + """Get a Point3D for the maximum of the bounding box around the object.""" + return self._max_with_shades(self._geometry) + + @property + def tilt(self): + """Get the tilt of the geometry between 0 (up) and 180 (down).""" + return math.degrees(self._geometry.tilt) + + @property + def altitude(self): + """Get the altitude of the geometry between +90 (up) and -90 (down).""" + return math.degrees(self._geometry.altitude) + + @property + def azimuth(self): + """Get the azimuth of the geometry, between 0 and 360. + + Given Y-axis as North, 0 = North, 90 = East, 180 = South, 270 = West + This will be zero if the Face3D is perfectly horizontal. + """ + return math.degrees(self._geometry.azimuth) + + @property + def type_color(self): + """Get a Color to be used in visualizations by type.""" + return self.TYPE_COLORS[self.is_glass] + + @property + def bc_color(self): + """Get a Color to be used in visualizations by boundary condition.""" + return self.BC_COLORS[self.boundary_condition.name] + +
+[docs] + def horizontal_orientation(self, north_vector=Vector2D(0, 1)): + """Get a number between 0 and 360 for the orientation of the door in degrees. + + 0 = North, 90 = East, 180 = South, 270 = West + + Args: + north_vector: A ladybug_geometry Vector2D for the north direction. + Default is the Y-axis (0, 1). + """ + return math.degrees( + north_vector.angle_clockwise(Vector2D(self.normal.x, self.normal.y)))
+ + +
+[docs] + def cardinal_direction(self, north_vector=Vector2D(0, 1)): + """Get text description for the cardinal direction that the door is pointing. + + Will be one of the following: ('North', 'NorthEast', 'East', 'SouthEast', + 'South', 'SouthWest', 'West', 'NorthWest'). + + Args: + north_vector: A ladybug_geometry Vector2D for the north direction. + Default is the Y-axis (0, 1). + """ + orient = self.horizontal_orientation(north_vector) + orient_text = ('North', 'NorthEast', 'East', 'SouthEast', 'South', + 'SouthWest', 'West', 'NorthWest') + angles = (22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, 337.5) + for i, ang in enumerate(angles): + if orient < ang: + return orient_text[i] + return orient_text[0]
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier of this object and child objects by inserting a prefix. + + This is particularly useful in workflows where you duplicate and edit + a starting object and then want to combine it with the original object + into one Model (like making a model of repeated rooms) since all objects + within a Model must have unique identifiers. + + Args: + prefix: Text that will be inserted at the start of this object's + (and child objects') identifier and display_name. It is recommended + that this prefix be short to avoid maxing out the 100 allowable + characters for honeybee identifiers. + """ + self._identifier = clean_string('{}_{}'.format(prefix, self.identifier)) + self.display_name = '{}_{}'.format(prefix, self.display_name) + self.properties.add_prefix(prefix) + self._add_prefix_shades(prefix) + if isinstance(self._boundary_condition, Surface): + new_bc_objs = (clean_string('{}_{}'.format(prefix, adj_name)) for adj_name + in self._boundary_condition._boundary_condition_objects) + self._boundary_condition = Surface(new_bc_objs, True)
+ + +
+[docs] + def set_adjacency(self, other_door): + """Set this door to be adjacent to another (and vice versa). + + Note that this method does not verify whether the other_door geometry is + co-planar or compatible with this one so it is recommended that a test + be performed before using this method in order to verify these criteria. + The Face3D.is_centered_adjacent() or the Face3D.is_geometrically_equivalent() + methods are both suitable for this purpose. + + Args: + other_door: Another Door object to be set adjacent to this one. + """ + assert isinstance(other_door, Door), \ + 'Expected Door. Got {}.'.format(type(other_door)) + assert other_door.is_glass is self.is_glass, \ + 'Adjacent doors must have matching is_glass properties.' + self._boundary_condition = boundary_conditions.surface(other_door, True) + other_door._boundary_condition = boundary_conditions.surface(self, True)
+ + +
+[docs] + def overhang(self, depth, angle=0, indoor=False, tolerance=0.01, base_name=None): + """Add a single overhang for this Door. Can represent entryway awnings. + + Args: + depth: A number for the overhang depth. + angle: A number for the for an angle to rotate the overhang in degrees. + Positive numbers indicate a downward rotation while negative numbers + indicate an upward rotation. Default is 0 for no rotation. + indoor: Boolean for whether the overhang should be generated facing the + opposite direction of the aperture normal (typically meaning + indoor geometry). Default: False. + tolerance: An optional value to return None if the overhang has a length less + than the tolerance. Default: 0.01, suitable for objects in meters. + base_name: Optional base name for the shade objects. If None, the default + is InOverhang or OutOverhang depending on whether indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + # get a name for the shade + if base_name is None: + base_name = 'InOverhang' if indoor else 'OutOverhang' + shd_name_base = '{}_' + str(base_name) + '{}' + + # create the shade geometry + angle = math.radians(angle) + dr_geo = self.geometry if indoor is False else self.geometry.flip() + shade_faces = dr_geo.contour_fins_by_number( + 1, depth, 0, angle, Vector2D(0, 1), False, tolerance) + + # create the Shade objects + overhang = [] + for i, shade_geo in enumerate(shade_faces): + overhang.append(Shade(shd_name_base.format(self.identifier, i), shade_geo)) + if indoor: + self.add_indoor_shades(overhang) + else: + self.add_outdoor_shades(overhang) + return overhang
+ + +
+[docs] + def move(self, moving_vec): + """Move this Door along a vector. + + Args: + moving_vec: A ladybug_geometry Vector3D with the direction and distance + to move the face. + """ + self._geometry = self.geometry.move(moving_vec) + self.move_shades(moving_vec) + self.properties.move(moving_vec) + self._reset_parent_geometry()
+ + +
+[docs] + def rotate(self, axis, angle, origin): + """Rotate this Door by a certain angle around an axis and origin. + + Args: + axis: A ladybug_geometry Vector3D axis representing the axis of rotation. + angle: An angle for rotation in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate(axis, math.radians(angle), origin) + self.rotate_shades(axis, angle, origin) + self.properties.rotate(axis, angle, origin) + self._reset_parent_geometry()
+ + +
+[docs] + def rotate_xy(self, angle, origin): + """Rotate this Door counterclockwise in the world XY plane by a certain angle. + + Args: + angle: An angle in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate_xy(math.radians(angle), origin) + self.rotate_xy_shades(angle, origin) + self.properties.rotate_xy(angle, origin) + self._reset_parent_geometry()
+ + +
+[docs] + def reflect(self, plane): + """Reflect this Door across a plane. + + Args: + plane: A ladybug_geometry Plane across which the object will + be reflected. + """ + self._geometry = self.geometry.reflect(plane.n, plane.o) + self.reflect_shades(plane) + self.properties.reflect(plane) + self._reset_parent_geometry()
+ + +
+[docs] + def scale(self, factor, origin=None): + """Scale this Door by a factor from an origin point. + + Args: + factor: A number representing how much the object should be scaled. + origin: A ladybug_geometry Point3D representing the origin from which + to scale. If None, it will be scaled from the World origin (0, 0, 0). + """ + self._geometry = self.geometry.scale(factor, origin) + self.scale_shades(factor, origin) + self.properties.scale(factor, origin) + self._reset_parent_geometry()
+ + +
+[docs] + def remove_colinear_vertices(self, tolerance=0.01): + """Remove all colinear and duplicate vertices from this object's geometry. + + Note that this does not affect any assigned Shades. + + Args: + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered colinear. Default: 0.01, + suitable for objects in meters. + """ + try: + self._geometry = self.geometry.remove_colinear_vertices(tolerance) + except AssertionError as e: # usually a sliver face of some kind + raise ValueError( + 'Door "{}" is invalid with dimensions less than the ' + 'tolerance.\n{}'.format(self.full_id, e))
+ + +
+[docs] + def is_geo_equivalent(self, door, tolerance=0.01): + """Get a boolean for whether this object is geometrically equivalent to another. + + The total number of vertices and the ordering of these vertices can be + different but the geometries must share the same center point and be + next to one another to within the tolerance. + + Args: + door: Another Door for which geometric equivalency will be tested. + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered geometrically equivalent. + + Returns: + True if geometrically equivalent. False if not geometrically equivalent. + """ + meta_1 = (self.display_name, self.is_glass, self.boundary_condition) + meta_2 = (door.display_name, door.is_glass, door.boundary_condition) + if meta_1 != meta_2: + return False + if abs(self.area - door.area) > tolerance * self.area: + return False + if not self.geometry.is_centered_adjacent(door.geometry, tolerance): + return False + if not self._are_shades_equivalent(door, tolerance): + return False + return True
+ + +
+[docs] + def check_planar(self, tolerance=0.01, raise_exception=True, detailed=False): + """Check whether all of the Door's vertices lie within the same plane. + + Args: + tolerance: The minimum distance between a given vertex and a the + object's plane at which the vertex is said to lie in the plane. + Default: 0.01, suitable for objects in meters. + raise_exception: Boolean to note whether an ValueError should be + raised if a vertex does not lie within the object's plane. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + try: + self.geometry.check_planar(tolerance, raise_exception=True) + except ValueError as e: + msg = 'Door "{}" is not planar.\n{}'.format(self.full_id, e) + full_msg = self._validation_message( + msg, raise_exception, detailed, '000101', + error_type='Non-Planar Geometry') + if detailed: # add the out-of-plane points to helper_geometry + help_pts = [ + p.to_dict() for p in self.geometry.non_planar_vertices(tolerance) + ] + full_msg[0]['helper_geometry'] = help_pts + return full_msg + return [] if detailed else ''
+ + +
+[docs] + def check_self_intersecting(self, tolerance=0.01, raise_exception=True, + detailed=False): + """Check whether the edges of the Door intersect one another (like a bowtie). + + Note that objects that have duplicate vertices will not be considered + self-intersecting and are valid in honeybee. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. Default: 0.01, + suitable for objects in meters. + raise_exception: If True, a ValueError will be raised if the object + intersects with itself. Default: True. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + if self.geometry.is_self_intersecting: + msg = 'Door "{}" has self-intersecting edges.'.format(self.full_id) + try: # see if it is self-intersecting because of a duplicate vertex + new_geo = self.geometry.remove_duplicate_vertices(tolerance) + if not new_geo.is_self_intersecting: + return [] if detailed else '' # valid with removed dup vertex + except AssertionError: + return [] if detailed else '' # degenerate geometry + full_msg = self._validation_message( + msg, raise_exception, detailed, '000102', + error_type='Self-Intersecting Geometry') + if detailed: # add the self-intersection points to helper_geometry + help_pts = [p.to_dict() for p in self.geometry.self_intersection_points] + full_msg[0]['helper_geometry'] = help_pts + return full_msg + return [] if detailed else ''
+ + +
+[docs] + def display_dict(self): + """Get a list of DisplayFace3D dictionaries for visualizing the object.""" + base = [self._display_face(self.geometry, self.type_color)] + for shd in self.shades: + base.extend(shd.display_dict()) + return base
+ + + @property + def to(self): + """Door writer object. + + Use this method to access Writer class to write the door in different formats. + + Usage: + + .. code-block:: python + + door.to.idf(door) -> idf string. + door.to.radiance(door) -> Radiance string. + """ + return writer + +
+[docs] + def to_dict(self, abridged=False, included_prop=None, include_plane=True): + """Return Door as a dictionary. + + Args: + abridged: Boolean to note whether the extension properties of the + object (ie. materials, constructions) should be included in detail + (False) or just referenced by identifier (True). (Default: False). + included_prop: List of properties to filter keys that must be included in + output dictionary. For example ['energy'] will include 'energy' key if + available in properties to_dict. By default all the keys will be + included. To exclude all the keys from extensions use an empty list. + include_plane: Boolean to note wether the plane of the Face3D should be + included in the output. This can preserve the orientation of the + X/Y axes of the plane but is not required and can be removed to + keep the dictionary smaller. (Default: True). + """ + base = {'type': 'Door'} + base['identifier'] = self.identifier + base['display_name'] = self.display_name + base['properties'] = self.properties.to_dict(abridged, included_prop) + enforce_upper_left = True if 'energy' in base['properties'] else False + base['geometry'] = self._geometry.to_dict(include_plane, enforce_upper_left) + base['is_glass'] = self.is_glass + if isinstance(self.boundary_condition, Outdoors) and \ + 'energy' in base['properties']: + base['boundary_condition'] = self.boundary_condition.to_dict(full=True) + else: + base['boundary_condition'] = self.boundary_condition.to_dict() + self._add_shades_to_dict(base, abridged, included_prop, include_plane) + if self.user_data is not None: + base['user_data'] = self.user_data + return base
+ + + def _reset_parent_geometry(self): + """Reset parent punched_geometry in the case that the object is transformed.""" + if self.has_parent: + self._parent._punched_geometry = None + + def __copy__(self): + new_door = Door(self.identifier, self.geometry, self.boundary_condition, + self.is_glass) + new_door._display_name = self._display_name + new_door._user_data = None if self.user_data is None else self.user_data.copy() + self._duplicate_child_shades(new_door) + new_door._properties._duplicate_extension_attr(self._properties) + return new_door + + def __repr__(self): + return 'Door: %s' % self.display_name
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/extensionutil.html b/docs/_modules/honeybee/extensionutil.html new file mode 100644 index 00000000..db3949a1 --- /dev/null +++ b/docs/_modules/honeybee/extensionutil.html @@ -0,0 +1,1354 @@ + + + + + + + honeybee.extensionutil — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.extensionutil

+# coding: utf-8
+"""A series of utility functions that are useful across several honeybee extensions."""
+
+
+
+[docs] +def model_extension_dicts(data, extension_key, room_ext_dicts, face_ext_dicts, + shade_ext_dicts, aperture_ext_dicts, door_ext_dicts): + """Get all Model property dictionaries of an extension organized by geometry type. + + Note that the order in which dictionaries appear in the output lists is the + same order as the geometry objects appear when requested from the model. + For example, the shade_ext_dicts align with the model.shades. + + Args: + data: A dictionary representation of an entire honeybee-core Model. + extension_key: Text for the key of the extension (eg. "energy", "radiance"). + + Returns: + A tuple with five elements + + - room_ext_dicts: A list of Room extension property dictionaries that + align with the serialized model.rooms. + + - face_ext_dicts: A list of Face extension property dictionaries that + align with the serialized model.faces. + + - shade_ext_dicts: A list of Shade extension property dictionaries that + align with the serialized model.shades plus the model.shade_meshes. + + - aperture_ext_dicts: A list of Aperture extension property dictionaries that + align with the serialized model.apertures. + + - door_ext_dicts: A list of Door extension property dictionaries that + align with the serialized model.doors. + """ + assert data['type'] == 'Model', \ + 'Expected Model dictionary. Got {}.'.format(data['type']) + + # loop through the model dictionary using the same logic that the + # model does when you request rooms, faces, shades, apertures and doors. + if 'rooms' in data and data['rooms'] is not None: + room_extension_dicts(data['rooms'], extension_key, room_ext_dicts, + face_ext_dicts, shade_ext_dicts, aperture_ext_dicts, + door_ext_dicts) + if 'orphaned_faces' in data and data['orphaned_faces'] is not None: + face_extension_dicts(data['orphaned_faces'], extension_key, face_ext_dicts, + shade_ext_dicts, aperture_ext_dicts, door_ext_dicts) + if 'orphaned_apertures' in data and data['orphaned_apertures'] is not None: + aperture_extension_dicts(data['orphaned_apertures'], extension_key, + aperture_ext_dicts, shade_ext_dicts) + if 'orphaned_doors' in data and data['orphaned_doors'] is not None: + door_extension_dicts(data['orphaned_doors'], extension_key, door_ext_dicts, + shade_ext_dicts) + if 'orphaned_shades' in data and data['orphaned_shades'] is not None: + shade_extension_dicts(data['orphaned_shades'], extension_key, shade_ext_dicts) + if 'shade_meshes' in data and data['shade_meshes'] is not None: + shade_extension_dicts(data['shade_meshes'], extension_key, shade_ext_dicts) + + return room_ext_dicts, face_ext_dicts, shade_ext_dicts, \ + aperture_ext_dicts, door_ext_dicts
+ + + +
+[docs] +def room_extension_dicts(room_list, extension_key, room_ext_dicts, face_ext_dicts, + shade_ext_dicts, aperture_ext_dicts, door_ext_dicts): + """Get all Room property dictionaries of an extension organized by geometry type. + + Args: + room_list: A list of Room dictionaries. + extension_key: Text for the key of the extension (eg. "energy", "radiance"). + + Returns: + A tuple with five elements + + - room_ext_dicts: A list with the Room extension property dictionaries. + + - face_ext_dicts: A list with Face extension property dictionaries. + + - shade_ext_dicts: A list with Shade extension property dictionaries. + + - aperture_ext_dicts: A list with Aperture extension property dictionaries. + + - door_ext_dicts: A list with Door extension property dictionaries. + """ + for room_dict in room_list: + try: + room_ext_dicts.append(room_dict['properties'][extension_key]) + except KeyError: + room_ext_dicts.append(None) + if 'outdoor_shades' in room_dict and room_dict['outdoor_shades'] is not None: + shade_extension_dicts(room_dict['outdoor_shades'], extension_key, + shade_ext_dicts) + if 'indoor_shades' in room_dict and room_dict['indoor_shades'] is not None: + shade_extension_dicts(room_dict['indoor_shades'], extension_key, + shade_ext_dicts) + face_extension_dicts(room_dict['faces'], extension_key, face_ext_dicts, + shade_ext_dicts, aperture_ext_dicts, door_ext_dicts) + return room_ext_dicts, face_ext_dicts, shade_ext_dicts, \ + aperture_ext_dicts, door_ext_dicts
+ + + +
+[docs] +def face_extension_dicts(face_list, extension_key, face_ext_dicts, + shade_ext_dicts, aperture_ext_dicts, door_ext_dicts): + """Get all Face property dictionaries of an extension organized by geometry type. + + Args: + face_list: A list of Room dictionaries. + extension_key: Text for the key of the extension (eg. "energy", "radiance"). + + Returns: + A tuple with four elements + + - face_ext_dicts: A list with Face extension property dictionaries. + + - shade_ext_dicts: A list with Shade extension property dictionaries. + + - aperture_ext_dicts: A list with Aperture extension property dictionaries. + + - door_ext_dicts: A list with Door extension property dictionaries. + """ + for face_dict in face_list: + try: + face_ext_dicts.append(face_dict['properties'][extension_key]) + except KeyError: + face_ext_dicts.append(None) + if 'outdoor_shades' in face_dict and face_dict['outdoor_shades'] is not None: + shade_extension_dicts(face_dict['outdoor_shades'], extension_key, + shade_ext_dicts) + if 'indoor_shades' in face_dict and face_dict['indoor_shades'] is not None: + shade_extension_dicts(face_dict['indoor_shades'], extension_key, + shade_ext_dicts) + if 'apertures' in face_dict and face_dict['apertures'] is not None: + aperture_extension_dicts(face_dict['apertures'], extension_key, + aperture_ext_dicts, shade_ext_dicts) + if 'doors' in face_dict and face_dict['doors'] is not None: + door_extension_dicts(face_dict['doors'], extension_key, + door_ext_dicts, shade_ext_dicts) + return face_ext_dicts, shade_ext_dicts, aperture_ext_dicts, door_ext_dicts
+ + + +
+[docs] +def shade_extension_dicts(shade_list, extension_key, shade_ext_dicts): + """Get all Shade property dictionaries of an extension organized by geometry type. + + Args: + shade_list: A list of Shade dictionaries. + extension_key: Text for the key of the extension (eg. "energy", "radiance"). + + Returns: + shade_ext_dicts -- A list with Shade extension property dictionaries. + """ + for shd_dict in shade_list: + try: + shade_ext_dicts.append(shd_dict['properties'][extension_key]) + except KeyError: + shade_ext_dicts.append(None) + return shade_ext_dicts
+ + + +
+[docs] +def aperture_extension_dicts(aperture_list, extension_key, aperture_ext_dicts, + shade_ext_dicts): + """Get all Aperture property dictionaries of an extension organized by geometry type. + + Args: + aperture_list: A list of Aperture dictionaries. + extension_key: Text for the key of the extension (eg. "energy", "radiance"). + + Returns: + A tuple with two elements + + - aperture_ext_dicts: A list with Aperture extension property dictionaries. + + - shade_ext_dicts: A list with Shade extension property dictionaries. + """ + for ap_dict in aperture_list: + try: + aperture_ext_dicts.append(ap_dict['properties'][extension_key]) + except KeyError: + aperture_ext_dicts.append(None) + if 'outdoor_shades' in ap_dict and ap_dict['outdoor_shades'] is not None: + shade_extension_dicts(ap_dict['outdoor_shades'], extension_key, shade_ext_dicts) + if 'indoor_shades' in ap_dict and ap_dict['indoor_shades'] is not None: + shade_extension_dicts(ap_dict['indoor_shades'], extension_key, shade_ext_dicts) + return aperture_ext_dicts, shade_ext_dicts
+ + + +
+[docs] +def door_extension_dicts(door_list, extension_key, door_ext_dicts, + shade_ext_dicts): + """Get all Door property dictionaries of an extension organized by geometry type. + + Args: + door_list: A list of Door dictionaries. + extension_key: Text for the key of the extension (eg. "energy", "radiance"). + + Returns: + A tuple with two elements + + - door_ext_dicts: A list with Door extension property dictionaries. + + - shade_ext_dicts: A list with Shade extension property dictionaries. + """ + for dr_dict in door_list: + try: + door_ext_dicts.append(dr_dict['properties'][extension_key]) + except KeyError: + door_ext_dicts.append(None) + if 'outdoor_shades' in dr_dict and dr_dict['outdoor_shades'] is not None: + shade_extension_dicts(dr_dict['outdoor_shades'], extension_key, shade_ext_dicts) + if 'indoor_shades' in dr_dict and dr_dict['indoor_shades'] is not None: + shade_extension_dicts(dr_dict['indoor_shades'], extension_key, shade_ext_dicts) + return door_ext_dicts, shade_ext_dicts
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/face.html b/docs/_modules/honeybee/face.html new file mode 100644 index 00000000..6c8f72a4 --- /dev/null +++ b/docs/_modules/honeybee/face.html @@ -0,0 +1,3386 @@ + + + + + + + honeybee.face — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.face

+# coding: utf-8
+"""Honeybee Face."""
+from __future__ import division
+import math
+
+from ladybug_geometry.geometry2d import Vector2D, Point2D, Polygon2D, Mesh2D
+from ladybug_geometry.geometry3d import Vector3D, Point3D, Plane, Face3D
+from ladybug.color import Color
+
+from ._basewithshade import _BaseWithShade
+from .typing import clean_string, invalid_dict_error
+from .properties import FaceProperties
+from .facetype import face_types, get_type_from_normal, AirBoundary, Floor, RoofCeiling
+from .boundarycondition import boundary_conditions, get_bc_from_position, \
+    _BoundaryCondition, Outdoors, Surface, Ground
+from .shade import Shade
+from .aperture import Aperture
+from .door import Door
+import honeybee.boundarycondition as hbc
+import honeybee.writer.face as writer
+
+
+
+[docs] +class Face(_BaseWithShade): + """A single planar face. + + Args: + identifier: Text string for a unique Face ID. Must be < 100 characters and + not contain any spaces or special characters. + geometry: A ladybug-geometry Face3D. + type: Face type. Default varies depending on the direction that + the Face geometry is points. + RoofCeiling = pointing upward within 30 degrees + Wall = oriented vertically within +/- 60 degrees + Floor = pointing downward within 30 degrees + boundary_condition: Face boundary condition (Outdoors, Ground, etc.) + Default is Outdoors unless all vertices of the geometry lie + below the below the XY plane, in which case it will be set to Ground. + + Properties: + * identifier + * display_name + * type + * boundary_condition + * apertures + * doors + * sub_faces + * indoor_shades + * outdoor_shades + * parent + * has_parent + * has_sub_faces + * can_be_ground + * geometry + * punched_geometry + * vertices + * punched_vertices + * upper_left_vertices + * normal + * center + * area + * perimeter + * min + * max + * aperture_area + * aperture_ratio + * tilt + * altitude + * azimuth + * type_color + * bc_color + * user_data + """ + TYPES = face_types + __slots__ = ('_geometry', '_parent', '_punched_geometry', + '_apertures', '_doors', '_type', '_boundary_condition') + TYPE_COLORS = { + 'Wall': Color(230, 180, 60), + 'RoofCeiling': Color(128, 20, 20), + 'Floor': Color(128, 128, 128), + 'AirBoundary': Color(255, 255, 200, 100), + 'InteriorWall': Color(230, 215, 150), + 'InteriorRoofCeiling': Color(255, 128, 128), + 'InteriorFloor': Color(255, 128, 128), + 'InteriorAirBoundary': Color(255, 255, 200, 100) + } + BC_COLORS = { + 'Outdoors': Color(64, 180, 255), + 'Surface': Color(0, 128, 0), + 'Ground': Color(165, 82, 0), + 'Adiabatic': Color(255, 128, 128), + 'Other': Color(255, 255, 200) + } + + def __init__(self, identifier, geometry, type=None, boundary_condition=None): + """A single planar face.""" + _BaseWithShade.__init__(self, identifier) # process the identifier + + # process the geometry + assert isinstance(geometry, Face3D), \ + 'Expected ladybug_geometry Face3D. Got {}'.format(geometry) + self._geometry = geometry + self._parent = None # _parent will be set when the Face is added to a Room + # initialize with no apertures/doors (they can be assigned later) + self._punched_geometry = None + self._apertures = [] + self._doors = [] + + # initialize properties for extensions + self._properties = FaceProperties(self) + + # set face type based on normal if not provided + if type is not None: + assert type in self.TYPES, '{} is not a valid face type.'.format(type) + self._type = type or get_type_from_normal(geometry.normal) + + # set boundary condition by the relation to a zero ground plane if not provided + self.boundary_condition = boundary_condition or \ + get_bc_from_position(geometry.boundary) + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize an Face from a dictionary. + + Args: + data: A dictionary representation of an Face object. + """ + try: + # check the type of dictionary + assert data['type'] == 'Face', 'Expected Face dictionary. ' \ + 'Got {}.'.format(data['type']) + + # first serialize it with an outdoor boundary condition + face_type = face_types.by_name(data['face_type']) + face = cls(data['identifier'], Face3D.from_dict(data['geometry']), + face_type, boundary_conditions.outdoors) + if 'display_name' in data and data['display_name'] is not None: + face.display_name = data['display_name'] + if 'user_data' in data and data['user_data'] is not None: + face.user_data = data['user_data'] + + # add sub-faces and shades + if 'apertures' in data and data['apertures'] is not None: + aps = [] + for ap in data['apertures']: + try: + aps.append(Aperture.from_dict(ap)) + except Exception as e: + invalid_dict_error(ap, e) + face.add_apertures(aps) + if 'doors' in data and data['doors'] is not None: + drs = [] + for dr in data['doors']: + try: + drs.append(Door.from_dict(dr)) + except Exception as e: + invalid_dict_error(dr, e) + face.add_doors(drs) + face._recover_shades_from_dict(data) + + # get the boundary condition and assign it + try: + bc_class = getattr(hbc, data['boundary_condition']['type']) + face.boundary_condition = bc_class.from_dict(data['boundary_condition']) + except AttributeError: # extension boundary condition; default to Outdoors + pass + + # assign extension properties + if data['properties']['type'] == 'FaceProperties': + face.properties._load_extension_attr_from_dict(data['properties']) + return face + except Exception as e: + cls._from_dict_error_message(data, e)
+ + +
+[docs] + @classmethod + def from_vertices(cls, identifier, vertices, type=None, boundary_condition=None): + """Create a Face from vertices with each vertex as an iterable of 3 floats. + + Note that this method is not recommended for a face with one or more holes + since the distinction between hole vertices and boundary vertices cannot + be derived from a single list of vertices. + + Args: + identifier: Text string for a unique Face ID. Must be < 100 characters and + not contain any spaces or special characters. + vertices: A flattened list of 3 or more vertices as (x, y, z). + type: Face type object (eg. Wall, Floor). + boundary_condition: Boundary condition object (eg. Outdoors, Ground) + """ + geometry = Face3D(tuple(Point3D(*v) for v in vertices)) + return cls(identifier, geometry, type, boundary_condition)
+ + + @property + def type(self): + """Get or set an object for Type of Face (ie. Wall, Floor, Roof). + + Note that setting this property will reset extension attributes on this + Face to their default values. + """ + return self._type + + @type.setter + def type(self, value): + assert value in self.TYPES, '{} is not a valid face type.'.format(value) + if isinstance(value, AirBoundary): + assert self._apertures == [] or self._doors == [], \ + '{} cannot be assigned to a Face with Apertures or Doors.'.format(value) + self.properties.reset_to_default() # reset constructions/modifiers + self._type = value + + @property + def boundary_condition(self): + """Get or set the boundary condition of the Face. (ie. Outdoors, Ground, etc.). + """ + return self._boundary_condition + + @boundary_condition.setter + def boundary_condition(self, value): + assert isinstance(value, _BoundaryCondition), \ + 'Expected BoundaryCondition. Got {}'.format(type(value)) + if self._apertures != [] or self._doors != []: + assert isinstance(value, (Outdoors, Surface)), \ + '{} cannot be assigned to a Face with apertures or doors.'.format(value) + self._boundary_condition = value + + @property + def apertures(self): + """Get a tuple of apertures in this Face.""" + return tuple(self._apertures) + + @property + def doors(self): + """Get a tuple of doors in this Face.""" + return tuple(self._doors) + + @property + def sub_faces(self): + """Get a tuple of apertures and doors in this Face.""" + return tuple(self._apertures + self._doors) + + @property + def parent(self): + """Get the parent Room if assigned. None if not assigned.""" + return self._parent + + @property + def has_parent(self): + """Get a boolean noting whether this Face has a parent Room.""" + return self._parent is not None + + @property + def has_sub_faces(self): + """Get a boolean noting whether this Face has Apertures or Doors.""" + return not (self._apertures == [] and self._doors == []) + + @property + def can_be_ground(self): + """Get a boolean for whether this Face can support a Ground boundary condition. + """ + return self._apertures == [] and self._doors == [] \ + and not isinstance(self._type, AirBoundary) + + @property + def geometry(self): + """Get a ladybug_geometry Face3D object representing the Face. + + Note that this Face3D only represents the parent face and does not have any + holes cut in it for apertures or doors. + """ + return self._geometry + + @property + def punched_geometry(self): + """Get a Face3D object with holes cut in it for apertures and doors. + """ + if self._punched_geometry is None: + _sub_faces = tuple(sub_f.geometry for sub_f in self._apertures + self._doors) + if len(_sub_faces) != 0: + self._punched_geometry = Face3D.from_punched_geometry( + self._geometry, _sub_faces) + else: + self._punched_geometry = self._geometry + return self._punched_geometry + + @property + def vertices(self): + """Get a list of vertices for the face (in counter-clockwise order). + + Note that these vertices only represent the outer boundary of the face + and do not account for holes cut in the face by apertures or doors. + """ + return self._geometry.vertices + + @property + def punched_vertices(self): + """Get a list of vertices with holes cut in it for apertures and doors. + + Note that some vertices will be repeated since the vertices effectively + trace out a single boundary around the whole shape, winding inward to cut + out the holes. This property should be used when exporting to Radiance. + """ + return self.punched_geometry.vertices + + @property + def upper_left_vertices(self): + """Get a list of vertices starting from the upper-left corner. + + This property obeys the same rules as the vertices property but always starts + from the upper-left-most vertex. This property should be used when exporting to + EnergyPlus / OpenStudio. + """ + return self._geometry.upper_left_counter_clockwise_vertices + + @property + def normal(self): + """Get a Vector3D for the direction in which the face is pointing. + """ + return self._geometry.normal + + @property + def center(self): + """Get a ladybug_geometry Point3D for the center of the face. + + Note that this is the center of the bounding rectangle around this geometry + and not the area centroid. + """ + return self._geometry.center + + @property + def area(self): + """Get the area of the face.""" + return self._geometry.area + + @property + def perimeter(self): + """Get the perimeter of the face. This includes the length of holes in the face. + """ + return self._geometry.perimeter + + @property + def min(self): + """Get a Point3D for the minimum of the bounding box around the object.""" + all_geo = self._outdoor_shades + self._indoor_shades + all_geo.extend(self._apertures) + all_geo.extend(self._doors) + all_geo.append(self.geometry) + return self._calculate_min(all_geo) + + @property + def max(self): + """Get a Point3D for the maximum of the bounding box around the object.""" + all_geo = self._outdoor_shades + self._indoor_shades + all_geo.extend(self._apertures) + all_geo.extend(self._doors) + all_geo.append(self.geometry) + return self._calculate_max(all_geo) + + @property + def aperture_area(self): + """Get the combined area of the face's apertures.""" + return sum([ap.area for ap in self._apertures]) + + @property + def aperture_ratio(self): + """Get a number between 0 and 1 for the area ratio of the apertures to the face. + """ + return self.aperture_area / self.area + + @property + def tilt(self): + """Get the tilt of the geometry between 0 (up) and 180 (down).""" + return math.degrees(self._geometry.tilt) + + @property + def altitude(self): + """Get the altitude of the geometry between +90 (up) and -90 (down).""" + return math.degrees(self._geometry.altitude) + + @property + def azimuth(self): + """Get the azimuth of the geometry, between 0 and 360. + + Given Y-axis as North, 0 = North, 90 = East, 180 = South, 270 = West + This will be zero if the Face3D is perfectly horizontal. + """ + return math.degrees(self._geometry.azimuth) + + @property + def type_color(self): + """Get a Color to be used in visualizations by type.""" + ts = self.type.name if isinstance(self.boundary_condition, (Outdoors, Ground)) \ + else 'Interior{}'.format(self.type.name) + return self.TYPE_COLORS[ts] + + @property + def bc_color(self): + """Get a Color to be used in visualizations by boundary condition.""" + try: + return self.BC_COLORS[self.boundary_condition.name] + except KeyError: # extension boundary condition + return self.BC_COLORS['Other'] + +
+[docs] + def horizontal_orientation(self, north_vector=Vector2D(0, 1)): + """Get a number between 0 and 360 for the orientation of the face in degrees. + + 0 = North, 90 = East, 180 = South, 270 = West + + Args: + north_vector: A ladybug_geometry Vector2D for the north direction. + Default is the Y-axis (0, 1). + """ + return math.degrees( + north_vector.angle_clockwise(Vector2D(self.normal.x, self.normal.y)))
+ + +
+[docs] + def cardinal_direction(self, north_vector=Vector2D(0, 1)): + """Get text description for the cardinal direction that the face is pointing. + + Will be one of the following: ('North', 'NorthEast', 'East', 'SouthEast', + 'South', 'SouthWest', 'West', 'NorthWest'). + + Args: + north_vector: A ladybug_geometry Vector2D for the north direction. + Default is the Y-axis (0, 1). + """ + orient = self.horizontal_orientation(north_vector) + orient_text = ('North', 'NorthEast', 'East', 'SouthEast', 'South', + 'SouthWest', 'West', 'NorthWest') + angles = (22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, 337.5) + for i, ang in enumerate(angles): + if orient < ang: + return orient_text[i] + return orient_text[0]
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier of this object and child objects by inserting a prefix. + + This is particularly useful in workflows where you duplicate and edit + a starting object and then want to combine it with the original object + into one Model (like making a model of repeated rooms) since all objects + within a Model must have unique identifiers. + + Args: + prefix: Text that will be inserted at the start of this object's + (and child objects') identifier and display_name. It is recommended + that this prefix be short to avoid maxing out the 100 allowable + characters for honeybee identifiers. + """ + self._identifier = clean_string('{}_{}'.format(prefix, self.identifier)) + self.display_name = '{}_{}'.format(prefix, self.display_name) + self.properties.add_prefix(prefix) + for ap in self._apertures: + ap.add_prefix(prefix) + for dr in self._doors: + dr.add_prefix(prefix) + self._add_prefix_shades(prefix) + if isinstance(self._boundary_condition, Surface): + new_bc_objs = (clean_string('{}_{}'.format(prefix, adj_name)) for adj_name + in self._boundary_condition._boundary_condition_objects) + self._boundary_condition = Surface(new_bc_objs, False)
+ + +
+[docs] + def remove_sub_faces(self): + """Remove all apertures and doors from the face.""" + self.remove_apertures() + self.remove_doors()
+ + +
+[docs] + def remove_apertures(self): + """Remove all apertures from the face.""" + for aperture in self._apertures: + aperture._parent = None + self._apertures = [] + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def remove_doors(self): + """Remove all doors from the face.""" + for door in self._apertures: + door._parent = None + self._doors = [] + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def add_aperture(self, aperture): + """Add an Aperture to this face. + + This method does not check the co-planarity between this Face and the + Aperture or whether the Aperture has all vertices within the boundary of + this Face. To check this, the Face3D.is_sub_face() method can be used + with the Aperture and Face geometry before using this method or the + are_sub_faces_valid() method can be used afterwards. + + Args: + aperture: An Aperture to add to this face. + """ + assert isinstance(aperture, Aperture), \ + 'Expected Aperture. Got {}.'.format(type(aperture)) + self._acceptable_sub_face_check(Aperture) + aperture._parent = self + if self.normal.angle(aperture.normal) > math.pi / 2: # reversed normal + aperture._geometry = aperture._geometry.flip() + self._apertures.append(aperture) + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def add_door(self, door): + """Add a Door to this face. + + This method does not check the co-planarity between this Face and the + Door or whether the Door has all vertices within the boundary of + this Face. To check this, the Face3D.is_sub_face() method can be used + with the Door and Face geometry before using this method or the + are_sub_faces_valid() method can be used afterwards. + + Args: + door: A Door to add to this face. + """ + assert isinstance(door, Door), \ + 'Expected Door. Got {}.'.format(type(door)) + self._acceptable_sub_face_check(Door) + door._parent = self + if self.normal.angle(door.normal) > math.pi / 2: # reversed normal + door._geometry = door._geometry.flip() + self._doors.append(door) + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def add_apertures(self, apertures): + """Add a list of Apertures to this face.""" + for aperture in apertures: + self.add_aperture(aperture)
+ + +
+[docs] + def add_doors(self, doors): + """Add a list of Doors to this face.""" + for door in doors: + self.add_door(door)
+ + +
+[docs] + def add_sub_faces(self, sub_faces): + """Add a list of Apertures and/or Doors to this face.""" + for sub_f in sub_faces: + if isinstance(sub_f, Aperture): + self.add_aperture(sub_f) + else: + self.add_door(sub_f)
+ + +
+[docs] + def replace_apertures(self, apertures): + """Replace all sub-faces assigned to this Face with a new list of Apertures.""" + self.remove_sub_faces() + self.add_apertures(apertures)
+ + +
+[docs] + def set_adjacency(self, other_face, tolerance=0.01): + """Set this face adjacent to another and set the other face adjacent to this one. + + Note that this method does not verify whether the other_face geometry is + co-planar or compatible with this one so it is recommended that either the + Face3D.is_centered_adjacent() or the Face3D.is_geometrically_equivalent() + method be used with this face geometry and the other_face geometry + before using this method in order to verify these criteria. + + However, this method will use the proximity of apertures and doors within + the input tolerance to determine which of the sub faces in the other_face + are adjacent to the ones in this face. An exception will be thrown if not + all sub-faces can be matched. + + Args: + other_face: Another Face object to be set adjacent to this one. + tolerance: The minimum distance between the center of two aperture + geometries at which they are considered adjacent. Default: 0.01, + suitable for objects in meters. + + Returns: + A dictionary of adjacency information with the following keys + + - adjacent_apertures - A list of tuples with each tuple containing 2 + objects for Apertures paired in the process of solving adjacency. + + - adjacent_doors - A list of tuples with each tuple containing 2 + objects for Doors paired in the process of solving adjacency. + """ + # check the inputs and the ability of the faces to be adjacent + assert isinstance(other_face, Face), \ + 'Expected honeybee Face. Got {}.'.format(type(other_face)) + + # set the boundary conditions of the faces + self._boundary_condition = boundary_conditions.surface(other_face) + other_face._boundary_condition = boundary_conditions.surface(self) + + adj_info = {'adjacent_apertures': [], 'adjacent_doors': []} + + # set the apertures to be adjacent to one another + if len(self._apertures) != len(other_face._apertures): + msg = 'Number of apertures does not match between {} and {}.'.format( + self.display_name, other_face.display_name) + if self.has_parent and other_face.has_parent: + msg = '{} Relevant rooms: {}, {}'.format( + msg, self.parent.display_name, other_face.parent.display_name) + raise AssertionError(msg) + if len(self._apertures) > 0: + found_adjacencies = 0 + for aper_1 in self._apertures: + for aper_2 in other_face._apertures: + if aper_1.center.distance_to_point(aper_2.center) <= tolerance: + aper_1.set_adjacency(aper_2) + adj_info['adjacent_apertures'].append((aper_1, aper_2)) + found_adjacencies += 1 + break + if len(self._apertures) != found_adjacencies: + msg = 'Not all apertures of {} were found to be adjacent to ' \ + 'apertures in {}.'.format(self.display_name, other_face.display_name) + if self.has_parent and other_face.has_parent: + msg = '{} Relevant rooms: {}, {}'.format( + msg, self.parent.display_name, other_face.parent.display_name) + raise AssertionError(msg) + + # set the doors to be adjacent to one another + assert len(self._doors) == len(other_face._doors), \ + 'Number of doors does not match between {} and {}.'.format( + self.display_name, other_face.display_name) + if len(self._doors) > 0: + found_adjacencies = 0 + for door_1 in self._doors: + for door_2 in other_face._doors: + if door_1.center.distance_to_point(door_2.center) <= tolerance: + door_1.set_adjacency(door_2) + adj_info['adjacent_doors'].append((door_1, door_2)) + found_adjacencies += 1 + break + if len(self._doors) != found_adjacencies: + msg = 'Not all doors of {} were found to be adjacent to ' \ + 'doors in {}.'.format(self.display_name, other_face.display_name) + if self.has_parent and other_face.has_parent: + msg = '{} Relevant rooms: {}, {}'.format( + msg, self.parent.display_name, other_face.parent.display_name) + raise AssertionError(msg) + + return adj_info
+ + +
+[docs] + def rectangularize_apertures( + self, subdivision_distance=None, max_separation=None, + merge_all=False, tolerance=0.01, angle_tolerance=1.0): + """Convert all Apertures on this Face to be rectangular. + + This is useful when exporting to simulation engines that only accept + rectangular window geometry. This method will always result ing Rooms where + all Apertures are rectangular. However, if the subdivision_distance is not + set, some Apertures may extend past the parent Face or may collide with + one another. + + Args: + subdivision_distance: A number for the resolution at which the + non-rectangular Apertures will be subdivided into smaller + rectangular units. Specifying a number here ensures that the + resulting rectangular Apertures do not extend past the parent + Face or collide with one another. If None, all non-rectangular + Apertures will be rectangularized by taking the bounding rectangle + around the Aperture. (Default: None). + max_separation: A number for the maximum distance between non-rectangular + Apertures at which point the Apertures will be merged into a single + rectangular geometry. This is often helpful when there are several + triangular Apertures that together make a rectangle when they are + merged across their frames. In such cases, this max_separation + should be set to a value that is slightly larger than the window frame. + If None, no merging of Apertures will happen before they are + converted to rectangles. (Default: None). + merge_all: Boolean to note whether all apertures should be merged before + they are rectangularized. If False, only non-rectangular apertures + will be merged before rectangularization. Note that this argument + has no effect when the max_separation is None. (Default: False). + tolerance: The maximum difference between point values for them to be + considered equivalent. (Default: 0.01, suitable for objects in meters). + angle_tolerance: The max angle in degrees that the corners of the + rectangle can differ from a right angle before it is not + considered a rectangle. (Default: 1). + + Returns: + True if the Apertures were changed. False if they were unchanged. + """ + # sort the rectangular and non-rectangular apertures + apertures = self._apertures + if len(apertures) == 0: + return False + tol, ang_tol = tolerance, math.radians(angle_tolerance) + rect_aps, non_rect_aps, non_rect_geos = [], [], [] + for aperture in apertures: + try: + clean_geo = aperture.geometry.remove_colinear_vertices(tol) + except AssertionError: # degenerate Aperture to be ignored + continue + if max_separation is None or not merge_all: + if clean_geo.polygon2d.is_rectangle(ang_tol): + rect_aps.append(aperture) + else: + non_rect_aps.append(aperture) + non_rect_geos.append(clean_geo) + else: + non_rect_aps.append(aperture) + non_rect_geos.append(clean_geo) + if not non_rect_geos: # nothing to be rectangularized + return False + + # reset boundary conditions to outdoors so new apertures can be added + if not isinstance(self.boundary_condition, Outdoors): + self.boundary_condition = boundary_conditions.outdoors + for ap in rect_aps: + ap.boundary_condition = boundary_conditions.outdoors + edits_occurred = False + + # try to merge the non-rectangular apertures if a max_separation is specified + ref_plane = self._reference_plane(ang_tol) + if max_separation is not None: + if merge_all or (not merge_all and len(non_rect_geos) > 1): + edits_occurred = True + if max_separation <= tol: # just join the Apertures at the tolerance + non_rect_geos = Face3D.join_coplanar_faces(non_rect_geos, tol) + else: # join the Apertures using the max_separation + # get polygons for the faces that all lie within the same plane + face_polys = [] + for fg in non_rect_geos: + verts2d = tuple(ref_plane.xyz_to_xy(_v) for _v in fg.boundary) + face_polys.append(Polygon2D(verts2d)) + if fg.has_holes: + for hole in fg.holes: + verts2d = tuple(ref_plane.xyz_to_xy(_v) for _v in hole) + face_polys.append(Polygon2D(verts2d)) + # get the joined boundaries around the Polygon2D + joined_bounds = Polygon2D.gap_crossing_boundary( + face_polys, max_separation, tolerance) + # convert the boundary polygons back to Face3D + if len(joined_bounds) == 1: # can be represented with a single Face3D + verts3d = tuple(ref_plane.xy_to_xyz(_v) for _v in joined_bounds[0]) + non_rect_geos = [Face3D(verts3d, plane=ref_plane)] + else: # need to separate holes from distinct Face3Ds + bound_faces = [] + for poly in joined_bounds: + verts3d = tuple(ref_plane.xy_to_xyz(_v) for _v in poly) + bound_faces.append(Face3D(verts3d, plane=ref_plane)) + non_rect_geos = Face3D.merge_faces_to_holes(bound_faces, tolerance) + clean_aps = [] + for ap_geo in non_rect_geos: + try: + clean_aps.append(ap_geo.remove_colinear_vertices(tol)) + except AssertionError: # degenerate Aperture to be ignored + continue + non_rect_geos = clean_aps + + # convert the remaining Aperture geometries to rectangles + if subdivision_distance is None: # just take the bounding rectangle + edits_occurred = True + # get the bounding rectangle around all of the geometries + ap_geos = [] + for ap_geo in non_rect_geos: + if ap_geo.polygon2d.is_rectangle(ang_tol): + ap_geos.append(ap_geo) # catch rectangles found in merging + continue + geo_2d = Polygon2D([ref_plane.xyz_to_xy(v) for v in ap_geo.vertices]) + g_min, g_max = geo_2d.min, geo_2d.max + base, hgt = g_max.x - g_min.x, g_max.y - g_min.y + bound_poly = Polygon2D.from_rectangle(g_min, Vector2D(0, 1), base, hgt) + geo_3d = Face3D([ref_plane.xy_to_xyz(v) for v in bound_poly.vertices]) + ap_geos.append(geo_3d) + non_rect_geos = ap_geos + + # create Aperture objects from all of the merged geometries + if not edits_occurred: + new_aps = non_rect_aps + else: + new_aps = [] + for i, ap_face in enumerate(non_rect_geos): + exist_ap = None + for old_ap in non_rect_aps: + if old_ap.center.is_equivalent(ap_face.center, tolerance): + exist_ap = old_ap + break + if exist_ap is None: # could not be matched; just make a new aperture + new_ap = Aperture('{}_RG{}'.format(self.identifier, i), ap_face) + else: + new_ap = Aperture(exist_ap.identifier, ap_face, + is_operable=exist_ap.is_operable) + new_ap.display_name = '{}_{}'.format(exist_ap.display_name, i) + new_aps.append(new_ap) + + # we can just add the apertures if there's no subdivision going on + if subdivision_distance is None: + # remove any Apertures that are overlapping + all_aps = rect_aps + new_aps + all_aps = self._remove_overlapping_sub_faces(all_aps, tolerance) + self.remove_apertures() + self.add_apertures(all_aps) + return True + + # if distance is provided, subdivide the apertures into strips + new_ap_objs = [] + for ap_obj in new_aps: + ap_geo = ap_obj.geometry + if ap_geo.polygon2d.is_rectangle(ang_tol): + new_ap_objs.append(ap_obj) # catch rectangles found in merging + continue + # create a mesh grid over the Aperture in the reference plane + geo_2d = Polygon2D([ref_plane.xyz_to_xy(v) for v in ap_geo.vertices]) + try: + grid = Mesh2D.from_polygon_grid( + geo_2d, subdivision_distance, subdivision_distance, False) + except AssertionError: # Aperture smaller than resolution; ignore + continue + + # group face by y value. All the rows will be merged together + vertices = grid.vertices + groups = {} + start_y = None + last_y = vertices[grid.faces[0][0]].y + for i, face in enumerate(grid.faces): + min_2d = vertices[face[0]] + for xy in groups: + if abs(min_2d.x - xy[0]) < tolerance and \ + abs(min_2d.y - last_y) < tolerance: + groups[(xy[0], start_y)].append(face) + break + else: + start_y = min_2d.y + groups[(min_2d.x, start_y)] = [face] + last_y = vertices[face[3]].y + + # get the max and min of each group + sorted_groups = [] + for group in groups.values(): + # find min_2d and max_2d for each group + min_2d = vertices[group[0][0]] + max_2d = vertices[group[-1][2]] + sorted_groups.append({'min': min_2d, 'max': max_2d}) + + def _get_last_row(groups, start=0): + """An internal function to return the index for the last row that can be + merged with the start row that is passed to this function. + + This function compares the min and max x and y values for each row to see + if they can be merged into a rectangle. + """ + for count, group in enumerate(groups[start:]): + next_group = groups[count + start + 1] + if abs(group['min'].y - next_group['min'].y) <= tolerance \ + and abs(group['max'].y - next_group['max'].y) <= tolerance \ + and abs(next_group['min'].x - group['max'].x) <= tolerance: + continue + else: + return start + count + + return start + count + 1 + + # merge the rows if they have the same number of grid cells + sorted_groups.sort(key=lambda x: x['min'].x) + merged_groups = [] + start_row = 0 + last_row = -1 + while last_row < len(sorted_groups): + try: + last_row = _get_last_row(sorted_groups, start=start_row) + except IndexError: + merged_groups.append( + { + 'min': sorted_groups[start_row]['min'], + 'max': sorted_groups[len(sorted_groups) - 1]['max'] + } + ) + break + else: + merged_groups.append( + { + 'min': sorted_groups[start_row]['min'], + 'max': sorted_groups[last_row]['max'] + } + ) + if last_row == start_row: + # the row was not grouped with anything else + start_row += 1 + else: + start_row = last_row + 1 + + # convert the groups into rectangular strips + for i, group in enumerate(merged_groups): + min_2d = group['min'] + max_2d = group['max'] + base, hgt = max_2d.x - min_2d.x, max_2d.y - min_2d.y + bound_poly = Polygon2D.from_rectangle(min_2d, Vector2D(0, 1), base, hgt) + geo_3d = Face3D([ref_plane.xy_to_xyz(v) for v in bound_poly.vertices]) + new_ap = Aperture( + '{}_Glz{}'.format(ap_obj.identifier, i), + geo_3d, is_operable=ap_obj.is_operable) + new_ap.display_name = '{}_{}'.format(ap_obj.display_name, i) + new_ap_objs.append(new_ap) + + # replace the apertures with the new ones + self.remove_apertures() + self.add_apertures(rect_aps + new_ap_objs) + return True
+ + + def _reference_plane(self, angle_tolerance): + """Get a Plane for this Face geometry derived from the Face3D plane. + + This will be oriented with the plane Y-Axis either aligned with the + World Z or World Y, which is helpful in rectangularization. + + Args: + angle_tolerance: The max angle in radians that Face normal can differ + from the World Z before the Face is treated as being in the + World XY plane. + """ + parent_llc = self.geometry.lower_left_corner + rel_plane = self.geometry.plane + vertical = Vector3D(0, 0, 1) + vert_ang = rel_plane.n.angle(vertical) + if vert_ang <= angle_tolerance or vert_ang >= math.pi - angle_tolerance: + proj_x = Vector3D(1, 0, 0) + else: + proj_y = vertical.project(rel_plane.n) + proj_x = proj_y.rotate(rel_plane.n, math.pi / -2) + + ref_plane = Plane(rel_plane.n, parent_llc, proj_x) + return ref_plane + +
+[docs] + def offset_aperture_edges(self, offset_distance, tolerance=0.01): + """Offset the edges of all apertures by a certain distance. + + This is useful for translating between interfaces that expect the window + frame to be included within or excluded from the geometry of the Aperture. + + Note that this operation can often create Apertures that collide with + one another or extend past the parent Face. So it may be desirable + to run the fix_invalid_sub_faces after using this method. + + Args: + offset_distance: Distance with which the edges of each Aperture will + be offset from the original geometry. Positive values will + offset the geometry outwards and negative values will offset the + geometries inwards. + tolerance: The minimum difference between point values for them to be + considered the distinct. (Default: 0.01, suitable for objects + in meters). + """ + # convert the apertures to polygons and offset them + new_apertures = [] + prim_pl = self.geometry.plane + for ap in self.apertures: + try: + verts_2d = tuple(prim_pl.xyz_to_xy(pt) for pt in ap.geometry.boundary) + poly = Polygon2D(verts_2d).remove_colinear_vertices(tolerance) + off_poly = poly.offset(-offset_distance, True) + if off_poly is not None: + verts_3d = tuple(prim_pl.xy_to_xyz(pt) for pt in off_poly) + new_ap = ap.duplicate() + new_ap._geometry = Face3D(verts_3d, prim_pl) + new_apertures.append(new_ap) + else: + new_apertures.append(ap) + except AssertionError: # degenerate geometry to ignore + new_apertures.append(ap) + # assign the new apertures + self.remove_apertures() + self.add_apertures(new_apertures)
+ + +
+[docs] + def merge_neighboring_sub_faces(self, merge_distance=0.05, tolerance=0.01): + """Merge neighboring Apertures and/or Doors on this Face together. + + This method is particularly useful for simplifying Apertures in concave + Faces since trying to simplify such Apertures down to a ratio will + produce a triangulated result that is not particularly clean. + + Args: + merge_distance: Distance between Apertures and/or Doors at which point they + will be merged into a single Aperture. When this value is less than + or equal to the tolerance, apertures will only be merged if they + touch one another. (Default: 0.05, suitable for objects in meters). + tolerance: The minimum difference between point values for them to be + considered the distinct. (Default: 0.01, suitable for objects + in meters). + """ + # first, check that there are Apertures to e merged + sub_faces = self.sub_faces + if len(sub_faces) <= 1: # no apertures to be merged + return + + # collect the sub-face geometries as polygons in the face plane + clean_polys, original_objs, original_area = [], [], 0 + prim_pl = self.geometry.plane + for sub_f in sub_faces: + try: + verts_2d = tuple(prim_pl.xyz_to_xy(pt) for pt in sub_f.geometry.boundary) + poly = Polygon2D(verts_2d).remove_colinear_vertices(tolerance) + clean_polys.append(poly) + original_area += poly.area + original_objs.append(sub_f) + except AssertionError: # degenerate geometry to ignore + pass + original_polys = clean_polys[:] + + # join the polygons together + if merge_distance <= tolerance: # only join the polygons that touch one another + clean_polys = Polygon2D.joined_intersected_boundary(clean_polys, tolerance) + else: + clean_polys = Polygon2D.gap_crossing_boundary( + clean_polys, merge_distance, tolerance) + + # assuming that the operations have edited the polygons, create new sub-faces + new_area = sum(p.area for p in clean_polys) + area_diff = abs(original_area - new_area) + if len(clean_polys) != len(original_polys) or area_diff > tolerance: + clean_polys = [poly.remove_colinear_vertices(tolerance) + for poly in clean_polys] + self.remove_sub_faces() + for i, n_poly in enumerate(clean_polys): + new_geo = Face3D([prim_pl.xy_to_xyz(pt) for pt in n_poly], prim_pl) + for o_poly, o_obj in zip(original_polys, original_objs): + if n_poly.is_point_inside_bound_rect(o_poly.center): + orig_obj = o_obj + break + else: # could not be matched with any original object + orig_obj = None + if orig_obj is None: + new_ap = Aperture('{}_{}'.format(self.identifier, i), new_geo) + self.add_aperture(new_ap) + elif isinstance(orig_obj, Aperture): + new_ap = orig_obj.duplicate() + new_ap._geometry = new_geo + self.add_aperture(new_ap) + elif isinstance(orig_obj, Door): + new_door = orig_obj.duplicate() + new_door._geometry = new_geo + self.add_door(new_door)
+ + +
+[docs] + def fix_invalid_sub_faces( + self, trim_with_parent=True, union_overlaps=True, + offset_distance=0.05, tolerance=0.01): + """Fix invalid Apertures and Doors on this face by performing two operations. + + First, sub-faces that extend past their parent Face are trimmed with the + parent and will have their edges offset towards the inside of the Face. + Second, any sub-faces that overlap or touch one another will be unioned + into a single Aperture or Door. + + Args: + trim_with_parent: Boolean to note whether the fixing operation should + check all sub-faces that extend past their parent and trim + them, offsetting them towards the inside of the Face. (Default: True). + union_overlaps: Boolean to note whether the fixing operation should + check all sub-faces that overlap with one another and union any + sub-faces together that overlap. (Default: True). + offset_distance: Distance from the edge of the parent Face that the + sub-faces will be offset to in order to make them valid. This + should be larger than the tolerance. (Default: 0.05, suitable for + objects in meters). + tolerance: The minimum difference between point values for them to be + considered the distinct. (Default: 0.01, suitable for objects + in meters). + """ + # collect the sub-face geometries as polygons in the face plane + clean_polys, original_objs, original_area = [], [], 0 + prim_pl = self.geometry.plane + for sub_f in self.sub_faces: + try: + verts_2d = tuple(prim_pl.xyz_to_xy(pt) for pt in sub_f.geometry.boundary) + poly = Polygon2D(verts_2d).remove_colinear_vertices(tolerance) + clean_polys.append(poly) + original_area += poly.area + original_objs.append(sub_f) + except AssertionError: # degenerate geometry to ignore + pass + original_polys = clean_polys[:] + + # trim objects with the parent polygon if they extend past it + if trim_with_parent: + face_3d = self.geometry + verts2d = tuple(prim_pl.xyz_to_xy(pt) for pt in face_3d.boundary) + parent_poly, parent_holes = Polygon2D(verts2d), None + if face_3d.has_holes: + parent_holes = tuple( + Polygon2D(prim_pl.xyz_to_xy(pt) for pt in hole) + for hole in face_3d.holes + ) + # loop through the polygons and offset them if they are not correctly bounded + new_polygons = [] + for polygon in clean_polys: + if not self._is_sub_polygon(polygon, parent_poly, parent_holes): + # find the boolean intersection of the polygon with the room + sub_face = Face3D([prim_pl.xy_to_xyz(pt) for pt in polygon]) + bool_int = Face3D.coplanar_intersection( + face_3d, sub_face, tolerance, math.radians(1)) + if bool_int is None: # sub-face completely outside parent + continue + # offset the result of the boolean intersection from the edge + parent_edges = face_3d.boundary_segments if face_3d.holes is None \ + else face_3d.boundary_segments + \ + tuple(seg for hole in face_3d.hole_segments for seg in hole) + for new_f in bool_int: + new_pts_2d = [] + for pt in new_f.boundary: + for edge in parent_edges: + close_pt = edge.closest_point(pt) + if pt.distance_to_point(close_pt) < offset_distance: + move_vec = edge.v.rotate(prim_pl.n, math.pi / 2) + move_vec = move_vec.normalize() * offset_distance + pt = pt.move(move_vec) + new_pts_2d.append(prim_pl.xyz_to_xy(pt)) + new_polygons.append(Polygon2D(new_pts_2d)) + else: + new_polygons.append(polygon) + clean_polys = new_polygons + + # union overlaps and merge sub-faces that are touching + if union_overlaps: + grouped_polys = Polygon2D.group_by_overlap(clean_polys, tolerance) + # union any of the polygons that overlap + if not all(len(g) == 1 for g in grouped_polys): + clean_polys = [] + for p_group in grouped_polys: + if len(p_group) == 1: + clean_polys.append(p_group[0]) + else: + union_poly = Polygon2D.boolean_union_all(p_group, tolerance) + for new_poly in union_poly: + clean_polys.append( + new_poly.remove_colinear_vertices(tolerance)) + # join the polygons that touch one another + clean_polys = Polygon2D.joined_intersected_boundary(clean_polys, tolerance) + + # assuming that the operations have edited the polygons, create new sub-faces + new_area = sum(p.area for p in clean_polys) + area_diff = abs(original_area - new_area) + if len(clean_polys) != len(original_polys) or area_diff > tolerance: + self.remove_sub_faces() + for i, n_poly in enumerate(clean_polys): + new_geo = Face3D([prim_pl.xy_to_xyz(pt) for pt in n_poly], prim_pl) + for o_poly, o_obj in zip(original_polys, original_objs): + if n_poly.is_point_inside_bound_rect(o_poly.center): + orig_obj = o_obj + break + else: # could not be matched with any original object + orig_obj = None + if orig_obj is None: + new_ap = Aperture('{}_{}'.format(self.identifier, i), new_geo) + self.add_aperture(new_ap) + elif isinstance(orig_obj, Aperture): + new_ap = orig_obj.duplicate() + new_ap._geometry = new_geo + self.add_aperture(new_ap) + elif isinstance(orig_obj, Door): + new_door = orig_obj.duplicate() + new_door._geometry = new_geo + self.add_door(new_door)
+ + +
+[docs] + def apertures_by_ratio(self, ratio, tolerance=0.01, rect_split=True): + """Add apertures to this Face given a ratio of aperture area to face area. + + Note that this method removes any existing apertures and doors on the Face. + This method attempts to generate as few apertures as necessary to meet the ratio. + + Args: + ratio: A number between 0 and 1 (but not perfectly equal to 1) + for the desired ratio between aperture area and face area. + tolerance: The maximum difference between point values for them to be + considered the same. This is used in the event that this face is + concave and an attempt to subdivide the face into a rectangle is + made. It does not affect the ability to produce apertures for + convex Faces. Default: 0.01, suitable for objects in meters. + rect_split: Boolean to note whether rectangular portions of base Face + should be extracted before scaling them to create apertures. For + gabled geometries, the resulting apertures will consist of one + rectangle and one triangle, which can often look more realistic + and is a better input for engines like EnergyPlus that cannot + model windows with more than 4 vertices. However, if a single + pentagonal window is desired for a gabled shape, this input can + be set to False to produce such a result. + + Usage: + + .. code-block:: python + + room = Room.from_box(3.0, 6.0, 3.2, 180) + room.faces[1].apertures_by_ratio(0.4) + """ + assert 0 <= ratio < 1, 'Ratio must be between 0 and 1. Got {}'.format(ratio) + self._acceptable_sub_face_check(Aperture) + self.remove_sub_faces() + if ratio == 0: + return + try: + geo = self._geometry.remove_colinear_vertices(tolerance) + except AssertionError: # degenerate face that should not have apertures + return + if rect_split: + ap_faces = geo.sub_faces_by_ratio_rectangle(ratio, tolerance) + else: + ap_faces = geo.sub_faces_by_ratio(ratio) + for i, ap_face in enumerate(ap_faces): + aperture = Aperture('{}_Glz{}'.format(self.identifier, i), ap_face) + self.add_aperture(aperture)
+ + +
+[docs] + def apertures_by_ratio_rectangle(self, ratio, aperture_height, sill_height, + horizontal_separation, vertical_separation=0, + tolerance=0.01): + """Add apertures to this face given a ratio of aperture area to face area. + + Note that this method removes any existing apertures on the Face. + + This function is virtually equivalent to the apertures_by_ratio method but + any rectangular portions of this face will produce customizable rectangular + apertures using the other inputs (aperture_height, sill_height, + horizontal_separation, vertical_separation). + + Args: + ratio: A number between 0 and 0.95 for the ratio between the area of + the apertures and the area of this face. + aperture_height: A number for the target height of the output apertures. + Note that, if the ratio is too large for the height, the ratio will + take precedence and the actual aperture_height will be larger + than this value. + sill_height: A number for the target height above the bottom edge of + the rectangle to start the apertures. Note that, if the + ratio is too large for the height, the ratio will take precedence + and the sill_height will be smaller than this value. + horizontal_separation: A number for the target separation between + individual aperture center lines. If this number is larger than + the parent rectangle base, only one aperture will be produced. + vertical_separation: An optional number to create a single vertical + separation between top and bottom apertures. The default is + 0 for no separation. + tolerance: The maximum difference between point values for them to be + considered a part of a rectangle. Default: 0.01, suitable for + objects in meters. + + Usage: + + .. code-block:: python + + room = Room.from_box(3.0, 6.0, 3.2, 180) + room.faces[1].apertures_by_ratio_rectangle(0.4, 2, 0.9, 3) + """ + assert 0 <= ratio <= 0.95, \ + 'Ratio must be between 0 and 0.95. Got {}'.format(ratio) + self._acceptable_sub_face_check(Aperture) + self.remove_sub_faces() + if ratio == 0: + return + try: + geo = self._geometry.remove_colinear_vertices(tolerance) + except AssertionError: # degenerate face that should not have apertures + return + ap_faces = geo.sub_faces_by_ratio_sub_rectangle( + ratio, aperture_height, sill_height, horizontal_separation, + vertical_separation, tolerance) + for i, ap_face in enumerate(ap_faces): + aperture = Aperture('{}_Glz{}'.format(self.identifier, i), ap_face) + self.add_aperture(aperture)
+ + +
+[docs] + def apertures_by_ratio_gridded(self, ratio, x_dim, y_dim=None, tolerance=0.01): + """Add apertures to this face given a ratio of aperture area to face area. + + Note that this method removes any existing apertures on the Face. + + Apertures will be arranged in a grid derived from this face's plane. + Because the x_dim and y_dim refer to dimensions within the X and Y + coordinate system of this faces's plane, rotating this plane will + result in rotated grid cells. This is particularly useful for generating + skylights based on a glazing ratio. + + If the x_dim and/or y_dim are too large for this face, this method will + return essentially the same result as the apertures_by_ratio method. + + Args: + ratio: A number between 0 and 1 for the ratio between the area of + the apertures and the area of this face. + x_dim: The x dimension of the grid cells as a number. + y_dim: The y dimension of the grid cells as a number. Default is None, + which will assume the same cell dimension for y as is set for x. + tolerance: The maximum difference between point values for them to be + considered a part of a rectangle. Default: 0.01, suitable for + objects in meters. + + Usage: + + .. code-block:: python + + room = Room.from_box(3.0, 6.0, 3.2, 180) + room.faces[-1].apertures_by_ratio_gridded(0.05, 3) + """ + assert 0 <= ratio < 1, 'Ratio must be between 0 and 1. Got {}'.format(ratio) + self._acceptable_sub_face_check(Aperture) + self.remove_sub_faces() + if ratio == 0: + return + try: + geo = self._geometry.remove_colinear_vertices(tolerance) + except AssertionError: # degenerate face that should not have apertures + return + ap_faces = geo.sub_faces_by_ratio_gridded(ratio, x_dim, y_dim) + for i, ap_face in enumerate(ap_faces): + aperture = Aperture('{}_Glz{}'.format(self.identifier, i), ap_face) + self.add_aperture(aperture)
+ + +
+[docs] + def apertures_by_width_height_rectangle(self, aperture_height, aperture_width, + sill_height, horizontal_separation, + tolerance=0.01): + """Add repeating apertures to this face given the aperture width and height. + + Note that this method removes any existing apertures on the Face. + + Note that this method will effectively fill any rectangular portions of + this Face with apertures at the specified width, height and separation. + If no rectangular portion of this Face can be identified, no apertures + will be added. + + Args: + aperture_height: A number for the target height of the apertures. + aperture_width: A number for the target width of the apertures. + sill_height: A number for the target height above the bottom edge of + the rectangle to start the apertures. If the aperture_height + is too large for the sill_height to fit within the rectangle, + the aperture_height will take precedence. + horizontal_separation: A number for the target separation between + individual apertures center lines. If this number is larger than + the parent rectangle base, only one aperture will be produced. + tolerance: The maximum difference between point values for them to be + considered a part of a rectangle. Default: 0.01, suitable for + objects in meters. + + Usage: + + .. code-block:: python + + room = Room.from_box(5.0, 10.0, 3.2, 180) + room.faces[1].apertures_by_width_height_rectangle(1.5, 2, 0.8, 2.5) + """ + assert horizontal_separation > 0, \ + 'horizontal_separation must be above 0. Got {}'.format(horizontal_separation) + if aperture_height <= 0 or aperture_width <= 0: + return + self._acceptable_sub_face_check(Aperture) + self.remove_sub_faces() + try: + geo = self._geometry.remove_colinear_vertices(tolerance) + except AssertionError: # degenerate face that should not have apertures + return + ap_faces = geo.sub_faces_by_dimension_rectangle( + aperture_height, aperture_width, sill_height, horizontal_separation, + tolerance) + for i, ap_face in enumerate(ap_faces): + aperture = Aperture('{}_Glz{}'.format(self.identifier, i), ap_face) + self.add_aperture(aperture)
+ + +
+[docs] + def aperture_by_width_height(self, width, height, sill_height=1, + aperture_identifier=None): + """Add a single rectangular aperture to the center of this Face. + + A rectangular window with the input width and height will always be added + by this method regardless of whether this parent Face contains a recognizable + rectangular portion or not. Furthermore, this method preserves any existing + apertures on the Face. + + While the resulting aperture will always be in the plane of this Face, + this method will not check to ensure that the aperture has all of its + vertices completely within the boundary of this Face or that it does not + intersect with other apertures in the Face. The are_sub_faces_valid() + method can be used afterwards to check this. + + Args: + width: A number for the Aperture width. + height: A number for the Aperture height. + sill_height: A number for the sill height. (Default: 1). + aperture_identifier: Optional string for the aperture identifier. + If None, the default will follow the convention + "[face_identifier]_Glz[count]" where [count] is one more than + the current number of apertures in the face. + + Returns: + The new Aperture object that has been generated. + + Usage: + + .. code-block:: python + + room = Room.from_box(3.0, 6.0, 3.2, 180) + room[1].aperture_by_width_height(2, 2, .7) # aperture in front + room[2].aperture_by_width_height(4, 1.5, .5) # aperture on right + room[2].aperture_by_width_height(4, 0.5, 2.2) # aperture on right + """ + # Perform checks + if width <= 0 or height <= 0: + return + self._acceptable_sub_face_check(Aperture) + # Generate the aperture geometry + origin = self._geometry.lower_left_counter_clockwise_vertices[0] + face_plane = Plane(self._geometry.plane.n, origin) + if face_plane.y.z < 0: + face_plane = face_plane.rotate(face_plane.n, math.pi, face_plane.o) + center2d = face_plane.xyz_to_xy(self._geometry.center) + x_dist = width / 2 + lower_left = Point2D(center2d.x - x_dist, sill_height) + lower_right = Point2D(center2d.x + x_dist, sill_height) + upper_right = Point2D(center2d.x + x_dist, sill_height + height) + upper_left = Point2D(center2d.x - x_dist, sill_height + height) + ap_verts2d = (lower_left, lower_right, upper_right, upper_left) + ap_verts3d = tuple(face_plane.xy_to_xyz(pt) for pt in ap_verts2d) + ap_face = Face3D(ap_verts3d, self._geometry.plane) + if self.normal.angle(ap_face.normal) > math.pi / 2: # reversed normal + ap_face = ap_face.flip() + + # Create the aperture and add it to this Face + identifier = aperture_identifier or \ + '{}_Glz{}'.format(self.identifier, len(self.apertures)) + aperture = Aperture(identifier, ap_face) + self.add_aperture(aperture) + return aperture
+ + +
+[docs] + def overhang(self, depth, angle=0, indoor=False, tolerance=0.01, base_name=None): + """Add an overhang to this Face. + + Args: + depth: A number for the overhang depth. + angle: A number for the for an angle to rotate the overhang in degrees. + Positive numbers indicate a downward rotation while negative numbers + indicate an upward rotation. Default is 0 for no rotation. + indoor: Boolean for whether the overhang should be generated facing the + opposite direction of the aperture normal (typically meaning + indoor geometry). Default: False. + tolerance: An optional value to not add the overhang if it has a length less + than the tolerance. Default: 0.01, suitable for objects in meters. + base_name: Optional base identifier for the shade objects. If None, + the default is InOverhang or OutOverhang depending on whether + indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + if base_name is None: + base_name = 'InOverhang' if indoor else 'OutOverhang' + return self.louvers_by_count(1, depth, angle=angle, indoor=indoor, + tolerance=tolerance, base_name=base_name)
+ + +
+[docs] + def louvers_by_count(self, louver_count, depth, offset=0, angle=0, + contour_vector=Vector2D(0, 1), flip_start_side=False, + indoor=False, tolerance=0.01, base_name=None): + """Add a series of louvered Shade objects over this Face. + + Args: + louver_count: A positive integer for the number of louvers to generate. + depth: A number for the depth to extrude the louvers. + offset: A number for the distance to louvers from this Face. + Default is 0 for no offset. + angle: A number for the for an angle to rotate the louvers in degrees. + Positive numbers indicate a downward rotation while negative numbers + indicate an upward rotation. Default is 0 for no rotation. + contour_vector: A Vector2D for the direction along which contours + are generated. This 2D vector will be interpreted into a 3D vector + within the plane of this Face. (0, 1) will usually generate + horizontal contours in 3D space, (1, 0) will generate vertical + contours, and (1, 1) will generate diagonal contours. Default: (0, 1). + flip_start_side: Boolean to note whether the side the louvers start from + should be flipped. Default is False to have louvers on top or right. + Setting to True will start contours on the bottom or left. + indoor: Boolean for whether louvers should be generated facing the + opposite direction of the Face normal (typically meaning + indoor geometry). Default: False. + tolerance: An optional value to remove any louvers with a length less + than the tolerance. Default: 0.01, suitable for objects in meters. + base_name: Optional base identifier for the shade objects. If None, + the default is InShd or OutShd depending on whether indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + assert louver_count > 0, 'louver_count must be greater than 0.' + angle = math.radians(angle) + louvers = [] + face_geo = self.geometry if indoor is False else self.geometry.flip() + if base_name is None: + shd_name_base = '{}_InShd{}' if indoor else '{}_OutShd{}' + else: + shd_name_base = '{}_' + str(base_name) + '{}' + shade_faces = face_geo.contour_fins_by_number( + louver_count, depth, offset, angle, + contour_vector, flip_start_side, tolerance) + for i, shade_geo in enumerate(shade_faces): + louvers.append(Shade(shd_name_base.format(self.identifier, i), shade_geo)) + if indoor: + self.add_indoor_shades(louvers) + else: + self.add_outdoor_shades(louvers) + return louvers
+ + +
+[docs] + def louvers_by_distance_between( + self, distance, depth, offset=0, angle=0, contour_vector=Vector2D(0, 1), + flip_start_side=False, indoor=False, tolerance=0.01, max_count=None, + base_name=None): + """Add a series of louvered Shade objects over this Face. + + Args: + distance: A number for the approximate distance between each louver. + depth: A number for the depth to extrude the louvers. + offset: A number for the distance to louvers from this Face. + Default is 0 for no offset. + angle: A number for the for an angle to rotate the louvers in degrees. + Positive numbers indicate a downward rotation while negative numbers + indicate an upward rotation. Default is 0 for no rotation. + contour_vector: A Vector2D for the direction along which contours + are generated. This 2D vector will be interpreted into a 3D vector + within the plane of this Face. (0, 1) will usually generate + horizontal contours in 3D space, (1, 0) will generate vertical + contours, and (1, 1) will generate diagonal contours. Default: (0, 1). + flip_start_side: Boolean to note whether the side the louvers start from + should be flipped. Default is False to have contours on top or right. + Setting to True will start contours on the bottom or left. + indoor: Boolean for whether louvers should be generated facing the + opposite direction of the Face normal (typically meaning + indoor geometry). Default: False. + tolerance: An optional value to remove any louvers with a length less + than the tolerance. Default: 0.01, suitable for objects in meters. + max_count: Optional integer to set the maximum number of louvers that + will be generated. If None, louvers will cover the entire face. + base_name: Optional base identifier for the shade objects. If None, the + default is InShd or OutShd depending on whether indoor is True. + + Returns: + A list of the new Shade objects that have been generated. + """ + # set defaults + angle = math.radians(angle) + face_geo = self.geometry if indoor is False else self.geometry.flip() + if base_name is None: + shd_name_base = '{}_InShd{}' if indoor else '{}_OutShd{}' + else: + shd_name_base = '{}_' + str(base_name) + '{}' + + # generate shade geometries + shade_faces = face_geo.contour_fins_by_distance_between( + distance, depth, offset, angle, contour_vector, flip_start_side, tolerance) + if max_count: + try: + shade_faces = shade_faces[:max_count] + except IndexError: # fewer shades were generated than the max count + pass + + # create the shade objects + louvers = [] + for i, shade_geo in enumerate(shade_faces): + louvers.append(Shade(shd_name_base.format(self.identifier, i), shade_geo)) + if indoor: + self.add_indoor_shades(louvers) + else: + self.add_outdoor_shades(louvers) + return louvers
+ + +
+[docs] + def move(self, moving_vec): + """Move this Face along a vector. + + Args: + moving_vec: A ladybug_geometry Vector3D with the direction and distance + to move the face. + """ + self._geometry = self.geometry.move(moving_vec) + for ap in self._apertures: + ap.move(moving_vec) + for dr in self._doors: + dr.move(moving_vec) + self.move_shades(moving_vec) + self.properties.move(moving_vec) + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def rotate(self, axis, angle, origin): + """Rotate this Face by a certain angle around an axis and origin. + + Args: + axis: A ladybug_geometry Vector3D axis representing the axis of rotation. + angle: An angle for rotation in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate(axis, math.radians(angle), origin) + for ap in self._apertures: + ap.rotate(axis, angle, origin) + for dr in self._doors: + dr.rotate(axis, angle, origin) + self.rotate_shades(axis, angle, origin) + self.properties.rotate(axis, angle, origin) + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def rotate_xy(self, angle, origin): + """Rotate this Face counterclockwise in the world XY plane by a certain angle. + + Args: + angle: An angle in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate_xy(math.radians(angle), origin) + for ap in self._apertures: + ap.rotate_xy(angle, origin) + for dr in self._doors: + dr.rotate_xy(angle, origin) + self.rotate_xy_shades(angle, origin) + self.properties.rotate_xy(angle, origin) + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def reflect(self, plane): + """Reflect this Face across a plane. + + Args: + plane: A ladybug_geometry Plane across which the object will + be reflected. + """ + self._geometry = self.geometry.reflect(plane.n, plane.o) + for ap in self._apertures: + ap.reflect(plane) + for dr in self._doors: + dr.reflect(plane) + self.reflect_shades(plane) + self.properties.reflect(plane) + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def scale(self, factor, origin=None): + """Scale this Face by a factor from an origin point. + + Args: + factor: A number representing how much the object should be scaled. + origin: A ladybug_geometry Point3D representing the origin from which + to scale. If None, it will be scaled from the World origin (0, 0, 0). + """ + self._geometry = self.geometry.scale(factor, origin) + for ap in self._apertures: + ap.scale(factor, origin) + for dr in self._doors: + dr.scale(factor, origin) + self.scale_shades(factor, origin) + self.properties.scale(factor, origin) + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def remove_colinear_vertices(self, tolerance=0.01): + """Remove all colinear and duplicate vertices from this object's geometry. + + Note that this does not affect any assigned Apertures, Doors or Shades. + + Args: + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered colinear. Default: 0.01, + suitable for objects in meters. + """ + try: + self._geometry = self.geometry.remove_colinear_vertices(tolerance) + except AssertionError as e: # usually a sliver face of some kind + raise ValueError( + 'Face "{}" is invalid with dimensions less than the ' + 'tolerance.\n{}'.format(self.full_id, e)) + self._punched_geometry = None # reset so that it can be re-computed
+ + +
+[docs] + def remove_degenerate_sub_faces(self, tolerance=0.01): + """Remove colinear vertices from sub-faces and eliminate degenerate ones. + + Args: + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered colinear. Default: 0.01, + suitable for objects in meters. + """ + for i, ap in enumerate(self._apertures): + try: + ap.remove_colinear_vertices(tolerance) + except ValueError: + self._apertures.pop(i) + for i, dr in enumerate(self._doors): + try: + dr.remove_colinear_vertices(tolerance) + except ValueError: + self._apertures.pop(i)
+ + +
+[docs] + def is_geo_equivalent(self, face, tolerance=0.01): + """Get a boolean for whether this object is geometrically equivalent to another. + + This will also check all child Apertures and Doors for equivalency but not + assigned shades. + + Args: + face: Another Face for which geometric equivalency will be tested. + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered geometrically equivalent. + + Returns: + True if geometrically equivalent. False if not geometrically equivalent. + """ + meta_1 = (self.display_name, self.type, self.boundary_condition) + meta_2 = (face.display_name, face.type, face.boundary_condition) + if meta_1 != meta_2: + return False + if abs(self.area - face.area) > tolerance * self.area: + return False + if not self.geometry.is_centered_adjacent(face.geometry, tolerance): + return False + if len(self._apertures) != len(face._apertures): + return False + if len(self._doors) != len(face._doors): + return False + for ap1, ap2 in zip(self._apertures, face._apertures): + if not ap1.is_geo_equivalent(ap2, tolerance): + return False + for dr1, dr2 in zip(self._doors, face._doors): + if not dr1.is_geo_equivalent(dr2, tolerance): + return False + if not self._are_shades_equivalent(face, tolerance): + return False + return True
+ + +
+[docs] + def check_sub_faces_valid(self, tolerance=0.01, angle_tolerance=1, + raise_exception=True, detailed=False): + """Check that sub-faces are co-planar with this Face within the Face boundary. + + Note this does not check the planarity of the sub-faces themselves, whether + they self-intersect, or whether they have a non-zero area. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. Default: 0.01, + suitable for objects in meters. + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered coplanar. + Default: 1 degree. + raise_exception: Boolean to note whether a ValueError should be raised + if an sub-face is not valid. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with dictionaries if detailed is True. + """ + detailed = False if raise_exception else detailed + ap = self.check_apertures_valid(tolerance, angle_tolerance, False, detailed) + dr = self.check_doors_valid(tolerance, angle_tolerance, False, detailed) + full_msgs = ap + dr if detailed else [m for m in (ap, dr) if m != ''] + if raise_exception and len(full_msgs) != 0: + raise ValueError('\n'.join(full_msgs)) + return full_msgs if detailed else '\n'.join(full_msgs)
+ + +
+[docs] + def check_apertures_valid(self, tolerance=0.01, angle_tolerance=1, + raise_exception=True, detailed=False): + """Check that apertures are co-planar with this Face within the Face boundary. + + Note this does not check the planarity of the apertures themselves, whether + they self-intersect, or whether they have a non-zero area. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. Default: 0.01, + suitable for objects in meters. + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered coplanar. + Default: 1 degree. + raise_exception: Boolean to note whether a ValueError should be raised + if an aperture is not valid. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with dictionaries if detailed is True. + """ + detailed = False if raise_exception else detailed + angle_tolerance = math.radians(angle_tolerance) + msgs = [] + for ap in self._apertures: + if not self.geometry.is_sub_face(ap.geometry, tolerance, angle_tolerance): + msg = 'Aperture "{}" is not coplanar or fully bounded by its parent ' \ + 'Face "{}".'.format(ap.full_id, self.full_id) + msg = self._validation_message_child( + msg, ap, detailed, '000104', error_type='Invalid Sub-Face Geometry') + msgs.append(msg) + full_msg = msgs if detailed else '\n'.join(msgs) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_doors_valid(self, tolerance=0.01, angle_tolerance=1, + raise_exception=True, detailed=False): + """Check that doors are co-planar with this Face within the Face boundary. + + Note this does not check the planarity of the doors themselves, whether + they self-intersect, or whether they have a non-zero area. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. Default: 0.01, + suitable for objects in meters. + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered coplanar. + Default: 1 degree. + raise_exception: Boolean to note whether a ValueError should be raised + if an door is not valid. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with dictionaries if detailed is True. + """ + detailed = False if raise_exception else detailed + angle_tolerance = math.radians(angle_tolerance) + msgs = [] + for dr in self._doors: + if not self.geometry.is_sub_face(dr.geometry, tolerance, angle_tolerance): + msg = 'Door "{}" is not coplanar or fully bounded by its parent ' \ + 'Face "{}".'.format(dr.full_id, self.full_id) + msg = self._validation_message_child( + msg, dr, detailed, '000104', error_type='Invalid Sub-Face Geometry') + msgs.append(msg) + full_msg = msgs if detailed else '\n'.join(msgs) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_sub_faces_overlapping( + self, tolerance=0.01, raise_exception=True, detailed=False): + """Check that this Face's sub-faces do not overlap with one another. + + Args: + tolerance: The minimum distance that two sub-faces must overlap in order + for them to be considered overlapping and invalid. (Default: 0.01, + suitable for objects in meters). + raise_exception: Boolean to note whether a ValueError should be raised + if a sub-faces overlap with one another. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with dictionaries if detailed is True. + """ + sub_faces = self.sub_faces + if len(sub_faces) == 0: + return [] if detailed else '' + sf_groups = self._group_sub_faces_by_overlap(sub_faces, tolerance) + if not all(len(g) == 1 for g in sf_groups): + base_msg = 'Face "{}" contains Apertures and/or ' \ + 'Doors that overlap with each other.'.format(self.full_id) + if raise_exception: + raise ValueError(base_msg) + if not detailed: # just give a message about the Face if not detailed + return base_msg + all_overlaps = [] + for sf_group in sf_groups: + if len(sf_group) != 1: + det_msg = 'The following sub-faces overlap with one another:' \ + '\n{}'.format('\n'.join([sf.full_id for sf in sf_group])) + msg = '{}\n{}'.format(base_msg, det_msg) + err_obj = self._validation_message_child( + msg, sf_group[0], detailed, '000105', + error_type='Overlapping Sub-Face Geometry') + err_obj['element_type'] = 'SubFace' + for ov_obj in sf_group[1:]: + err_obj['element_id'].append(ov_obj.identifier) + err_obj['element_name'].append(ov_obj.display_name) + err_obj['parents'].append(err_obj['parents'][0]) + all_overlaps.append(err_obj) + return all_overlaps + return [] if detailed else ''
+ + +
+[docs] + def check_upside_down(self, angle_tolerance=1, raise_exception=True, detailed=False): + """Check whether the face is pointing in the correct direction for the face type. + + This method will only report Floors that are pointing upwards or RoofCeilings + that are pointed downwards. These cases are likely modeling errors and are in + danger of having their vertices flipped by EnergyPlus, causing them to + not see the sun. + + Args: + angle_tolerance: The max angle in degrees that the Face normal can + differ from up or down before it is considered a case of a downward + pointing RoofCeiling or upward pointing Floor. Default: 1 degree. + raise_exception: Boolean to note whether an ValueError should be + raised if the Face is an an upward pointing Floor or a downward + pointing RoofCeiling. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + msg = None + if isinstance(self.type, Floor) and self.altitude > 90 - angle_tolerance: + msg = 'Face "{}" is an upward-pointing Floor, which should be ' \ + 'changed to a RoofCeiling.'.format(self.full_id) + elif isinstance(self.type, RoofCeiling) and self.altitude < angle_tolerance - 90: + msg = 'Face "{}" is an downward-pointing RoofCeiling, which should be ' \ + 'changed to a Floor.'.format(self.full_id) + if msg: + full_msg = self._validation_message( + msg, raise_exception, detailed, '000109', + error_type='Upside Down Face') + return full_msg + return [] if detailed else ''
+ + +
+[docs] + def check_planar(self, tolerance=0.01, raise_exception=True, detailed=False): + """Check whether all of the Face's vertices lie within the same plane. + + Args: + tolerance: The minimum distance between a given vertex and a the + object's plane at which the vertex is said to lie in the plane. + Default: 0.01, suitable for objects in meters. + raise_exception: Boolean to note whether an ValueError should be + raised if a vertex does not lie within the object's plane. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + try: + self.geometry.check_planar(tolerance, raise_exception=True) + except ValueError as e: + msg = 'Face "{}" is not planar.\n{}'.format(self.full_id, e) + full_msg = self._validation_message( + msg, raise_exception, detailed, '000101', + error_type='Non-Planar Geometry') + if detailed: # add the out-of-plane points to helper_geometry + help_pts = [ + p.to_dict() for p in self.geometry.non_planar_vertices(tolerance) + ] + full_msg[0]['helper_geometry'] = help_pts + return full_msg + return [] if detailed else ''
+ + +
+[docs] + def check_self_intersecting(self, tolerance=0.01, raise_exception=True, + detailed=False): + """Check whether the edges of the Face intersect one another (like a bowtie). + + Note that objects that have duplicate vertices will not be considered + self-intersecting and are valid in honeybee. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. Default: 0.01, + suitable for objects in meters. + raise_exception: If True, a ValueError will be raised if the object + intersects with itself. Default: True. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + if self.geometry.is_self_intersecting: + msg = 'Face "{}" has self-intersecting edges.'.format(self.full_id) + try: # see if it is self-intersecting because of a duplicate vertex + new_geo = self.geometry.remove_duplicate_vertices(tolerance) + if not new_geo.is_self_intersecting: + return [] if detailed else '' # valid with removed dup vertex + except AssertionError: + pass # degenerate face; treat it as self-intersecting + full_msg = self._validation_message( + msg, raise_exception, detailed, '000102', + error_type='Self-Intersecting Geometry') + if detailed: # add the self-intersection points to helper_geometry + help_pts = [p.to_dict() for p in self.geometry.self_intersection_points] + full_msg[0]['helper_geometry'] = help_pts + return full_msg + return [] if detailed else ''
+ + +
+[docs] + def display_dict(self): + """Get a list of DisplayFace3D dictionaries for visualizing the object.""" + base = [self._display_face(self.punched_geometry, self.type_color)] + for ap in self._apertures: + base.extend(ap.display_dict()) + for dr in self._doors: + base.extend(dr.display_dict()) + for shd in self.shades: + base.extend(shd.display_dict()) + return base
+ + + @property + def to(self): + """Face writer object. + + Use this method to access Writer class to write the face in other formats. + + Usage: + + .. code-block:: python + + face.to.idf(face) -> idf string. + face.to.radiance(face) -> Radiance string. + """ + return writer + +
+[docs] + def to_dict(self, abridged=False, included_prop=None, include_plane=True): + """Return Face as a dictionary. + + Args: + abridged: Boolean to note whether the extension properties of the + object (ie. materials, constructions) should be included in detail + (False) or just referenced by identifier (True). (Default: False). + included_prop: List of properties to filter keys that must be included in + output dictionary. For example ['energy'] will include 'energy' key if + available in properties to_dict. By default all the keys will be + included. To exclude all the keys from extensions use an empty list. + include_plane: Boolean to note wether the plane of the Face3D should be + included in the output. This can preserve the orientation of the + X/Y axes of the plane but is not required and can be removed to + keep the dictionary smaller. (Default: True). + """ + base = {'type': 'Face'} + base['identifier'] = self.identifier + base['display_name'] = self.display_name + base['properties'] = self.properties.to_dict(abridged, included_prop) + enforce_upper_left = True if 'energy' in base['properties'] else False + base['geometry'] = self._geometry.to_dict(include_plane, enforce_upper_left) + + base['face_type'] = self.type.name + if isinstance(self.boundary_condition, Outdoors) and \ + 'energy' in base['properties']: + base['boundary_condition'] = self.boundary_condition.to_dict(full=True) + else: + base['boundary_condition'] = self.boundary_condition.to_dict() + + if self._apertures != []: + base['apertures'] = [ap.to_dict(abridged, included_prop, include_plane) + for ap in self._apertures] + if self._doors != []: + base['doors'] = [dr.to_dict(abridged, included_prop, include_plane) + for dr in self._doors] + self._add_shades_to_dict(base, abridged, included_prop, include_plane) + if self.user_data is not None: + base['user_data'] = self.user_data + return base
+ + + def _acceptable_sub_face_check(self, sub_face_type=Aperture): + """Check whether the Face can accept sub-faces and raise an exception if not.""" + assert isinstance(self.boundary_condition, Outdoors), \ + '{} cannot be added to Face "{}" with a {} boundary condition.'.format( + sub_face_type.__name__, self.full_id, self.boundary_condition) + assert not isinstance(self.type, AirBoundary), \ + '{} cannot be added to AirBoundary Face "{}".'.format( + sub_face_type.__name__, self.full_id) + + @staticmethod + def _remove_overlapping_sub_faces(sub_faces, tolerance): + """Get a list of Apertures and/or Doors with no overlaps. + + Args: + sub_faces: A list of Apertures or Doors to be checked for overlapping. + tolerance: The minimum distance from the edge of a neighboring Face3D + at which a point is considered to overlap with that Face3D. + + Returns: + A list of the input sub_faces with smaller overlapping geometries removed. + """ + # group the sub-faces according to the overlaps with one another + grouped_sfs = Face._group_sub_faces_by_overlap(sub_faces, tolerance) + # build a list of sub-faces without any overlaps + clean_sub_faces = [] + for sf_group in grouped_sfs: + if len(sf_group) == 1: + clean_sub_faces.append(sf_group[0]) + else: # take the subface with the largest area + sf_group.sort(key=lambda x: x.area, reverse=True) + clean_sub_faces.append(sf_group[0]) + return clean_sub_faces + + @staticmethod + def _group_sub_faces_by_overlap(sub_faces, tolerance): + """Group a Apertures and/or Doors depending on whether they overlap one another. + + Args: + sub_faces: A list of Apertures or Doors to be checked for overlapping. + tolerance: The minimum distance from the edge of a neighboring Face3D + at which a point is considered to overlap with that Face3D. + + Returns: + A list of lists where each sub-list represents a group of Apertures and/or + Doors that overlap with one another. + """ + # sort the sub-faces by area + sub_faces = list(sorted(sub_faces, key=lambda x: x.area, reverse=True)) + # create polygons for all of the faces + r_plane = sub_faces[0].geometry.plane + polygons = [Polygon2D([r_plane.xyz_to_xy(pt) for pt in face.vertices]) + for face in sub_faces] + # loop through the polygons and check to see if it overlaps with the others + grouped_polys, grouped_sfs = [[polygons[0]]], [[sub_faces[0]]] + for poly, face in zip(polygons[1:], sub_faces[1:]): + group_found = False + for poly_group, face_group in zip(grouped_polys, grouped_sfs): + for oth_poly in poly_group: + if poly.polygon_relationship(oth_poly, tolerance) >= 0: + poly_group.append(poly) + face_group.append(face) + group_found = True + break + if group_found: + break + if not group_found: # the polygon does not overlap with any of the others + grouped_polys.append([poly]) # make a new group for the polygon + grouped_sfs.append([face]) # make a new group for the face + return grouped_sfs + + @staticmethod + def _is_sub_polygon(sub_poly, parent_poly, parent_holes=None): + """Check if a sub-polygon is valid for a given assumed parent polygon. + + Args: + sub_poly: A sub-Polygon2D for which sub-face equivalency will be tested. + parent_poly: A parent Polygon2D. + parent_holes: An optional list of Polygon2D for any holes that may + exist in the parent polygon. (Default: None). + """ + if parent_holes is None: + return parent_poly.is_polygon_inside(sub_poly) + else: + if not parent_poly.is_polygon_inside(sub_poly): + return False + for hole_poly in parent_holes: + if not hole_poly.is_polygon_outside(sub_poly): + return False + return True + + def __copy__(self): + new_f = Face(self.identifier, self.geometry, self.type, self.boundary_condition) + new_f._display_name = self._display_name + new_f._user_data = None if self.user_data is None else self.user_data.copy() + new_f._apertures = [ap.duplicate() for ap in self._apertures] + new_f._doors = [dr.duplicate() for dr in self._doors] + for ap in new_f._apertures: + ap._parent = new_f + for dr in new_f._doors: + dr._parent = new_f + self._duplicate_child_shades(new_f) + new_f._punched_geometry = self._punched_geometry + new_f._properties._duplicate_extension_attr(self._properties) + return new_f + + def __repr__(self): + return 'Face: %s' % self.display_name
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/facetype.html b/docs/_modules/honeybee/facetype.html new file mode 100644 index 00000000..d5e0bd01 --- /dev/null +++ b/docs/_modules/honeybee/facetype.html @@ -0,0 +1,1296 @@ + + + + + + + honeybee.facetype — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.facetype

+"""Face Types."""
+from ladybug_geometry.geometry3d.pointvector import Vector3D
+import re
+import math
+
+
+class _FaceType(object):
+    __slots__ = ()
+
+    def __init__(self):
+        pass
+
+    @property
+    def name(self):
+        return self.__class__.__name__
+
+    def ToString(self):
+        return self.__repr__()
+
+    def __eq__(self, other):
+        return self.__class__ == other.__class__
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __repr__(self):
+        return self.name
+
+
+
+[docs] +class Wall(_FaceType): + """Type for walls.""" + __slots__ = () + pass
+ + + +
+[docs] +class RoofCeiling(_FaceType): + """Type for roofs and ceilings.""" + __slots__ = () + pass
+ + + +
+[docs] +class Floor(_FaceType): + """Type for floors.""" + __slots__ = () + pass
+ + + +
+[docs] +class AirBoundary(_FaceType): + """Type for air boundaries (aka. virtual partitions) between Rooms.""" + __slots__ = () + pass
+ + + +class _FaceTypes(object): + """Face types.""" + + def __init__(self): + self._wall = Wall() + self._roof_ceiling = RoofCeiling() + self._floor = Floor() + self._air_boundary = AirBoundary() + self._type_name_dict = None + + @property + def wall(self): + return self._wall + + @property + def roof_ceiling(self): + return self._roof_ceiling + + @property + def floor(self): + return self._floor + + @property + def air_boundary(self): + return self._air_boundary + + def by_name(self, face_type_name): + """Get a Face Type instance from its name. + + This method will correct for capitalization as well as the presence of + spaces and underscores. + + Args: + face_type_name: A text string for the face type (eg. "Wall"). + """ + if self._type_name_dict is None: + self._build_type_name_dict() + try: + return self._type_name_dict[re.sub(r'[\s_]', '', face_type_name.lower())] + except KeyError: + raise ValueError( + '"{}" is not a valid face type name.\nChoose from the following' + ': {}'.format(face_type_name, list(self._type_name_dict.keys()))) + + def _build_type_name_dict(self): + """Build a dictionary that can be used to lookup face types by name.""" + attr = [atr for atr in dir(self) if not atr.startswith('_')] + clean_attr = [re.sub(r'[\s_]', '', atr.lower()) for atr in attr] + self._type_name_dict = {} + for atr_name, atr in zip(clean_attr, attr): + try: + full_attr = getattr(self, '_' + atr) + self._type_name_dict[atr_name] = full_attr + except AttributeError: + pass # callable method that has no static default object + + def __contains__(self, value): + return isinstance(value, _FaceType) + + def __repr__(self): + attr = [atr for atr in dir(self) if not atr.startswith('_') and atr != 'by_name'] + return 'Face Types:\n{}'.format('\n'.join(attr)) + + +face_types = _FaceTypes() + + +
+[docs] +def get_type_from_normal(normal_vector, roof_angle=60, floor_angle=130): + """Return face type based on the angle between Z axis and normal vector. + + Angles between 0 and roof_angle will be set to roof_ceiling. + Angles between roof_angle and floor_angle will be set to wall. + Angles larger than floor angle will be set to floor. + + Args: + normal_vector: Normal vector as a ladybug_geometry Vector3D. + roof_angle: A number between 0 and 90 to set the angle from the horizontal + plane below which faces will be considered roofs instead of + walls. 90 indicates that all vertical faces are roofs and 0 + indicates that all horizontal faces are walls. (Default: 60, + recommended by the ASHRAE 90.1 standard). + floor_angle: A number between 90 and 180 to set the angle from the horizontal + plane above which faces will be considered floors instead of + walls. 180 indicates that all vertical faces are floors and 0 + indicates that all horizontal faces are walls. (Default: 130, + recommended by the ASHRAE 90.1 standard). + + Returns: + Face type instance. + """ + z_axis = Vector3D(0, 0, 1) + angle = math.degrees(z_axis.angle(normal_vector)) + if angle < roof_angle: + return face_types.roof_ceiling + elif roof_angle <= angle < floor_angle: + return face_types.wall + else: + return face_types.floor + + return face_types.wall
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/logutil.html b/docs/_modules/honeybee/logutil.html new file mode 100644 index 00000000..cc6c1fb8 --- /dev/null +++ b/docs/_modules/honeybee/logutil.html @@ -0,0 +1,1210 @@ + + + + + + + honeybee.logutil — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.logutil

+import logging
+from logging.handlers import TimedRotatingFileHandler
+import os
+import tempfile
+
+
+# This is copied from logging module since python 2 doesn't have it under the same name.
+CRITICAL = 50
+FATAL = CRITICAL
+ERROR = 40
+WARNING = 30
+WARN = WARNING
+INFO = 20
+DEBUG = 10
+NOTSET = 0
+
+_name_to_level = {
+    'CRITICAL': CRITICAL,
+    'FATAL': FATAL,
+    'ERROR': ERROR,
+    'WARN': WARNING,
+    'WARNING': WARNING,
+    'INFO': INFO,
+    'DEBUG': DEBUG,
+    'NOTSET': NOTSET,
+}
+
+
+def _get_log_folder():
+    home_folder = os.getenv('HOME') or os.path.expanduser('~')
+    if not os.access(home_folder, os.W_OK):
+        home_folder = tempfile.gettempdir()
+    log_folder = os.path.join(home_folder, '.honeybee')
+    if not os.path.isdir(log_folder):
+        try:
+            os.mkdir(log_folder)
+        except OSError as e:
+            if e.errno != 17:  # avoid race conditions between multiple tasks
+                raise OSError('Failed to create log folder: %s\n%s' % (log_folder, e))
+    return log_folder
+
+
+def _get_log_level(level):
+    level = _name_to_level.get(level)
+    return level or logging.INFO
+
+
+
+[docs] +def get_logger(name, filename='honeybee.log', file_log_level='DEBUG', + console_log_level='WARNING'): + """Get a logger to be used for each module. + + Args: + name: Logger name. The good practice is to set it to __init__ from inside each + modules. + filename: Logger filename.Setting filename to None will remove the file handler + (Default: honeybee.log). + file_log_level: Log level for file handler as a string (Default: DEBUG). + console_log_level: Log level for stream handler as a string (Default: WARNING). + """ + logger = logging.getLogger(name) + + # create a file handler to log debug and higher level logs + if filename: + log_file = os.path.join(_get_log_folder(), filename) + file_handler = TimedRotatingFileHandler(log_file, when='midnight') + file_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + file_handler.setFormatter(file_format) + file_handler.setLevel(_get_log_level(file_log_level)) + logger.addHandler(file_handler) + + # create a console handler that only prints out errors and warnings + stream_handler = logging.StreamHandler() + stream_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s') + stream_handler.setFormatter(stream_format) + stream_handler.setLevel(_get_log_level(console_log_level)) + + logger.addHandler(stream_handler) + + return logger
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/model.html b/docs/_modules/honeybee/model.html new file mode 100644 index 00000000..92c8fcea --- /dev/null +++ b/docs/_modules/honeybee/model.html @@ -0,0 +1,4827 @@ + + + + + + + honeybee.model — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.model

+# coding: utf-8
+"""Honeybee Model."""
+from __future__ import division
+import os
+import sys
+import io
+import re
+import json
+import math
+import uuid
+try:  # check if we are in IronPython
+    import cPickle as pickle
+except ImportError:  # wea are in cPython
+    import pickle
+
+from ladybug_geometry.geometry3d import Plane, Face3D, Mesh3D
+from ladybug_geometry.interop.stl import STL
+
+from ._base import _Base
+from .units import conversion_factor_to_meters, UNITS, UNITS_TOLERANCES
+from .checkdup import check_duplicate_identifiers, check_duplicate_identifiers_parent
+from .properties import ModelProperties
+from .room import Room
+from .face import Face
+from .shade import Shade
+from .aperture import Aperture
+from .door import Door
+from .shademesh import ShadeMesh
+from .typing import float_positive, invalid_dict_error, clean_string, \
+    clean_and_number_string
+from .config import folders
+from .boundarycondition import Outdoors, Surface
+from .facetype import AirBoundary, Wall, Floor, RoofCeiling, face_types
+import honeybee.writer.model as writer
+from honeybee.boundarycondition import boundary_conditions as bcs
+try:
+    ad_bc = bcs.adiabatic
+except AttributeError:  # honeybee_energy is not loaded and adiabatic does not exist
+    ad_bc = None
+
+
+
+[docs] +class Model(_Base): + """A collection of Rooms, Faces, Shades, Apertures, and Doors representing a model. + + Args: + identifier: Text string for a unique Model ID. Must be < 100 characters and + not contain any spaces or special characters. + rooms: A list of Room objects in the model. + orphaned_faces: A list of the Face objects in the model that lack + a parent Room. Note that orphaned Faces are translated to sun-blocking + shade objects in energy simulation. + orphaned_shades: A list of the Shade objects in the model that lack + a parent. + orphaned_apertures: A list of the Aperture objects in the model that lack + a parent Face. Note that orphaned Apertures are translated to sun-blocking + shade objects in energy simulation. + orphaned_doors: A list of the Door objects in the model that lack + a parent Face. Note that orphaned Doors are translated to sun-blocking + shade objects in energy simulation. + shade_meshes: A list of the ShadeMesh objects in the model. + units: Text for the units system in which the model geometry + exists. Default: 'Meters'. Choose from the following: + + * Meters + * Millimeters + * Feet + * Inches + * Centimeters + + tolerance: The maximum difference between x, y, and z values at which + vertices are considered equivalent. Zero indicates that no tolerance + checks should be performed. None indicates that the tolerance will be + set based on the units above, with the tolerance consistently being + between 1 cm and 1 mm (roughly the tolerance implicit in the OpenStudio + SDK and EnergyPlus). (Default: None). + angle_tolerance: The max angle difference in degrees that vertices are allowed + to differ from one another in order to consider them colinear. Zero indicates + that no angle tolerance checks should be performed. (Default: 1.0). + + Properties: + * identifier + * display_name + * units + * tolerance + * angle_tolerance + * rooms + * faces + * apertures + * doors + * shades + * shade_meshes + * indoor_shades + * outdoor_shades + * orphaned_faces + * orphaned_shades + * orphaned_apertures + * orphaned_doors + * stories + * volume + * floor_area + * exposed_area + * exterior_wall_area + * exterior_roof_area + * exterior_aperture_area + * exterior_wall_aperture_area + * exterior_skylight_aperture_area + * min + * max + * top_level_dict + * user_data + """ + __slots__ = ( + '_rooms', '_orphaned_faces', '_orphaned_apertures', '_orphaned_doors', + '_orphaned_shades', '_shade_meshes', + '_units', '_tolerance', '_angle_tolerance' + ) + + UNITS = UNITS + UNITS_TOLERANCES = UNITS_TOLERANCES + + def __init__(self, identifier, rooms=None, orphaned_faces=None, orphaned_shades=None, + orphaned_apertures=None, orphaned_doors=None, shade_meshes=None, + units='Meters', tolerance=None, angle_tolerance=1.0): + """A collection of Rooms, Faces, Apertures, and Doors for an entire model.""" + _Base.__init__(self, identifier) # process the identifier + + self.units = units + self.tolerance = tolerance + self.angle_tolerance = angle_tolerance + + self._rooms = [] + self._orphaned_faces = [] + self._orphaned_apertures = [] + self._orphaned_doors = [] + self._orphaned_shades = [] + self._shade_meshes = [] + if rooms is not None: + for room in rooms: + self.add_room(room) + if orphaned_faces is not None: + for face in orphaned_faces: + self.add_face(face) + if orphaned_apertures is not None: + for aperture in orphaned_apertures: + self.add_aperture(aperture) + if orphaned_doors is not None: + for door in orphaned_doors: + self.add_door(door) + if orphaned_shades is not None: + for shade in orphaned_shades: + self.add_shade(shade) + if shade_meshes is not None: + for shade_mesh in shade_meshes: + self.add_shade_mesh(shade_mesh) + + self._properties = ModelProperties(self) + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize a Model from a dictionary. + + Args: + data: A dictionary representation of a Model object. + """ + # check the type of dictionary + assert data['type'] == 'Model', 'Expected Model dictionary. ' \ + 'Got {}.'.format(data['type']) + + # import the units and tolerance values + units = 'Meters' if 'units' not in data or data['units'] is None \ + else data['units'] + tol = cls.UNITS_TOLERANCES[units] if 'tolerance' not in data or \ + data['tolerance'] is None else data['tolerance'] + angle_tol = 1.0 if 'angle_tolerance' not in data or \ + data['angle_tolerance'] is None else data['angle_tolerance'] + + # import all of the geometry + rooms = None # import rooms + if 'rooms' in data and data['rooms'] is not None: + rooms = [] + for r in data['rooms']: + try: + rooms.append(Room.from_dict(r, tol, angle_tol)) + except Exception as e: + invalid_dict_error(r, e) + orphaned_faces = None # import orphaned faces + if 'orphaned_faces' in data and data['orphaned_faces'] is not None: + orphaned_faces = [] + for f in data['orphaned_faces']: + try: + orphaned_faces.append(Face.from_dict(f)) + except Exception as e: + invalid_dict_error(f, e) + orphaned_apertures = None # import orphaned apertures + if 'orphaned_apertures' in data and data['orphaned_apertures'] is not None: + orphaned_apertures = [] + for a in data['orphaned_apertures']: + try: + orphaned_apertures.append(Aperture.from_dict(a)) + except Exception as e: + invalid_dict_error(a, e) + orphaned_doors = None # import orphaned doors + if 'orphaned_doors' in data and data['orphaned_doors'] is not None: + orphaned_doors = [] + for d in data['orphaned_doors']: + try: + orphaned_doors.append(Door.from_dict(d)) + except Exception as e: + invalid_dict_error(d, e) + orphaned_shades = None # import orphaned shades + if 'orphaned_shades' in data and data['orphaned_shades'] is not None: + orphaned_shades = [] + for s in data['orphaned_shades']: + try: + orphaned_shades.append(Shade.from_dict(s)) + except Exception as e: + invalid_dict_error(s, e) + shade_meshes = None # import shade meshes + if 'shade_meshes' in data and data['shade_meshes'] is not None: + shade_meshes = [] + for sm in data['shade_meshes']: + try: + shade_meshes.append(ShadeMesh.from_dict(sm)) + except Exception as e: + invalid_dict_error(sm, e) + + # build the model object + model = Model( + data['identifier'], rooms, orphaned_faces, orphaned_shades, + orphaned_apertures, orphaned_doors, shade_meshes, + units, tol, angle_tol) + if 'display_name' in data and data['display_name'] is not None: + model.display_name = data['display_name'] + if 'user_data' in data and data['user_data'] is not None: + model.user_data = data['user_data'] + + # assign extension properties to the model + model.properties.apply_properties_from_dict(data) + return model
+ + +
+[docs] + @classmethod + def from_file(cls, hb_file): + """Initialize a Model from a HBJSON or HBpkl file, auto-sensing the type. + + Args: + hb_file: Path to either a HBJSON or HBpkl file. + """ + # sense the file type from the first character to avoid maxing memory with JSON + # this is needed since queenbee overwrites all file extensions + with io.open(hb_file, encoding='utf-8') as inf: + first_char = inf.read(1) + second_char = inf.read(1) + is_json = True if first_char == '{' or second_char == '{' else False + # load the file using either HBJSON pathway or HBpkl + if is_json: + return cls.from_hbjson(hb_file) + return cls.from_hbpkl(hb_file)
+ + +
+[docs] + @classmethod + def from_hbjson(cls, hbjson_file): + """Initialize a Model from a HBJSON file. + + Args: + hbjson_file: Path to HBJSON file. + """ + assert os.path.isfile(hbjson_file), 'Failed to find %s' % hbjson_file + with io.open(hbjson_file, encoding='utf-8') as inf: + inf.read(1) + second_char = inf.read(1) + with io.open(hbjson_file, encoding='utf-8') as inf: + if second_char == '{': + inf.read(1) + data = json.load(inf) + return cls.from_dict(data)
+ + +
+[docs] + @classmethod + def from_hbpkl(cls, hbpkl_file): + """Initialize a Model from a HBpkl file. + + Args: + hbpkl_file: Path to HBpkl file. + """ + assert os.path.isfile(hbpkl_file), 'Failed to find %s' % hbpkl_file + with open(hbpkl_file, 'rb') as inf: + data = pickle.load(inf) + return cls.from_dict(data)
+ + +
+[docs] + @classmethod + def from_stl(cls, file_path, geometry_to_faces=False, units='Meters', + tolerance=None, angle_tolerance=1.0): + """Create a Honeybee Model from an STL file. + + Args: + file_path: Path to an STL file as a text string. The STL file can be + in either ASCII or binary format. + geometry_to_faces: A boolean to note whether the geometry in the STL + file should be imported as Faces (with Walls/Floors/RoofCeiling + set according to the normal). If False, all geometry will be + imported as ShadeMeshes instead of Faces. (Default: False). + units: Text for the units system in which the model geometry + exists. Default: 'Meters'. Choose from the following: + + * Meters + * Millimeters + * Feet + * Inches + * Centimeters + + tolerance: The maximum difference between x, y, and z values at which + vertices are considered equivalent. Zero indicates that no tolerance + checks should be performed. None indicates that the tolerance will be + set based on the units above, with the tolerance consistently being + between 1 cm and 1 mm (roughly the tolerance implicit in the OpenStudio + SDK and EnergyPlus). (Default: None). + angle_tolerance: The max angle difference in degrees that vertices + are allowed to differ from one another in order to consider them + colinear. Zero indicates that no angle tolerance checks should be + performed. (Default: 1.0). + """ + stl_obj = STL.from_file(file_path) + all_id = clean_string(stl_obj.name) + all_geo = [] + if geometry_to_faces: + for verts, normal in zip(stl_obj.face_vertices, stl_obj.face_normals): + all_geo.append(Face3D(verts, plane=Plane(normal, verts[0]))) + hb_objs = [Face(all_id + '_' + str(uuid.uuid4())[:8], go) for go in all_geo] + return Model(all_id, orphaned_faces=hb_objs, units=units, + tolerance=tolerance, angle_tolerance=angle_tolerance) + else: + mesh3d = Mesh3D.from_face_vertices(stl_obj.face_vertices) + hb_objs = [ShadeMesh(all_id, mesh3d)] + return Model(all_id, shade_meshes=hb_objs, units=units, + tolerance=tolerance, angle_tolerance=angle_tolerance)
+ + +
+[docs] + @classmethod + def from_sync(cls, base_model, other_model, sync_instructions): + """Initialize a Model from two models and instructions for syncing them. + + The SyncInstructions dictionary schema is essentially a variant of the + ComparisonReport schema that can be obtained by calling + base_model.comparison_report(other_model). The main difference is + that the XXX_changed properties should be replaced with update_XXX properties + for whether the change from the other_model should be accepted into + the new model or rejected from it. + + Args: + base_model: An base Honeybee Model that forms the base of + the new model to be created. + other_model: An other Honeybee Model that contains changes to + the base model to be merged into the base_model. + sync_instructions: A dictionary of SyncInstructions that states which + changes from the other_model should be accepted or rejected + when building a new Model from the base_model. + """ + # make sure the unit systems of the two models align + if base_model.units != other_model.units: + other_model = other_model.duplicate() + other_model.convert_to_units(base_model.units) + # set up dictionaries of objects and lists of changes + exist_dict = base_model.top_level_dict + other_dict = other_model.top_level_dict + add_dict = { + 'Room': [], 'Face': [], 'Aperture': [], 'Door': [], + 'Shade': [], 'ShadeMesh': [] + } + del_dict = { + 'Room': [], 'Face': [], 'Aperture': [], 'Door': [], + 'Shade': [], 'ShadeMesh': [] + } + # loop through the changed objects and record changes + if 'changed_objects' in sync_instructions: + for change in sync_instructions['changed_objects']: + ex_obj = exist_dict[change['element_id']] + up_obj = other_dict[change['element_id']] + base_obj = up_obj if 'update_geometry' in change \ + and change['update_geometry'] else ex_obj + base_obj.properties._update_by_sync( + change, ex_obj.properties, up_obj.properties) + del_dict[change['element_type']].append(change['element_id']) + add_dict[change['element_type']].append(base_obj) + # loop through deleted objects and record changes + if 'deleted_objects' in sync_instructions: + for change in sync_instructions['deleted_objects']: + del_dict[change['element_type']].append(change['element_id']) + # loop through added objects and record changes + if 'added_objects' in sync_instructions: + for change in sync_instructions['added_objects']: + up_obj = other_dict[change['element_id']] + add_dict[change['element_type']].append(up_obj) + # duplicate the base model and make changes to it + new_model = base_model.duplicate() + new_model.remove_rooms(del_dict['Room']) + new_model.remove_faces(del_dict['Face']) + new_model.remove_apertures(del_dict['Aperture']) + new_model.remove_doors(del_dict['Door']) + new_model.remove_shades(del_dict['Shade']) + new_model.remove_shade_meshes(del_dict['ShadeMesh']) + new_model.add_rooms(add_dict['Room']) + new_model.add_faces(add_dict['Face']) + new_model.add_apertures(add_dict['Aperture']) + new_model.add_doors(add_dict['Door']) + new_model.add_shades(add_dict['Shade']) + new_model.add_shade_meshes(add_dict['ShadeMesh']) + return new_model
+ + +
+[docs] + @classmethod + def from_sync_files( + cls, base_model_file, other_model_file, sync_instructions_file): + """Initialize a Model from two model files and instructions for syncing them. + + Args: + base_model_file: An base Honeybee Model (as HBJSON or HBPkl) + that forms the base of the new model to be created. + other_model_file: An other Honeybee Model (as HBJSON or HBPkl) + that contains changes to the base model to be merged into + the base_model. + sync_instructions: A JSON of SyncInstructions that states which + changes from the other_model should be accepted or rejected + when building a new Model from the base_model. The SyncInstructions + schema is essentially a variant of the ComparisonReport schema + that can be obtained by calling base_model.comparison_report( + other_model). The main difference is that the XXX_changed + properties should be replaced with update_XXX properties for + whether the change from the other_model should be accepted into + the new model or rejected from it. + """ + base_model = cls.from_file(base_model_file) + other_model = cls.from_file(other_model_file) + assert os.path.isfile(sync_instructions_file), \ + 'Failed to find %s' % sync_instructions_file + if sys.version_info < (3, 0): + with open(sync_instructions_file) as inf: + sync_instructions = json.load(inf) + else: + with open(sync_instructions_file, encoding='utf-8') as inf: + sync_instructions = json.load(inf) + return cls.from_sync(base_model, other_model, sync_instructions)
+ + +
+[docs] + @classmethod + def from_objects(cls, identifier, objects, units='Meters', + tolerance=None, angle_tolerance=1.0): + """Initialize a Model from a list of any type of honeybee-core geometry objects. + + Args: + identifier: Text string for a unique Model ID. Must be < 100 characters and + not contain any spaces or special characters. + objects: A list of honeybee Rooms, Faces, Shades, ShadeMEshes, + Apertures and Doors. + units: Text for the units system in which the model geometry + exists. Default: 'Meters'. Choose from the following: + + * Meters + * Millimeters + * Feet + * Inches + * Centimeters + + tolerance: The maximum difference between x, y, and z values at which + vertices are considered equivalent. Zero indicates that no tolerance + checks should be performed. None indicates that the tolerance will be + set based on the units above, with the tolerance consistently being + between 1 cm and 1 mm (roughly the tolerance implicit in the OpenStudio + SDK and EnergyPlus). (Default: None). + angle_tolerance: The max angle difference in degrees that vertices + are allowed to differ from one another in order to consider them + colinear. Zero indicates that no angle tolerance checks should be + performed. (Default: 1.0). + """ + rooms = [] + faces = [] + shades = [] + shade_meshes = [] + apertures = [] + doors = [] + for obj in objects: + if isinstance(obj, Room): + rooms.append(obj) + elif isinstance(obj, Face): + faces.append(obj) + elif isinstance(obj, Shade): + shades.append(obj) + elif isinstance(obj, ShadeMesh): + shade_meshes.append(obj) + elif isinstance(obj, Aperture): + apertures.append(obj) + elif isinstance(obj, Door): + doors.append(obj) + else: + raise TypeError('Expected Room, Face, Shade, Aperture or Door ' + 'for Model. Got {}'.format(type(obj))) + + return cls(identifier, rooms, faces, shades, apertures, doors, shade_meshes, + units, tolerance, angle_tolerance)
+ + +
+[docs] + @classmethod + def from_shoe_box( + cls, width, depth, height, orientation_angle=0, window_ratio=0, + adiabatic=True, units='Meters', tolerance=None, angle_tolerance=1.0): + """Create a model with a single shoe box Room. + + Args: + width: Number for the width of the box (in the X direction). + depth: Number for the depth of the box (in the Y direction). + height: Number for the height of the box (in the Z direction). + orientation_angle: A number between 0 and 360 for the clockwise + orientation of the box in degrees. (0=North, 90=East, 180=South, + 270=West). (Default: 0). + window_ratio: A number between 0 and 1 (but not equal to 1) for the ratio + between aperture area and area of the face pointing towards the + orientation-angle. Using 0 will generate no windows. (Default: 0). + adiabatic: Boolean to note whether the faces that are not in the direction + of the orientation-angle are adiabatic or outdoors. (Default: True) + units: Text for the units system in which the model geometry + exists. (Default: 'Meters'). + tolerance: The maximum difference between x, y, and z values at which + vertices are considered equivalent. Zero indicates that no tolerance + checks should be performed. None indicates that the tolerance will be + set based on the units above, with the tolerance consistently being + between 1 cm and 1 mm (roughly the tolerance implicit in the OpenStudio + SDK and EnergyPlus). (Default: None). + angle_tolerance: The max angle difference in degrees that vertices + are allowed to differ from one another in order to consider them + colinear. Zero indicates that no angle tolerance checks should be + performed. (Default: 1.0). + """ + # create the box room and assign all of the attributes + unique_id = str(uuid.uuid4())[:8] # unique identifier for the shoe box + tolerance = tolerance if tolerance is not None else UNITS_TOLERANCES[units] + room_id = 'Shoe_Box_Room_{}'.format(unique_id) + room = Room.from_box(room_id, width, depth, height, orientation_angle) + room.display_name = 'Shoe_Box_Room' + front_face = room[1] + front_face.apertures_by_ratio(window_ratio, tolerance) + if adiabatic and ad_bc: + room[0].boundary_condition = ad_bc # make the floor adiabatic + for face in room[2:]: # make all other face adiabatic + face.boundary_condition = ad_bc + # create the model object + model_id = 'Shoe_Box_Model_{}'.format(unique_id) + return cls(model_id, [room], units=units, tolerance=tolerance, + angle_tolerance=angle_tolerance)
+ + +
+[docs] + @classmethod + def from_rectangle_plan( + cls, width, length, floor_to_floor_height, perimeter_offset=0, story_count=1, + orientation_angle=0, outdoor_roof=True, ground_floor=True, + units='Meters', tolerance=None, angle_tolerance=1.0): + """Create a model with a rectangular floor plan. + + Note that the resulting Rooms in the model won't have any windows or solved + adjacencies. These can be added by using the Model.solve_adjacency method + and the various Face.apertures_by_XXX methods. + + Args: + width: Number for the width of the plan (in the X direction). + length: Number for the length of the plan (in the Y direction). + floor_to_floor_height: Number for the height of each floor of the model + (in the Z direction). + perimeter_offset: An optional positive number that will be used to offset + the perimeter to create core/perimeter Rooms. If this value is 0, + no offset will occur and each floor will have one Room. (Default: 0). + story_count: An integer for the number of stories to generate. (Default: 1). + orientation_angle: A number between 0 and 360 for the counterclockwise + orientation that the width of the box faces. (0=North, 90=East, + 180=South, 270=West). (Default: 0). + outdoor_roof: Boolean to note whether the roof faces of the top floor + should be outdoor or adiabatic. (Default: True). + ground_floor: Boolean to note whether the floor faces of the bottom + floor should be ground or adiabatic. (Default: True). + units: Text for the units system in which the model geometry + exists. (Default: 'Meters'). + tolerance: The maximum difference between x, y, and z values at which + vertices are considered equivalent. Zero indicates that no tolerance + checks should be performed. None indicates that the tolerance will be + set based on the units above, with the tolerance consistently being + between 1 cm and 1 mm (roughly the tolerance implicit in the OpenStudio + SDK and EnergyPlus). (Default: None). + angle_tolerance: The max angle difference in degrees that vertices + are allowed to differ from one another in order to consider them + colinear. Zero indicates that no angle tolerance checks should be + performed. (Default: 1.0). + """ + # create the honeybee rooms + tolerance = tolerance if tolerance is not None else UNITS_TOLERANCES[units] + unique_id = str(uuid.uuid4())[:8] # unique identifier for the model + rooms = Room.rooms_from_rectangle_plan( + width, length, floor_to_floor_height, perimeter_offset, story_count, + orientation_angle, outdoor_roof, ground_floor, unique_id, tolerance) + # create the model object + model_id = 'Rectangle_Plan_Model_{}'.format(unique_id) + return cls(model_id, rooms, units=units, tolerance=tolerance, + angle_tolerance=angle_tolerance)
+ + +
+[docs] + @classmethod + def from_l_shaped_plan( + cls, width_1, length_1, width_2, length_2, floor_to_floor_height, + perimeter_offset=0, story_count=1, orientation_angle=0, + outdoor_roof=True, ground_floor=True, + units='Meters', tolerance=None, angle_tolerance=1.0): + """Create a model with an L-shaped floor plan. + + Note that the resulting Rooms in the model won't have any windows or solved + adjacencies. These can be added by using the Model.solve_adjacency method + and the various Face.apertures_by_XXX methods. + + Args: + width_1: Number for the width of the lower part of the L segment. + length_1: Number for the length of the lower part of the L segment, not + counting the overlap between the upper and lower segments. + width_2: Number for the width of the upper (left) part of the L segment. + length_2: Number for the length of the upper (left) part of the L segment, + not counting the overlap between the upper and lower segments. + floor_to_floor_height: Number for the height of each floor of the model + (in the Z direction). + perimeter_offset: An optional positive number that will be used to offset + the perimeter to create core/perimeter Rooms. If this value is 0, + no offset will occur and each floor will have one Room. (Default: 0). + story_count: An integer for the number of stories to generate. (Default: 1). + orientation_angle: A number between 0 and 360 for the counterclockwise + orientation that the width of the box faces. (0=North, 90=East, + 180=South, 270=West). (Default: 0). + outdoor_roof: Boolean to note whether the roof faces of the top floor + should be outdoor or adiabatic. (Default: True). + ground_floor: Boolean to note whether the floor faces of the bottom + floor should be ground or adiabatic. (Default: True). + units: Text for the units system in which the model geometry + exists. (Default: 'Meters'). + tolerance: The maximum difference between x, y, and z values at which + vertices are considered equivalent. Zero indicates that no tolerance + checks should be performed. None indicates that the tolerance will be + set based on the units above, with the tolerance consistently being + between 1 cm and 1 mm (roughly the tolerance implicit in the OpenStudio + SDK and EnergyPlus). (Default: None). + angle_tolerance: The max angle difference in degrees that vertices + are allowed to differ from one another in order to consider them + colinear. Zero indicates that no angle tolerance checks should be + performed. (Default: 1.0). + """ + # create the honeybee rooms + tolerance = tolerance if tolerance is not None else UNITS_TOLERANCES[units] + unique_id = str(uuid.uuid4())[:8] # unique identifier for the model + rooms = Room.rooms_from_l_shaped_plan( + width_1, length_1, width_2, length_2, floor_to_floor_height, + perimeter_offset, story_count, + orientation_angle, outdoor_roof, ground_floor, unique_id, tolerance) + # create the model object + model_id = 'L_Shaped_Plan_Model_{}'.format(unique_id) + return cls(model_id, rooms, units=units, tolerance=tolerance, + angle_tolerance=angle_tolerance)
+ + + @property + def units(self): + """Get or set Text for the units system in which the model geometry exists.""" + return self._units + + @units.setter + def units(self, value): + value = value.title() + assert value in UNITS, '{} is not supported as a units system. ' \ + 'Choose from the following: {}'.format(value, UNITS) + self._units = value + + @property + def tolerance(self): + """Get or set a number for the max meaningful difference between x, y, z values. + + This value should be in the Model's units. Zero indicates cases + where no tolerance checks should be performed. + """ + return self._tolerance + + @tolerance.setter + def tolerance(self, value): + self._tolerance = float_positive(value, 'model tolerance') if value is not None \ + else UNITS_TOLERANCES[self.units] + + @property + def angle_tolerance(self): + """Get or set a number for the max meaningful angle difference in degrees. + + Face3D normal vectors differing by this amount are not considered parallel + and Face3D segments that differ from 180 by this amount are not considered + colinear. Zero indicates cases where no angle_tolerance checks should be + performed. + """ + return self._angle_tolerance + + @angle_tolerance.setter + def angle_tolerance(self, value): + self._angle_tolerance = float_positive(value, 'model angle_tolerance') + + @property + def rooms(self): + """Get a tuple of all Room objects in the model.""" + return tuple(self._rooms) + + @property + def faces(self): + """Get a list of all Face objects in the model.""" + child_faces = [face for room in self._rooms for face in room._faces] + return child_faces + self._orphaned_faces + + @property + def apertures(self): + """Get a list of all Aperture objects in the model.""" + child_apertures = [] + for room in self._rooms: + for face in room._faces: + child_apertures.extend(face._apertures) + for face in self._orphaned_faces: + child_apertures.extend(face._apertures) + return child_apertures + self._orphaned_apertures + + @property + def doors(self): + """Get a list of all Door objects in the model.""" + child_doors = [] + for room in self._rooms: + for face in room._faces: + child_doors.extend(face._doors) + for face in self._orphaned_faces: + child_doors.extend(face._doors) + return child_doors + self._orphaned_doors + + @property + def shades(self): + """Get a list of all Shade objects in the model.""" + child_shades = [] + for room in self._rooms: + child_shades.extend(room.shades) + for face in room.faces: + child_shades.extend(face.shades) + for ap in face._apertures: + child_shades.extend(ap.shades) + for dr in face._doors: + child_shades.extend(dr.shades) + for face in self._orphaned_faces: + child_shades.extend(face.shades) + for ap in face._apertures: + child_shades.extend(ap.shades) + for dr in face._doors: + child_shades.extend(dr.shades) + for ap in self._orphaned_apertures: + child_shades.extend(ap.shades) + for dr in self._orphaned_doors: + child_shades.extend(dr.shades) + return child_shades + self._orphaned_shades + + @property + def indoor_shades(self): + """Get a list of all indoor Shade objects in the model.""" + child_shades = [] + for room in self._rooms: + child_shades.extend(room._indoor_shades) + for face in room.faces: + child_shades.extend(face._indoor_shades) + for ap in face._apertures: + child_shades.extend(ap._indoor_shades) + for dr in face._doors: + child_shades.extend(dr._indoor_shades) + for face in self._orphaned_faces: + child_shades.extend(face._indoor_shades) + for ap in face._apertures: + child_shades.extend(ap._indoor_shades) + for dr in face._doors: + child_shades.extend(dr._indoor_shades) + for ap in self._orphaned_apertures: + child_shades.extend(ap._indoor_shades) + for dr in self._orphaned_doors: + child_shades.extend(dr._indoor_shades) + return child_shades + + @property + def outdoor_shades(self): + """Get a list of all outdoor Shade objects in the model. + + This includes all of the orphaned_shades. + """ + child_shades = [] + for room in self._rooms: + child_shades.extend(room._outdoor_shades) + for face in room.faces: + child_shades.extend(face._outdoor_shades) + for ap in face._apertures: + child_shades.extend(ap._outdoor_shades) + for dr in face._doors: + child_shades.extend(dr._outdoor_shades) + for face in self._orphaned_faces: + child_shades.extend(face._outdoor_shades) + for ap in face._apertures: + child_shades.extend(ap._outdoor_shades) + for dr in face._doors: + child_shades.extend(dr._outdoor_shades) + for ap in self._orphaned_apertures: + child_shades.extend(ap._outdoor_shades) + for dr in self._orphaned_doors: + child_shades.extend(dr._outdoor_shades) + return child_shades + self._orphaned_shades + + @property + def shade_meshes(self): + """Get a tuple of all ShadeMesh objects in the model.""" + return tuple(self._shade_meshes) + + @property + def grouped_shades(self): + """Get a list of lists where each sub-list contains Shades and/or ShadeMeshes + with the same display_name. + + Assigning a common display_name to Shades and ShadeMeshes is the officially + recommended way to group these objects for export to platforms that + support shade groups. In this case, it is customary to use the common + display_name as the name of the shade group. + + Note that, if no display_names have been assigned to the Shades and + ShadeMeshes, the unique object identifier is used, meaning each sublist + returned here should have only one item in it. + """ + all_shades = self.shades + self._shade_meshes + group_dict = {} + for shade in all_shades: + try: + group_dict[shade.display_name].append(shade) + except KeyError: + group_dict[shade.display_name] = [shade] + return list(group_dict.values()) + + @property + def orphaned_faces(self): + """Get a tuple of all Face objects without parent Rooms in the model.""" + return tuple(self._orphaned_faces) + + @property + def orphaned_apertures(self): + """Get a tuple of all Aperture objects without parent Faces in the model.""" + return tuple(self._orphaned_apertures) + + @property + def orphaned_doors(self): + """Get a tuple of all Door objects without parent Faces in the model.""" + return tuple(self._orphaned_doors) + + @property + def orphaned_shades(self): + """Get a tuple of all Shade objects without parent Rooms in the model.""" + return tuple(self._orphaned_shades) + + @property + def stories(self): + """Get a list of text for each unique story identifier in the Model. + + Note that this will be an empty list if the model has to rooms. + """ + _stories = set() + for room in self._rooms: + if room.story is not None: + _stories.add(room.story) + return list(_stories) + + @property + def volume(self): + """Get the combined volume of all rooms in the Model. + + Note that this property accounts for the room multipliers. Also note that, + if this model's rooms are not closed solids, the value of this property + will not be accurate. + """ + return sum([room.volume * room.multiplier for room in self._rooms]) + + @property + def floor_area(self): + """Get the combined area of all room floor faces in the Model. + + Note that this property accounts for the room multipliers. + """ + return sum([room.floor_area * room.multiplier for room in self._rooms + if not room.exclude_floor_area]) + + @property + def exposed_area(self): + """Get the combined area of all room faces with outdoor boundary conditions. + + Useful for estimating infiltration, often expressed as a flow per unit exposed + envelope area. Note that this property accounts for the room multipliers. + """ + return sum([room.exposed_area * room.multiplier for room in self._rooms]) + + @property + def exterior_wall_area(self): + """Get the combined area of all exterior walls on the model's rooms. + + This is NOT the area of the wall's punched_geometry and it includes BOTH + the area of opaque and transparent parts of the walls. Note that this + property accounts for the room multipliers. + """ + return sum([room.exterior_wall_area * room.multiplier for room in self._rooms]) + + @property + def exterior_roof_area(self): + """Get the combined area of all exterior roofs on the model's rooms. + + This is NOT the area of the roof's punched_geometry and it includes BOTH + the area of opaque and transparent parts of the roofs. Note that this + property accounts for the room multipliers. + """ + return sum([room.exterior_roof_area * room.multiplier for room in self._rooms]) + + @property + def exterior_aperture_area(self): + """Get the combined area of all exterior apertures on the model's rooms. + + Note that this property accounts for the room multipliers. + """ + return sum([room.exterior_aperture_area * room.multiplier + for room in self._rooms]) + + @property + def exterior_wall_aperture_area(self): + """Get the combined area of all apertures on exterior walls of the model's rooms. + + Note that this property accounts for the room multipliers. + """ + return sum([room.exterior_wall_aperture_area * room.multiplier + for room in self._rooms]) + + @property + def exterior_skylight_aperture_area(self): + """Get the combined area of all apertures on exterior roofs of the model's rooms. + + Note that this property accounts for the room multipliers. + """ + return sum([room.exterior_skylight_aperture_area * room.multiplier + for room in self._rooms]) + + @property + def min(self): + """Get a Point3D for the min bounding box vertex in the XY plane.""" + return self._calculate_min(self._all_objects()) + + @property + def max(self): + """Get a Point3D for the max bounding box vertex in the XY plane.""" + return self._calculate_max(self._all_objects()) + + @property + def top_level_dict(self): + """Get dictionary of top-level model objects with identifiers as the keys. + + This is useful for matching these objects to others using identifiers. + """ + base = {r.identifier: r for r in self._rooms} + for f in self._orphaned_faces: + base[f.identifier] = f + for a in self._orphaned_apertures: + base[a.identifier] = a + for d in self._orphaned_doors: + base[d.identifier] = d + for s in self._orphaned_shades: + base[s.identifier] = s + for sm in self._shade_meshes: + base[sm.identifier] = sm + return base + +
+[docs] + def add_model(self, other_model): + """Add another Model object to this model.""" + assert isinstance(other_model, Model), \ + 'Expected Model. Got {}.'.format(type(other_model)) + if self.units != other_model.units: + other_model.convert_to_units(self.units) + for room in other_model._rooms: + self._rooms.append(room) + for face in other_model._orphaned_faces: + self._orphaned_faces.append(face) + for shade in other_model._orphaned_shades: + self._orphaned_shades.append(shade) + for shade_mesh in other_model._shade_meshes: + self._shade_meshes.append(shade_mesh) + for aperture in other_model._orphaned_apertures: + self._orphaned_apertures.append(aperture) + for door in other_model._orphaned_doors: + self._orphaned_doors.append(door)
+ + +
+[docs] + def add_room(self, obj): + """Add a Room object to the model.""" + assert isinstance(obj, Room), 'Expected Room. Got {}.'.format(type(obj)) + self._rooms.append(obj)
+ + +
+[docs] + def add_face(self, obj): + """Add an orphaned Face object without a parent to the model.""" + assert isinstance(obj, Face), 'Expected Face. Got {}.'.format(type(obj)) + assert not obj.has_parent, 'Face "{}"" has a parent Room. Add the Room to '\ + 'the model instead of the Face.'.format(obj.display_name) + self._orphaned_faces.append(obj)
+ + +
+[docs] + def add_aperture(self, obj): + """Add an orphaned Aperture object to the model.""" + assert isinstance(obj, Aperture), 'Expected Aperture. Got {}.'.format(type(obj)) + assert not obj.has_parent, 'Aperture "{}"" has a parent Face. Add the Face to '\ + 'the model instead of the Aperture.'.format(obj.display_name) + self._orphaned_apertures.append(obj)
+ + +
+[docs] + def add_door(self, obj): + """Add an orphaned Door object to the model.""" + assert isinstance(obj, Door), 'Expected Door. Got {}.'.format(type(obj)) + assert not obj.has_parent, 'Door "{}"" has a parent Face. Add the Face to '\ + 'the model instead of the Door.'.format(obj.display_name) + self._orphaned_doors.append(obj)
+ + +
+[docs] + def add_shade(self, obj): + """Add an orphaned Shade object to the model, typically representing context.""" + assert isinstance(obj, Shade), 'Expected Shade. Got {}.'.format(type(obj)) + assert not obj.has_parent, 'Shade "{}"" has a parent object. Add the object to '\ + 'the model instead of the Shade.'.format(obj.display_name) + self._orphaned_shades.append(obj)
+ + +
+[docs] + def add_shade_mesh(self, obj): + """Add a ShadeMesh object to the model.""" + assert isinstance(obj, ShadeMesh), 'Expected ShadeMesh. Got {}.'.format(type(obj)) + self._shade_meshes.append(obj)
+ + +
+[docs] + def remove_rooms(self, room_ids=None): + """Remove Rooms from the model. + + Args: + room_ids: An optional list of Room identifiers to only remove certain rooms + from the model. If None, all Rooms will be removed. (Default: None). + """ + self._rooms = self._remove_by_ids(self.rooms, room_ids)
+ + +
+[docs] + def remove_faces(self, face_ids=None): + """Remove orphaned Faces from the model. + + Args: + face_ids: An optional list of Face identifiers to only remove certain faces + from the model. If None, all Faces will be removed. (Default: None). + """ + self._orphaned_faces = self._remove_by_ids(self._orphaned_faces, face_ids)
+ + +
+[docs] + def remove_apertures(self, aperture_ids=None): + """Remove orphaned Apertures from the model. + + Args: + aperture_ids: An optional list of Aperture identifiers to only remove + certain apertures from the model. If None, all Apertures will + be removed. (Default: None). + """ + self._orphaned_apertures = self._remove_by_ids( + self._orphaned_apertures, aperture_ids)
+ + +
+[docs] + def remove_doors(self, door_ids=None): + """Remove orphaned Doors from the model. + + Args: + door_ids: An optional list of Door identifiers to only remove certain doors + from the model. If None, all Doors will be removed. (Default: None). + """ + self._orphaned_doors = self._remove_by_ids(self._orphaned_doors, door_ids)
+ + +
+[docs] + def remove_shades(self, shade_ids=None): + """Remove orphaned Shades from the model. + + Args: + shade_ids: An optional list of Shade identifiers to only remove + certain shades from the model. If None, all Shades will be + removed. (Default: None). + """ + self._orphaned_shades = self._remove_by_ids(self._orphaned_shades, shade_ids)
+ + +
+[docs] + def remove_shade_meshes(self, shade_mesh_ids=None): + """Remove ShadeMeshes from the model. + + Args: + shade_mesh_ids: An optional list of ShadeMesh identifiers to only remove + certain shades from the model. If None, all Shades will be + removed. (Default: None). + """ + self._shade_meshes = self._remove_by_ids(self._shade_meshes, shade_mesh_ids)
+ + +
+[docs] + def remove_assigned_apertures(self): + """Remove all Apertures assigned to the model's Faces. + + This includes nested apertures like those assigned to Faces with parent Rooms. + """ + for room in self._rooms: + for face in room.faces: + face.remove_apertures() + for face in self._orphaned_faces: + face.remove_apertures()
+ + +
+[docs] + def remove_assigned_doors(self): + """Remove all Doors assigned to the model's Faces. + + This includes nested doors like those assigned to Faces with parent Rooms. + """ + for room in self._rooms: + for face in room.faces: + face.remove_doors() + for face in self._orphaned_faces: + face.remove_doors()
+ + +
+[docs] + def remove_assigned_shades(self): + """Remove all Shades assigned to the model's Rooms, Faces, Apertures and Doors. + + This includes nested shades like those assigned to Apertures with parent + Faces that have parent Rooms. + """ + for room in self._rooms: + room.remove_shades() + for face in room.faces: + face.remove_shades() + for ap in face.apertures: + ap.remove_shades() + for dr in face.doors: + dr.remove_shades() + for face in self._orphaned_faces: + face.remove_shades() + for ap in face.apertures: + ap.remove_shades() + for dr in face.doors: + dr.remove_shades() + for aperture in self._orphaned_apertures: + aperture.remove_shades() + for door in self._orphaned_doors: + door.remove_shades()
+ + +
+[docs] + def remove_all_apertures(self): + """Remove all Apertures from the model. + + This includes assigned apertures as well as orphaned apertures. + """ + self.remove_apertures() + self.remove_assigned_apertures()
+ + +
+[docs] + def remove_all_doors(self): + """Remove all Doors from the model. + + This includes assigned doors as well as orphaned doors. + """ + self.remove_doors() + self.remove_assigned_doors()
+ + +
+[docs] + def remove_all_shades(self): + """Remove all Shades from the model. + + This includes assigned shades as well as orphaned shades. + """ + self.remove_shades() + self.remove_assigned_shades()
+ + +
+[docs] + def add_rooms(self, objs): + """Add a list of Room objects to the model.""" + for obj in objs: + self.add_room(obj)
+ + +
+[docs] + def add_faces(self, objs): + """Add a list of orphaned Face objects to the model.""" + for obj in objs: + self.add_face(obj)
+ + +
+[docs] + def add_apertures(self, objs): + """Add a list of orphaned Aperture objects to the model.""" + for obj in objs: + self.add_aperture(obj)
+ + +
+[docs] + def add_doors(self, objs): + """Add a list of orphaned Door objects to the model.""" + for obj in objs: + self.add_door(obj)
+ + +
+[docs] + def add_shades(self, objs): + """Add a list of orphaned Shade objects to the model.""" + for obj in objs: + self.add_shade(obj)
+ + +
+[docs] + def add_shade_meshes(self, objs): + """Add a list of ShadeMesh objects to the model.""" + for obj in objs: + self.add_shade_mesh(obj)
+ + +
+[docs] + def rooms_by_identifier(self, identifiers): + """Get a list of Room objects in the model given the Room identifiers.""" + rooms, missing_ids = [], [] + model_rooms = self._rooms + for obj_id in identifiers: + for room in model_rooms: + if room.identifier == obj_id: + rooms.append(room) + break + else: + missing_ids.append(obj_id) + if len(missing_ids) != 0: + all_objs = ' '.join(['"' + rid + '"' for rid in missing_ids]) + raise ValueError( + 'The following Rooms were not found in the model: {}'.format(all_objs) + ) + return rooms
+ + +
+[docs] + def faces_by_identifier(self, identifiers): + """Get a list of Face objects in the model given the Face identifiers.""" + faces, missing_ids = [], [] + model_faces = self.faces + for obj_id in identifiers: + for face in model_faces: + if face.identifier == obj_id: + faces.append(face) + break + else: + missing_ids.append(obj_id) + if len(missing_ids) != 0: + all_objs = ' '.join(['"' + rid + '"' for rid in missing_ids]) + raise ValueError( + 'The following Faces were not found in the model: {}'.format(all_objs) + ) + return faces
+ + +
+[docs] + def apertures_by_identifier(self, identifiers): + """Get a list of Aperture objects in the model given the Aperture identifiers.""" + apertures, missing_ids = [], [] + model_apertures = self.apertures + for obj_id in identifiers: + for aperture in model_apertures: + if aperture.identifier == obj_id: + apertures.append(aperture) + break + else: + missing_ids.append(obj_id) + if len(missing_ids) != 0: + all_objs = ' '.join(['"' + rid + '"' for rid in missing_ids]) + raise ValueError( + 'The following Apertures were not found in the model:\n' + '{}'.format(all_objs) + ) + return apertures
+ + +
+[docs] + def doors_by_identifier(self, identifiers): + """Get a list of Door objects in the model given the Door identifiers.""" + doors, missing_ids = [], [] + model_doors = self.doors + for obj_id in identifiers: + for door in model_doors: + if door.identifier == obj_id: + doors.append(door) + break + else: + missing_ids.append(obj_id) + if len(missing_ids) != 0: + all_objs = ' '.join(['"' + rid + '"' for rid in missing_ids]) + raise ValueError( + 'The following Doors were not found in the model: {}'.format(all_objs) + ) + return doors
+ + +
+[docs] + def shades_by_identifier(self, identifiers): + """Get a list of Shade objects in the model given the Shade identifiers.""" + shades, missing_ids = [], [] + model_shades = self.shades + for obj_id in identifiers: + for face in model_shades: + if face.identifier == obj_id: + shades.append(face) + break + else: + missing_ids.append(obj_id) + if len(missing_ids) != 0: + all_objs = ' '.join(['"' + rid + '"' for rid in missing_ids]) + raise ValueError( + 'The following Shades were not found in the model: {}'.format(all_objs) + ) + return shades
+ + +
+[docs] + def shade_meshes_by_identifier(self, identifiers): + """Get a list of ShadeMesh objects in the model given the ShadeMesh identifiers. + """ + shades, missing_ids = [], [] + model_shades = self._shade_meshes + for obj_id in identifiers: + for sm in model_shades: + if sm.identifier == obj_id: + shades.append(sm) + break + else: + missing_ids.append(obj_id) + if len(missing_ids) != 0: + a_os = ' '.join(['"' + rid + '"' for rid in missing_ids]) + raise ValueError( + 'The following ShadeMeshes were not found in the model: {}'.format(a_os) + ) + return shades
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier of this object and child objects by inserting a prefix. + + This is particularly useful in workflows where you duplicate and edit + a starting object and then want to combine it with the original object + since all objects within a Model must have unique identifiers. + + Args: + prefix: Text that will be inserted at the start of this object's + (and child objects') identifier and display_name. It is recommended + that this prefix be short to avoid maxing out the 100 allowable + characters for honeybee identifiers. + """ + for room in self._rooms: + room.add_prefix(prefix) + for face in self._orphaned_faces: + face.add_prefix(prefix) + for aperture in self._orphaned_apertures: + aperture.add_prefix(prefix) + for door in self._orphaned_doors: + door.add_prefix(prefix) + for shade in self._orphaned_shades: + shade.add_prefix(prefix) + for shade_mesh in self._shade_meshes: + shade_mesh.add_prefix(prefix)
+ + +
+[docs] + def reset_ids(self, repair_surface_bcs=True): + """Reset the identifiers of all Model objects to be derived from display_names. + + In the event that duplicate identifiers are found, an integer will be + automatically appended to the new ID to make it unique. This is similar + to the routines that automatically assign unique names to OpenStudio SDK objects. + + Args: + repair_surface_bcs: A Boolean to note whether all Surface boundary + conditions across the model should be updated with the new + identifiers that were generated from the display names. (Default: True). + """ + # set up dictionaries to hold various pieces of information + room_map = self.reset_room_ids() + face_dict, ap_dict, dr_dict, shd_dict, sm_dict = {}, {}, {}, {}, {} + face_map, ap_map, dr_map = {}, {}, {} + # loop through the objects and change their identifiers + for face in self.faces: + new_id = clean_and_number_string( + face.display_name, face_dict, 'Face identifier') + face_map[face.identifier] = new_id + face.identifier = new_id + for ap in self.apertures: + new_id = clean_and_number_string( + ap.display_name, ap_dict, 'Aperture identifier') + ap_map[ap.identifier] = new_id + ap.identifier = new_id + for dr in self.doors: + new_id = clean_and_number_string( + dr.display_name, dr_dict, 'Door identifier') + dr_map[dr.identifier] = new_id + dr.identifier = new_id + for shade in self.shades: + shade.identifier = clean_and_number_string( + shade.display_name, shd_dict, 'Shade identifier') + for shade_mesh in self.shade_meshes: + shade_mesh.identifier = clean_and_number_string( + shade_mesh.display_name, sm_dict, 'ShadeMesh identifier') + # reset all of the Surface boundary conditions if requested + if repair_surface_bcs: + for room in self.rooms: + for face in room.faces: + if isinstance(face.boundary_condition, Surface): + old_objs = face.boundary_condition.boundary_condition_objects + try: + new_objs = (face_map[old_objs[0]], room_map[old_objs[1]]) + except KeyError: # missing adjacency + try: # see if maybe the room reference is still there + new_objs = (old_objs[0], room_map[old_objs[1]]) + except KeyError: # just let the invalid adjacency pass + continue + new_bc = Surface(new_objs) + face.boundary_condition = new_bc + for ap in face.apertures: + old_objs = ap.boundary_condition.boundary_condition_objects + try: + new_objs = (ap_map[old_objs[0]], face_map[old_objs[1]], + room_map[old_objs[2]]) + except KeyError: # missing adjacency + new_objs = (old_objs[0], old_objs[1], + room_map[old_objs[2]]) + new_bc = Surface(new_objs, True) + ap.boundary_condition = new_bc + for dr in face.doors: + old_objs = dr.boundary_condition.boundary_condition_objects + try: + new_objs = (dr_map[old_objs[0]], face_map[old_objs[1]], + room_map[old_objs[2]]) + except KeyError: # missing adjacency + new_objs = (old_objs[0], old_objs[1], + room_map[old_objs[2]]) + new_bc = Surface(new_objs, True) + dr.boundary_condition = new_bc
+ + +
+[docs] + def reset_room_ids(self): + """Reset the identifiers of the Model Rooms to be derived from display_names. + + In the event that duplicate Room identifiers are found, an integer will + be automatically appended to the new Room ID to make it unique. + + Returns: + A dictionary that relates the old identifiers (keys) to the new + identifiers (values). This can be used to map between old and new + objects and update things like Surface boundary conditions. + """ + room_dict, room_map = {}, {} + for room in self.rooms: + new_id = clean_and_number_string( + room.display_name, room_dict, 'Room identifier') + room_map[room.identifier] = new_id + room.identifier = new_id + return room_map
+ + +
+[docs] + def solve_adjacency( + self, merge_coplanar=False, intersect=False, overwrite=False, + air_boundary=False, adiabatic=False, + tolerance=None, angle_tolerance=None): + """Solve adjacency between Rooms of the Model. + + Args: + merge_coplanar: Boolean to note whether coplanar Faces of the Rooms + should be merged before proceeding with the rest of the adjacency + solving. This is particularly helpful when used with the intersect + option since it will ensure the Room geometry is relatively + clean before the intersection and adjacency solving + occurs. (Default: False). + intersect: Boolean to note whether the Faces of the Rooms should be + intersected with one another before the adjacencies are + solved. (Default: False). + overwrite: Boolean to note whether existing Surface boundary + conditions should be overwritten. (Default: False). + air_boundary: Boolean to note whether the wall adjacencies should be + of the air boundary face type. (Default: False). + adiabatic: Boolean to note whether the adjacencies should be + surface or adiabatic. Note that this requires honeybee-energy + to be installed in order to have any meaning. (Default: False). + tolerance: The maximum difference between point values for them to be + considered equivalent. If None, the Model tolerance will be + used. (Default: None). + angle_tolerance: The max angle difference in degrees where Face normals + are no longer considered coplanar. If None, the Model + angle_tolerance will be used. (Default: None). + """ + tol = tolerance if tolerance else self.tolerance + ang_tol = angle_tolerance if angle_tolerance else self.angle_tolerance + + # merge coplanar faces if requested + if merge_coplanar: + for room in self.rooms: + room.merge_coplanar_faces(tol, ang_tol) + + # intersect adjacencies if requested + if intersect: + Room.intersect_adjacency(self.rooms, tol, ang_tol) + + # solve adjacency + if not overwrite: # only assign new adjacencies + adj_info = Room.solve_adjacency(self.rooms, tol) + else: # overwrite existing Surface BC + adj_faces = Room.find_adjacency(self.rooms, tol) + for face_pair in adj_faces: + face_pair[0].set_adjacency(face_pair[1]) + adj_info = {'adjacent_faces': adj_faces} + + # try to assign the air boundary face type + if air_boundary: + for face_pair in adj_info['adjacent_faces']: + if isinstance(face_pair[0].type, Wall): + face_pair[0].type = face_types.air_boundary + face_pair[1].type = face_types.air_boundary + + # try to assign the adiabatic boundary condition + if adiabatic and ad_bc: + for face_pair in adj_info['adjacent_faces']: + face_pair[0].boundary_condition = ad_bc + face_pair[1].boundary_condition = ad_bc
+ + +
+[docs] + def move(self, moving_vec): + """Move this Model along a vector. + + Args: + moving_vec: A ladybug_geometry Vector3D with the direction and distance + to move the Model. + """ + for room in self._rooms: + room.move(moving_vec) + for face in self._orphaned_faces: + face.move(moving_vec) + for aperture in self._orphaned_apertures: + aperture.move(moving_vec) + for door in self._orphaned_doors: + door.move(moving_vec) + for shade in self._orphaned_shades: + shade.move(moving_vec) + for shade_mesh in self._shade_meshes: + shade_mesh.move(moving_vec) + self.properties.move(moving_vec)
+ + +
+[docs] + def rotate(self, axis, angle, origin): + """Rotate this Model by a certain angle around an axis and origin. + + Args: + axis: A ladybug_geometry Vector3D axis representing the axis of rotation. + angle: An angle for rotation in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + for room in self._rooms: + room.rotate(axis, angle, origin) + for face in self._orphaned_faces: + face.rotate(axis, angle, origin) + for aperture in self._orphaned_apertures: + aperture.rotate(axis, angle, origin) + for door in self._orphaned_doors: + door.rotate(axis, angle, origin) + for shade in self._orphaned_shades: + shade.rotate(axis, angle, origin) + for shade_mesh in self._shade_meshes: + shade_mesh.rotate(axis, angle, origin) + self.properties.rotate(axis, angle, origin)
+ + +
+[docs] + def rotate_xy(self, angle, origin): + """Rotate this Model counterclockwise in the world XY plane by a certain angle. + + Args: + angle: An angle in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + for room in self._rooms: + room.rotate_xy(angle, origin) + for face in self._orphaned_faces: + face.rotate_xy(angle, origin) + for aperture in self._orphaned_apertures: + aperture.rotate_xy(angle, origin) + for door in self._orphaned_doors: + door.rotate_xy(angle, origin) + for shade in self._orphaned_shades: + shade.rotate_xy(angle, origin) + for shade_mesh in self._shade_meshes: + shade_mesh.rotate_xy(angle, origin) + self.properties.rotate_xy(angle, origin)
+ + +
+[docs] + def reflect(self, plane): + """Reflect this Model across a plane with the input normal vector and origin. + + Args: + plane: A ladybug_geometry Plane across which the object will + be reflected. + """ + for room in self._rooms: + room.reflect(plane) + for face in self._orphaned_faces: + face.reflect(plane) + for aperture in self._orphaned_apertures: + aperture.reflect(plane) + for door in self._orphaned_doors: + door.reflect(plane) + for shade in self._orphaned_shades: + shade.reflect(plane) + for shade_mesh in self._shade_meshes: + shade_mesh.reflect(plane) + self.properties.reflect(plane)
+ + +
+[docs] + def scale(self, factor, origin=None): + """Scale this Model by a factor from an origin point. + + Note that using this method does NOT scale the model tolerance and, if + it is desired that this tolerance be scaled with the model geometry, + it must be scaled separately. + + Args: + factor: A number representing how much the object should be scaled. + origin: A ladybug_geometry Point3D representing the origin from which + to scale. If None, it will be scaled from the World origin (0, 0, 0). + """ + for room in self._rooms: + room.scale(factor, origin) + for face in self._orphaned_faces: + face.scale(factor, origin) + for aperture in self._orphaned_apertures: + aperture.scale(factor, origin) + for door in self._orphaned_doors: + door.scale(factor, origin) + for shade in self._orphaned_shades: + shade.scale(factor, origin) + for shade_mesh in self._shade_meshes: + shade_mesh.scale(factor, origin) + self.properties.scale(factor, origin)
+ + +
+[docs] + def generate_exterior_face_grid( + self, dimension, offset=0.1, face_type='Wall', punched_geometry=False): + """Get a gridded Mesh3D offset from the exterior Faces of this Model. + + This will be None if the Model has no exterior Faces. + + Args: + dimension: The dimension of the grid cells as a number. + offset: A number for how far to offset the grid from the base face. + Positive numbers indicate an offset towards the exterior. (Default + is 0.1, which will offset the grid to be 0.1 unit from the faces). + face_type: Text to specify the type of face that will be used to + generate grids. Note that only Faces with Outdoors boundary + conditions will be used, meaning that most Floors will typically + be excluded unless they represent the underside of a cantilever. + Choose from the following. (Default: Wall). + + * Wall + * Roof + * Floor + * All + + punched_geometry: Boolean to note whether the punched_geometry of the faces + should be used (True) with the areas of sub-faces removed from the grid + or the full geometry should be used (False). (Default:False). + """ + # select the correct face type based on the input + face_t = face_type.title() + if face_t == 'Wall': + ft = Wall + elif face_t in ('Roof', 'Roofceiling'): + ft = RoofCeiling + elif face_t == 'All': + ft = (Wall, RoofCeiling, Floor) + elif face_t == 'Floor': + ft = Floor + else: + raise ValueError('Unrecognized face_type "{}".'.format(face_type)) + face_attr = 'punched_geometry' if punched_geometry else 'geometry' + # loop through the faces and generate grids + face_grids = [] + for face in self.faces: + if isinstance(face.type, ft) and \ + isinstance(face.boundary_condition, Outdoors): + try: + f_geo = getattr(face, face_attr) + face_grids.append( + f_geo.mesh_grid(dimension, None, offset, False)) + except AssertionError: # grid tolerance not fine enough + pass + # join the grids together if there are several ones + if len(face_grids) == 1: + return face_grids[0] + elif len(face_grids) > 1: + return Mesh3D.join_meshes(face_grids) + return None
+ + +
+[docs] + def generate_exterior_aperture_grid( + self, dimension, offset=0.1, aperture_type='All'): + """Get a gridded Mesh3D offset from the exterior Apertures of this Model. + + Will be None if the Model has no exterior Apertures. + + Args: + dimension: The dimension of the grid cells as a number. + offset: A number for how far to offset the grid from the base aperture. + Positive numbers indicate an offset towards the exterior while + negative numbers indicate an offset towards the interior, essentially + modeling the value of sun on the building interior. (Default + is 0.1, which will offset the grid to be 0.1 unit from the aperture). + aperture_type: Text to specify the type of Aperture that will be used to + generate grids. Window indicates Apertures in Walls. Choose from + the following. (Default: All). + + * Window + * Skylight + * All + """ + # select the correct face type based on the input + ap_t = aperture_type.title() + if ap_t == 'Window': + ft = Wall + elif ap_t == 'Skylight': + ft = RoofCeiling + elif ap_t == 'All': + ft = (Wall, RoofCeiling, Floor) + else: + raise ValueError('Unrecognized aperture_type "{}".'.format(aperture_type)) + # loop through the faces and generate grids + ap_grids = [] + for face in self.faces: + if isinstance(face.type, ft) and \ + isinstance(face.boundary_condition, Outdoors): + for ap in face.apertures: + try: + ap_grids.append( + ap.geometry.mesh_grid(dimension, None, offset, False)) + except AssertionError: # grid tolerance not fine enough + pass + # join the grids together if there are several ones + if len(ap_grids) == 1: + return ap_grids[0] + elif len(ap_grids) > 1: + return Mesh3D.join_meshes(ap_grids) + return None
+ + +
+[docs] + def simplify_apertures(self, resolve_adjacency=True, tolerance=None): + """Convert all Apertures in this Model to be a simple window ratio. + + This is useful for studies where faster simulation times are desired and + the window ratio is the critical factor driving the results (as opposed + to the detailed geometry of the window). Apertures assigned to concave + Faces will not be simplified given that the Face.apertures_by_ratio method + likely won't improve the cleanliness of the apertures for such cases. + + Args: + resolve_adjacency: Boolean to note whether Room adjacencies should be + re-solved after the Apertures have been simplified. Setting this + to True should ensure that and interior Apertures that are + simplified retain their Surface boundary conditions. If False, + all interior Apertures that have been simplified will have an + Outdoors boundary condition. (Default: True). + tolerance: The maximum difference between point values for them to be + considered equivalent. If None, the Model tolerance will be + used. (Default: None). + """ + tol = tolerance if tolerance else self.tolerance + for room in self._rooms: + room.simplify_apertures(tol) + if resolve_adjacency: + self.solve_adjacency()
+ + +
+[docs] + def rectangularize_apertures( + self, subdivision_distance=None, max_separation=None, merge_all=False, + resolve_adjacency=True, tolerance=None, angle_tolerance=None): + """Convert all Apertures on this Room to be rectangular. + + This is useful when exporting to simulation engines that only accept + rectangular window geometry. This method will always result ing Rooms where + all Apertures are rectangular. However, if the subdivision_distance is not + set, some Apertures may extend past the parent Face or may collide with + one another. + + Args: + subdivision_distance: A number for the resolution at which the + non-rectangular Apertures will be subdivided into smaller + rectangular units. Specifying a number here ensures that the + resulting rectangular Apertures do not extend past the parent + Face or collide with one another. If None, all non-rectangular + Apertures will be rectangularized by taking the bounding rectangle + around the Aperture. (Default: None). + max_separation: A number for the maximum distance between non-rectangular + Apertures at which point the Apertures will be merged into a single + rectangular geometry. This is often helpful when there are several + triangular Apertures that together make a rectangle when they are + merged across their frames. In such cases, this max_separation + should be set to a value that is slightly larger than the window frame. + If None, no merging of Apertures will happen before they are + converted to rectangles. (Default: None). + merge_all: Boolean to note whether all apertures should be merged before + they are rectangularized. If False, only non-rectangular apertures + will be merged before rectangularization. Note that this argument + has no effect when the max_separation is None. (Default: False). + resolve_adjacency: Boolean to note whether Room adjacencies should be + re-solved after the Apertures have been rectangularized. Setting this + to True should ensure that and interior Apertures that are + rectangularized retain their Surface boundary conditions. If False, + all interior Apertures that have been rectangularized will have an + Outdoors boundary condition. (Default: True). + tolerance: The maximum difference between point values for them to be + considered equivalent. If None, the Model tolerance will be + used. (Default: None). + angle_tolerance: The max angle in degrees that the corners of the + rectangle can differ from a right angle before it is not + considered a rectangle. If None, the Model angle_tolerance will be + used. (Default: None). + """ + tol = tolerance if tolerance else self.tolerance + a_tol = angle_tolerance if angle_tolerance else self.angle_tolerance + for room in self._rooms: + room.rectangularize_apertures( + subdivision_distance, max_separation, merge_all, tol, a_tol) + if resolve_adjacency: + self.solve_adjacency()
+ + +
+[docs] + def wall_apertures_by_ratio(self, ratio, tolerance=None): + """Add apertures to all exterior walls given a ratio of aperture to face area. + + Note this method only affects the Models rooms (no orphaned faces) and it + removes any existing apertures and doors on the room's exterior walls. + This method attempts to generate as few apertures as necessary to meet the ratio. + + Args: + ratio: A number between 0 and 1 (but not perfectly equal to 1) + for the desired ratio between aperture area and face area. + tolerance: The maximum difference between point values for them to be + considered a part of a rectangle. This is used in the event that + this face is concave and an attempt to subdivide the face into a + rectangle is made. It does not affect the ability to produce apertures + for convex Faces. If None, the Model tolerance will be + used. (Default: None). + """ + tol = tolerance if tolerance else self.tolerance + for room in self._rooms: + room.wall_apertures_by_ratio(ratio, tol)
+ + +
+[docs] + def skylight_apertures_by_ratio(self, ratio, tolerance=None): + """Add apertures to all exterior roofs given a ratio of aperture to face area. + + Note this method only affects the Models rooms (no orphaned faces) and + removes any existing apertures and overhead doors on the Room's roofs. + This method attempts to generate as few apertures as necessary to meet the ratio. + + Args: + ratio: A number between 0 and 1 (but not perfectly equal to 1) + for the desired ratio between aperture area and face area. + tolerance: The maximum difference between point values for them to be + considered a part of a rectangle. This is used in the event that + this face is concave and an attempt to subdivide the face into a + rectangle is made. It does not affect the ability to produce apertures + for convex Faces. If None, the Model tolerance will be + used. (Default: None). + """ + tol = tolerance if tolerance else self.tolerance + for room in self._rooms: + room.skylight_apertures_by_ratio(ratio, tol)
+ + +
+[docs] + def assign_stories_by_floor_height(self, min_difference=2.0, overwrite=False): + """Assign story properties to the rooms of this Model using their floor heights. + + Stories will be named with a standard convention ('Floor1', 'Floor2', etc.). + + Args: + min_difference: An float value to denote the minimum difference + in floor heights that is considered meaningful. This can be used + to ensure rooms like those representing stair landings are grouped + with floors. Default: 2.0, which means that any difference in + floor heights less than 2.0 will be considered a part of the + same story. This assumption is suitable for models in meters. + overwrite: If True, all story properties of this model's rooms will + be overwritten by this method. If False, this method will only + assign stories to Rooms that do not already have a story identifier + already assigned to them. (Default: False). + + Returns: + A list of the unique story names that were assigned to the input rooms. + """ + if overwrite: + for room in self._rooms: + room.story = None + return Room.stories_by_floor_height(self._rooms, min_difference)
+ + +
+[docs] + def rooms_to_extrusions(self, tolerance=None, angle_tolerance=None): + """Convert all Rooms in the model to extruded floor plates with flat roofs. + + Rooms that already extrusions will be left as they are. For non-extrusion + rooms, all boundary conditions and windows applied to vertical walls will + be preserved and the resulting Room should have a volume that matches the + original Room. If adding back apertures to the room extrusion results in + these apertures going past the parent wall Face, the windows of the Face + will be reduced to a simple window ratio. Any Surface boundary conditions + will be converted to Adiabatic (if honeybee-energy is installed) or + Outdoors (if not). + + This method is useful for exporting to platforms that cannot model Room + geometry beyond simple extrusions. The fact that the resulting room has + window areas and volumes that match the original detailed geometry + should help ensure the results in these platforms are close to what they + would be had the detailed geometry been modeled. + + Args: + tolerance: The maximum difference between point values for them to be + considered equivalent. If None, the Model tolerance will be + used. (Default: None). + angle_tolerance: The max angle in degrees that the corners of the + rectangle can differ from a right angle before it is not + considered a rectangle. If None, the Model angle_tolerance will be + used. (Default: None). + """ + tol = tolerance if tolerance else self.tolerance + a_tol = angle_tolerance if angle_tolerance else self.angle_tolerance + extrusion_rooms = [] + for room in self._rooms: + extrusion_rooms.append(room.to_extrusion(tol, a_tol)) + self._rooms = extrusion_rooms
+ + +
+[docs] + def convert_to_units(self, units='Meters'): + """Convert all of the geometry in this model to certain units. + + This involves scaling the geometry, scaling the Model tolerance, and + changing the Model's units property. + + Args: + units: Text for the units to which the Model geometry should be + converted. Default: Meters. Choose from the following: + + * Meters + * Millimeters + * Feet + * Inches + * Centimeters + """ + if self.units != units: + scale_fac1 = conversion_factor_to_meters(self.units) + scale_fac2 = conversion_factor_to_meters(units) + scale_fac = scale_fac1 / scale_fac2 + self.scale(scale_fac) + self.tolerance = self.tolerance * scale_fac + self.units = units
+ + +
+[docs] + def rooms_to_orphaned(self): + """Convert all Rooms in this Model to orphaned geometry objects. + + This is useful when the energy load balance of Rooms is not important + and they are only significant as context shading. Note that this method + will effectively discount any geometries with a Surface boundary condition + or with an AirBoundary face type. + """ + for room in self._rooms: + for face in room._faces: + face._parent = None + if not isinstance(face.boundary_condition, Surface) and not \ + isinstance(face.type, AirBoundary): + self._orphaned_faces.append(face) + self._rooms = []
+ + +
+[docs] + def remove_degenerate_geometry(self, tolerance=None): + """Remove any degenerate geometry from the model. + + Degenerate geometry refers to any objects that evaluate to less than 3 vertices + when duplicate and colinear vertices are removed at the tolerance. + + Args: + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered distinct. If None, the + Model's tolerance will be used. (Default: None). + """ + tolerance = self.tolerance if tolerance is None else tolerance + adj_dict = {} # dictionary to track adjacent geometries + for room in self.rooms: + try: + r_adj = room.clean_envelope(adj_dict, tolerance=tolerance) + adj_dict.update(r_adj) + except AssertionError as e: # room removed; likely wrong units + error = 'Failed to remove degenerate geometry for Room {}.\n{}'.format( + room.full_id, e) + raise ValueError(error) + self._remove_degenerate_faces(self._orphaned_faces, tolerance) + self._remove_degenerate_faces(self._orphaned_apertures, tolerance) + self._remove_degenerate_faces(self._orphaned_doors, tolerance) + self._remove_degenerate_faces(self._orphaned_shades, tolerance) + sm_to_remove = [] + for i, sm in enumerate(self._shade_meshes): + try: + sm.triangulate_and_remove_degenerate_faces(tolerance) + except AssertionError: # completely degenerate Shade Mesh + sm_to_remove.append(i) + if len(sm_to_remove) != 0: + for ri in reversed(sm_to_remove): + self._shade_meshes.pop(ri)
+ + +
+[docs] + def triangulate_non_planar_quads(self, tolerance=None): + """Triangulate any non-planar orphaned geometry in the model. + + This method will only planarize the orphaned Faces, Apertures, Doors and + Shades that are quadrilaterals, which usually has a minimal impact on results. + It does not impact the Rooms at all. + + Args: + tolerance: The minimum distance from the geometry plane at which the + geometry is not considered planar. If None, the Model's tolerance + will be used. (Default: None). + """ + tolerance = self.tolerance if tolerance is None else tolerance + self._orphaned_apertures = \ + self._triangulate_quad_faces(self._orphaned_apertures, tolerance) + self._orphaned_doors = \ + self._triangulate_quad_faces(self._orphaned_doors, tolerance) + self._orphaned_shades = \ + self._triangulate_quad_faces(self._orphaned_shades, tolerance)
+ + +
+[docs] + def comparison_report(self, other_model, ignore_deleted=False, ignore_added=False): + """Get a dictionary outlining the differences between this model and another. + + The resulting dictionary will only report top-level objects that are different + between this model and the other. If an object has not changed at all, + then it will not show up in the report. + + Changes to geometry are reported separately from changes in metadata + (aka. properties) for each of the top level objects. + + If the Model units or tolerance are different between the two models, + then the units and tolerance of this model will take precedence and + the other_model will be converted to these units and tolerance for + geometry comparison. + + Args: + other_model: A new Model to which this current model will be compared. + ignore_deleted: A boolean to note whether objects that appear in this + current model but not in the other model should be reported. It is + useful to set this to True when the other model represents only a + subset of the current model. (Default: False). + ignore_added: A boolean to note whether objects that appear in the other + model but not in the current model should be reported. (Default: False). + + Returns: + A dictionary of differences between this model and the other model in + the format below. + """ + # make sure the unit systems of the two models align + tol = self.tolerance + if self.units != other_model.units: + other_model = other_model.duplicate() + other_model.convert_to_units(self.units) + # set up lists and dictionaries of objects for comparison + compare_dict = {'type': 'ComparisonReport'} + self_dict = self.top_level_dict + other_dict = other_model.top_level_dict + # loop through the new objects and detect changes between them + changed, added_objs = [], [] + for obj_id, new_obj in other_dict.items(): + try: + exist_obj = self_dict[obj_id] + change_dict = exist_obj._changed_dict(new_obj, tol) + if change_dict is not None: + changed.append(change_dict) + except KeyError: + added_objs.append(new_obj) + compare_dict['changed_objects'] = changed + # include the added objects in the comparison dictionary + if not ignore_added: + added = [] + for new_obj in added_objs: + added.append(new_obj._base_report_dict('AddedObject')) + compare_dict['added_objects'] = added + # include the deleted objects in the comparison dictionary + if not ignore_deleted: + deleted = [] + for obj_id, exist_obj in self_dict.items(): + try: + new_obj = other_dict[obj_id] + except KeyError: + deleted.append(exist_obj._base_report_dict('DeletedObject')) + compare_dict['deleted_objects'] = deleted + return compare_dict
+ + +
+[docs] + def check_all(self, raise_exception=True, detailed=False): + """Check all of the aspects of the Model for possible errors. + + This includes basic properties like adjacency checks and all geometry checks. + Furthermore, all extension attributes will be checked assuming the extension + Model properties have a check_all function. Note that an exception will + always be raised if the model has a tolerance of zero as this means that + no geometry checks can be performed. + + Args: + raise_exception: Boolean to note whether a ValueError should be raised + if any Model errors are found. If False, this method will simply + return a text string with all errors that were found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A text string with all errors that were found or a list if detailed is True. + This string (or list) will be empty if no errors were found. + """ + # set up defaults to ensure the method runs correctly + detailed = False if raise_exception else detailed + msgs = [] + # check that a tolerance has been specified in the model + assert self.tolerance != 0, \ + 'Model must have a non-zero tolerance in order to perform geometry checks.' + assert self.angle_tolerance != 0, \ + 'Model must have a non-zero angle_tolerance to perform geometry checks.' + tol = self.tolerance + ang_tol = self.angle_tolerance + + # perform checks for duplicate identifiers, which might mess with other checks + msgs.append(self.check_duplicate_room_identifiers(False, detailed)) + msgs.append(self.check_duplicate_face_identifiers(False, detailed)) + msgs.append(self.check_duplicate_sub_face_identifiers(False, detailed)) + msgs.append(self.check_duplicate_shade_identifiers(False, detailed)) + msgs.append(self.check_duplicate_shade_mesh_identifiers(False, detailed)) + + # perform several checks for the Honeybee schema geometry rules + msgs.append(self.check_planar(tol, False, detailed)) + msgs.append(self.check_self_intersecting(tol, False, detailed)) + # perform checks for degenerate rooms with a test that removes colinear vertices + for room in self.rooms: + try: + new_room = room.duplicate() # duplicate to avoid editing the original + new_room.remove_colinear_vertices_envelope(tol) + except ValueError as e: + deg_msg = str(e) + if detailed: + deg_msg = [{ + 'type': 'ValidationError', + 'code': '000107', + 'error_type': 'Degenerate Room Volume', + 'extension_type': 'Core', + 'element_type': 'Room', + 'element_id': [room.identifier], + 'element_name': [room.display_name], + 'message': deg_msg + }] + msgs.append(deg_msg) + msgs.append(self.check_degenerate_rooms(tol, False, detailed)) + # perform geometry checks related to parent-child relationships + msgs.append(self.check_sub_faces_valid(tol, ang_tol, False, detailed)) + msgs.append(self.check_sub_faces_overlapping(tol, False, detailed)) + msgs.append(self.check_upside_down_faces(ang_tol, False, detailed)) + msgs.append(self.check_rooms_solid(tol, ang_tol, False, detailed)) + + # perform checks related to adjacency relationships + msgs.append(self.check_room_volume_collisions(tol, False, detailed)) + msgs.append(self.check_missing_adjacencies(False, detailed)) + msgs.append(self.check_matching_adjacent_areas(tol, False, detailed)) + msgs.append(self.check_all_air_boundaries_adjacent(False, detailed)) + + # check the extension attributes + ext_msgs = self._properties._check_extension_attr(detailed) + if detailed: + ext_msgs = [m for m in ext_msgs if isinstance(m, list)] + msgs.extend(ext_msgs) + + # output a final report of errors or raise an exception + full_msgs = [msg for msg in msgs if msg] + if detailed: + return [m for msg in full_msgs for m in msg] + full_msg = '\n'.join(full_msgs) + if raise_exception and len(full_msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_duplicate_room_identifiers(self, raise_exception=True, detailed=False): + """Check that there are no duplicate Room identifiers in the model. + + Args: + raise_exception: Boolean to note whether a ValueError should be raised + if duplicate identifiers are found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + return check_duplicate_identifiers( + self._rooms, raise_exception, 'Room', detailed, '000004', 'Core', + 'Duplicate Room Identifier')
+ + +
+[docs] + def check_duplicate_face_identifiers(self, raise_exception=True, detailed=False): + """Check that there are no duplicate Face identifiers in the model. + + Args: + raise_exception: Boolean to note whether a ValueError should be raised + if duplicate identifiers are found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + return check_duplicate_identifiers_parent( + self.faces, raise_exception, 'Face', detailed, '000003', 'Core', + 'Duplicate Face Identifier')
+ + +
+[docs] + def check_duplicate_sub_face_identifiers(self, raise_exception=True, detailed=False): + """Check that there are no duplicate sub-face identifiers in the model. + + Note that both Apertures and Doors are checked for duplicates since the two + are counted together by EnergyPlus. + + Args: + raise_exception: Boolean to note whether a ValueError should be raised + if duplicate identifiers are found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + sub_faces = self.apertures + self.doors + return check_duplicate_identifiers_parent( + sub_faces, raise_exception, 'SubFace', detailed, '000002', 'Core', + 'Duplicate Sub-Face Identifier')
+ + +
+[docs] + def check_duplicate_shade_identifiers(self, raise_exception=True, detailed=False): + """Check that there are no duplicate Shade identifiers in the model. + + Args: + raise_exception: Boolean to note whether a ValueError should be raised + if duplicate identifiers are found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + return check_duplicate_identifiers_parent( + self.shades, raise_exception, 'Shade', detailed, '000001', 'Core', + 'Duplicate Shade Identifier')
+ + +
+[docs] + def check_duplicate_shade_mesh_identifiers( + self, raise_exception=True, detailed=False): + """Check that there are no duplicate ShadeMesh identifiers in the model. + + Args: + raise_exception: Boolean to note whether a ValueError should be raised + if duplicate identifiers are found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + return check_duplicate_identifiers( + self._shade_meshes, raise_exception, 'ShadeMesh', detailed, '000001', 'Core', + 'Duplicate ShadeMesh Identifier')
+ + +
+[docs] + def check_planar(self, tolerance=None, raise_exception=True, detailed=False): + """Check that all of the Model's geometry components are planar. + + This includes all of the Model's Faces, Apertures, Doors and Shades. + + Args: + tolerance: The minimum distance between a given vertex and a the + object's plane at which the vertex is said to lie in the plane. + If None, the Model tolerance will be used. (Default: None). + raise_exception: Boolean to note whether an ValueError should be + raised if a vertex does not lie within the object's plane. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + tolerance = self.tolerance if tolerance is None else tolerance + detailed = False if raise_exception else detailed + msgs = [] + for face in self.faces: + msgs.append(face.check_planar(tolerance, False, detailed)) + for shd in self.shades: + msgs.append(shd.check_planar(tolerance, False, detailed)) + for ap in self.apertures: + msgs.append(ap.check_planar(tolerance, False, detailed)) + for dr in self.doors: + msgs.append(dr.check_planar(tolerance, False, detailed)) + full_msgs = [msg for msg in msgs if msg] + if detailed: + return [m for msg in full_msgs for m in msg] + full_msg = '\n'.join(full_msgs) + if raise_exception and len(full_msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_self_intersecting(self, tolerance=None, raise_exception=True, + detailed=False): + """Check that no edges of the Model's geometry components self-intersect. + + This includes all of the Model's Faces, Apertures, Doors and Shades. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. If None, the + Model tolerance will be used. (Default: None). + raise_exception: If True, a ValueError will be raised if an object + intersects with itself (like a bowtie). (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + tolerance = self.tolerance if tolerance is None else tolerance + detailed = False if raise_exception else detailed + msgs = [] + for room in self.rooms: + msgs.append(room.check_self_intersecting(tolerance, False, detailed)) + for face in self.orphaned_faces: + msgs.append(face.check_self_intersecting(tolerance, False, detailed)) + for shd in self.orphaned_shades: + msgs.append(shd.check_self_intersecting(tolerance, False, detailed)) + for ap in self.orphaned_apertures: + msgs.append(ap.check_self_intersecting(tolerance, False, detailed)) + for dr in self.orphaned_doors: + msgs.append(dr.check_self_intersecting(tolerance, False, detailed)) + full_msgs = [msg for msg in msgs if msg] + if detailed: + return [m for msg in full_msgs for m in msg] + full_msg = '\n'.join(full_msgs) + if raise_exception and len(full_msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_degenerate_rooms( + self, tolerance=None, raise_exception=True, detailed=False): + """Check whether there are degenerate Rooms (with zero volume) within the Model. + + Args: + tolerance: The maximum difference between x, y, and z values + at which face vertices are considered equivalent. If None, the + Model tolerance will be used. (Default: None). + raise_exception: Boolean to note whether a ValueError should be raised + if degenerate Rooms are found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + tolerance = self.tolerance if tolerance is None else tolerance + detailed = False if raise_exception else detailed + msgs = [] + for room in self._rooms: + msg = room.check_degenerate(tolerance, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + if detailed: + return msgs + full_msg = '\n'.join(msgs) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_sub_faces_valid(self, tolerance=None, angle_tolerance=None, + raise_exception=True, detailed=False): + """Check that model's sub-faces are co-planar with faces and in their boundary. + + Note this does not check the planarity of the sub-faces themselves, whether + they self-intersect, or whether they have a non-zero area. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. If None, the + Model tolerance will be used. (Default: None). + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered coplanar. + If None, the Model angle_tolerance will be used. (Default: None). + raise_exception: Boolean to note whether a ValueError should be raised + if an sub-face is not valid. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + tolerance = self.tolerance if tolerance is None else tolerance + angle_tolerance = self.angle_tolerance \ + if angle_tolerance is None else angle_tolerance + detailed = False if raise_exception else detailed + msgs = [] + for rm in self._rooms: + msg = rm.check_sub_faces_valid(tolerance, angle_tolerance, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + for f in self._orphaned_faces: + msg = f.check_sub_faces_valid(tolerance, angle_tolerance, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + if detailed: + return msgs + full_msg = '\n'.join(msgs) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_sub_faces_overlapping( + self, tolerance=None, raise_exception=True, detailed=False): + """Check that model's sub-faces do not overlap with one another. + + Args: + tolerance: The minimum distance that two sub-faces must overlap in order + for them to be considered overlapping and invalid. If None, the + Model tolerance will be used. (Default: None). + raise_exception: Boolean to note whether a ValueError should be raised + if a sub-faces overlap with one another. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + tolerance = self.tolerance if tolerance is None else tolerance + detailed = False if raise_exception else detailed + msgs = [] + for rm in self._rooms: + msg = rm.check_sub_faces_overlapping(tolerance, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + for f in self._orphaned_faces: + msg = f.check_sub_faces_overlapping(tolerance, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + if detailed: + return msgs + full_msg = '\n'.join(msgs) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_upside_down_faces( + self, angle_tolerance=None, raise_exception=True, detailed=False): + """Check that the Model's Faces have the correct direction for the face type. + + This method will only report Floors that are pointing upwards or RoofCeilings + that are pointed downwards. These cases are likely modeling errors and are in + danger of having their vertices flipped by EnergyPlus, causing them to + not see the sun. + + Args: + angle_tolerance: The max angle in degrees that the Face normal can + differ from up or down before it is considered a case of a downward + pointing RoofCeiling or upward pointing Floor. If None, it + will be the model angle tolerance. (Default: None). + raise_exception: Boolean to note whether an ValueError should be + raised if the Face is an an upward pointing Floor or a downward + pointing RoofCeiling. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + a_tol = self.angle_tolerance if angle_tolerance is None else angle_tolerance + detailed = False if raise_exception else detailed + msgs = [] + for rm in self._rooms: + msg = rm.check_upside_down_faces(a_tol, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + if detailed: + return msgs + full_msg = '\n'.join(msgs) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_rooms_solid(self, tolerance=None, angle_tolerance=None, + raise_exception=True, detailed=False): + """Check whether the Model's rooms are closed solid to within tolerances. + + Args: + tolerance: tolerance: The maximum difference between x, y, and z values + at which face vertices are considered equivalent. If None, the Model + tolerance will be used. (Default: None). + angle_tolerance: The max angle difference in degrees that vertices are + allowed to differ from one another in order to consider them colinear. + If None, the Model angle_tolerance will be used. (Default: None). + raise_exception: Boolean to note whether a ValueError should be raised + if the room geometry does not form a closed solid. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + tolerance = self.tolerance if tolerance is None else tolerance + angle_tolerance = self.angle_tolerance \ + if angle_tolerance is None else angle_tolerance + detailed = False if raise_exception else detailed + msgs = [] + for room in self._rooms: + msg = room.check_solid(tolerance, angle_tolerance, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + if detailed: + return msgs + full_msg = '\n'.join(msgs) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_room_volume_collisions( + self, tolerance=None, raise_exception=True, detailed=False): + """Check whether the Model's rooms collide with one another beyond the tolerance. + + Args: + tolerance: tolerance: The maximum difference between x, y, and z values + at which face vertices are considered equivalent. If None, the Model + tolerance will be used. (Default: None). + raise_exception: Boolean to note whether a ValueError should be raised + if the room geometry does not form a closed solid. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + # set default values + tolerance = self.tolerance if tolerance is None else tolerance + detailed = False if raise_exception else detailed + # group the rooms by their floor heights to enable collision checking + if len(self.rooms) == 0: + return [] if detailed else '' + room_groups, _ = Room.group_by_floor_height(self.rooms, tolerance) + # loop trough the groups and detect collisions + msgs = [] + for rg in room_groups: + msg = Room.check_room_volume_collisions(rg, tolerance, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + if detailed: + return msgs + full_msg = '\n'.join(msgs) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_missing_adjacencies(self, raise_exception=True, detailed=False): + """Check that all Faces Apertures, and Doors have adjacent objects in the model. + + Args: + raise_exception: Boolean to note whether a ValueError should be raised + if invalid adjacencies are found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + detailed = False if raise_exception else detailed + # loop through all objects and get their adjacent object + room_ids = [] + face_bc_ids, face_set = [], set() + ap_bc_ids, ap_set = [], set() + door_bc_ids, dr_set = [], set() + sr = [] + for room in self._rooms: + for face in room._faces: + if isinstance(face.boundary_condition, Surface): + sr.append(self._self_adj_check( + 'Face', face, face_bc_ids, room_ids, face_set, detailed)) + for ap in face.apertures: + assert isinstance(ap.boundary_condition, Surface), \ + 'Aperture "{}" must have Surface boundary condition ' \ + 'if the parent Face has a Surface BC.'.format(ap.full_id) + sr.append(self._self_adj_check( + 'Aperture', ap, ap_bc_ids, room_ids, ap_set, detailed)) + for dr in face.doors: + assert isinstance(dr.boundary_condition, Surface), \ + 'Door "{}" must have Surface boundary condition ' \ + 'if the parent Face has a Surface BC.'.format(dr.full_id) + sr.append(self._self_adj_check( + 'Door', dr, door_bc_ids, room_ids, dr_set, detailed)) + # check to see if the adjacent objects are in the model + mr = self._missing_adj_check(self.rooms_by_identifier, room_ids) + mf = self._missing_adj_check(self.faces_by_identifier, face_bc_ids) + ma = self._missing_adj_check(self.apertures_by_identifier, ap_bc_ids) + md = self._missing_adj_check(self.doors_by_identifier, door_bc_ids) + # if not, go back and find the original object with the missing BC object + msgs = [] + if len(mr) != 0 or len(mf) != 0 or len(ma) != 0 or len(md) != 0: + for room in self._rooms: + for face in room._faces: + if isinstance(face.boundary_condition, Surface): + bc_obj, bc_room = self._adj_objects(face) + if bc_obj in mf: + self._missing_adj_msg( + msgs, face, bc_obj, 'Face', 'Face', detailed) + if bc_room in mr: + self._missing_adj_msg( + msgs, face, bc_room, 'Face', 'Room', detailed) + for ap in face.apertures: + bc_obj, bc_room = self._adj_objects(ap) + if bc_obj in ma: + self._missing_adj_msg( + msgs, ap, bc_obj, 'Aperture', 'Aperture', detailed) + if bc_room in mr: + self._missing_adj_msg( + msgs, ap, bc_room, 'Aperture', 'Room', detailed) + for dr in face.doors: + bc_obj, bc_room = self._adj_objects(dr) + if bc_obj in md: + self._missing_adj_msg( + msgs, dr, bc_obj, 'Door', 'Door', detailed) + if bc_room in mr: + self._missing_adj_msg( + msgs, dr, bc_room, 'Door', 'Room', detailed) + # return the final error messages + all_msgs = [m for m in sr + msgs if m] + if detailed: + return [m for msg in all_msgs for m in msg] + msg = '\n'.join(all_msgs) + if msg != '' and raise_exception: + raise ValueError(msg) + return msg
+ + +
+[docs] + def check_matching_adjacent_areas(self, tolerance=None, raise_exception=True, + detailed=False): + """Check that all adjacent Faces have areas that match within the tolerance. + + This is required for energy simulation in order to get matching heat flow + across adjacent Faces. Otherwise, conservation of energy is violated. + Note that, if there are missing adjacencies in the model, the message from + this method will simply note this fact without reporting on mis-matched areas. + + Args: + tolerance: tolerance: The maximum difference between x, y, and z values + at which face vertices are considered equivalent. If None, the Model + tolerance will be used. (Default: None). + raise_exception: Boolean to note whether a ValueError should be raised + if invalid adjacencies are found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + tolerance = self.tolerance if tolerance is None else tolerance + detailed = False if raise_exception else detailed + + # first gather all interior faces in the model and their adjacent object + base_faces, adj_ids = [], [] + for room in self._rooms: + for face in room._faces: + if isinstance(face.boundary_condition, Surface): + base_faces.append(face) + adj_ids.append(face.boundary_condition.boundary_condition_object) + + # get the adjacent faces + try: + adj_faces = self.faces_by_identifier(adj_ids) + except ValueError as e: # the model has missing adjacencies + if detailed: # the user will get a more detailed error in honeybee-core + return [] + else: + msg = 'Matching adjacent areas could not be verified because ' \ + 'of missing adjacencies in the model. \n{}'.format(e) + if raise_exception: + raise ValueError(msg) + return msg + + # loop through the adjacent face pairs and report if areas are not matched + full_msgs, reported_items = [], set() + for base_f, adj_f in zip(base_faces, adj_faces): + if (base_f.identifier, adj_f.identifier) in reported_items: + continue + two_tol = 2 * tolerance + tol_area = math.sqrt(base_f.area) * two_tol + tol_area = 2 * two_tol if tol_area < 2 * two_tol else tol_area + if abs(base_f.area - adj_f.area) > tol_area: + f_msg = 'Face "{}" with area {} is adjacent to Face "{}" with area {}.' \ + ' This difference is greater than what is permitted by {} ' \ + 'tolerance ({}).'.format( + base_f.full_id, base_f.area, adj_f.full_id, adj_f.area, + tolerance, tol_area + ) + f_msg = self._validation_message_child( + f_msg, base_f, detailed, '000205', + error_type='Mismatched Area Adjacency') + if detailed: + f_msg['element_id'].append(adj_f.identifier) + f_msg['element_name'].append(adj_f.display_name) + parents = [] + rel_obj = adj_f + while getattr(rel_obj, '_parent', None) is not None: + rel_obj = getattr(rel_obj, '_parent') + par_dict = { + 'parent_type': rel_obj.__class__.__name__, + 'id': rel_obj.identifier, + 'name': rel_obj.display_name + } + parents.append(par_dict) + f_msg['parents'].append(parents) + full_msgs.append(f_msg) + reported_items.add((adj_f.identifier, base_f.identifier)) + else: # check to ensure the shapes are the same when vertices are removed + try: + base_f_geo = base_f.geometry.remove_colinear_vertices(tolerance) + adj_f_geo = adj_f.geometry.remove_colinear_vertices(tolerance) + except AssertionError: # degenerate Faces to ignore + continue + if len(base_f_geo) != len(adj_f_geo): + f_msg = 'Face "{}" is a shape with {} distinct vertices and is ' \ + 'adjacent to Face "{}", which has {} distinct vertices' \ + ' within the model tolerance of {}.'.format( + base_f.full_id, len(base_f_geo), + adj_f.full_id, len(adj_f_geo), tolerance + ) + f_msg = self._validation_message_child( + f_msg, base_f, detailed, '000205', + error_type='Mismatched Area Adjacency') + if detailed: + f_msg['element_id'].append(adj_f.identifier) + f_msg['element_name'].append(adj_f.display_name) + parents = [] + rel_obj = adj_f + while getattr(rel_obj, '_parent', None) is not None: + rel_obj = getattr(rel_obj, '_parent') + par_dict = { + 'parent_type': rel_obj.__class__.__name__, + 'id': rel_obj.identifier, + 'name': rel_obj.display_name + } + parents.append(par_dict) + f_msg['parents'].append(parents) + full_msgs.append(f_msg) + reported_items.add((adj_f.identifier, base_f.identifier)) + + # ensure that adjacent sub-faces have matching areas + if base_f.has_sub_faces: + base_subs, adj_subs, sub_ids = [], [], [] + for sf in base_f.sub_faces: + if isinstance(sf.boundary_condition, Surface): + base_subs.append(sf) + sub_ids.append(sf.boundary_condition.boundary_condition_object) + missing_sfs = False + for obj_id in sub_ids: + for adj_sf in adj_f.sub_faces: + if adj_sf.identifier == obj_id: + adj_subs.append(adj_sf) + break + else: # missing sub-face adjacencies will get reported elsewhere + missing_sfs = True + if not missing_sfs: + for base_sf, adj_sf in zip(base_subs, adj_subs): + two_tol = 2 * tolerance + tol_area = math.sqrt(base_sf.area) * two_tol + tol_area = 2 * two_tol if tol_area < 2 * two_tol else tol_area + if abs(base_sf.area - adj_sf.area) > tol_area: + f_msg = 'SubFace "{}" with area {} is adjacent to ' \ + 'SubFace "{}" with area {}. This difference is greater ' \ + 'than what is permitted at {} tolerance ({}).'.format( + base_sf.full_id, base_sf.area, + adj_sf.full_id, adj_sf.area, tolerance, tol_area + ) + f_msg = self._validation_message_child( + f_msg, base_sf, detailed, '000205', + error_type='Mismatched Area Adjacency') + if detailed: + f_msg['element_id'].append(adj_sf.identifier) + f_msg['element_name'].append(adj_sf.display_name) + parents = [] + rel_obj = adj_sf + while getattr(rel_obj, '_parent', None) is not None: + rel_obj = getattr(rel_obj, '_parent') + par_dict = { + 'parent_type': rel_obj.__class__.__name__, + 'id': rel_obj.identifier, + 'name': rel_obj.display_name + } + parents.append(par_dict) + f_msg['parents'].append(parents) + full_msgs.append(f_msg) + reported_items.add((adj_f.identifier, base_f.identifier)) + + # return all of the validation error messages that were gathered + full_msg = full_msgs if detailed else '\n'.join(full_msgs) + if raise_exception and len(full_msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_all_air_boundaries_adjacent(self, raise_exception=True, detailed=False): + """Check that all Faces with the AirBoundary type are adjacent to other Faces. + + This is a requirement for energy simulation. + + Args: + raise_exception: Boolean to note whether a ValueError should be raised + if an AirBoundary without an adjacency is found. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + detailed = False if raise_exception else detailed + msgs = [] + for face in self.faces: + if isinstance(face.type, AirBoundary) and not \ + isinstance(face.boundary_condition, Surface): + msg = 'Face "{}" is an AirBoundary but is not adjacent ' \ + 'to another Face.'.format(face.full_id) + msg = self._validation_message_child( + msg, face, detailed, '000206', error_type='Non-Adjacent AirBoundary') + msgs.append(msg) + if detailed: + return msgs + full_msg = '\n'.join(msgs) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def triangulated_apertures(self): + """Get triangulated versions of the model Apertures that have more than 4 sides. + + This is necessary for energy simulation since EnergyPlus cannot accept + sub-faces with more than 4 sides. Note that this method does not alter the + Apertures within the Model object but just returns a list of modified + Apertures that all have 3 or 4 sides. + + Returns: + A tuple with two elements + + - triangulated_apertures: A list of lists where each list is a set of + triangle Apertures meant to replace an Aperture with more than + 4 sides in the model. + + - parents_to_edit: An list of lists that parallels the triangulated + apertures in that each item represents an Aperture that has been + triangulated in the model. However, each of these lists holds between + 1 and 3 values for the identifiers of the original aperture and parents + of the aperture. This information is intended to help edit parent + faces that have had their child faces triangulated. The 3 values + are as follows: + + * 0 = The identifier of the original Aperture that was triangulated. + * 1 = The identifier of the parent Face of the original Aperture + (if it exists). + * 2 = The identifier of the parent Room of the parent Face of the + original Aperture (if it exists). + """ + triangulated_apertures = [] + parents_to_edit = [] + all_apertures = self.apertures + adj_check = [] # confirms when interior apertures are triangulated by adjacency + for ap in all_apertures: + if len(ap.geometry) <= 4: + pass + elif ap.identifier not in adj_check: + # generate the new triangulated apertures + ap_mesh3d = ap.triangulated_mesh3d + new_verts = [[ap_mesh3d[v] for v in face] for face in ap_mesh3d.faces] + new_ap_geo = [Face3D(verts, ap.geometry.plane) for verts in new_verts] + new_ap_geo = self._remove_sliver_geometries(new_ap_geo) + new_aps, parent_edit_info = self._replace_aperture(ap, new_ap_geo) + triangulated_apertures.append(new_aps) + if parent_edit_info is not None: + parents_to_edit.append(parent_edit_info) + # coordinate new apertures with any adjacent apertures + if isinstance(ap.boundary_condition, Surface): + bc_obj_identifier = ap.boundary_condition.boundary_condition_object + for other_ap in all_apertures: + if other_ap.identifier == bc_obj_identifier: + adj_ap = other_ap + break + new_adj_ap_geo = [face.flip() for face in new_ap_geo] + new_adj_aps, edit_in = self._replace_aperture(adj_ap, new_adj_ap_geo) + for new_ap, new_adj_ap in zip(new_aps, new_adj_aps): + new_ap.set_adjacency(new_adj_ap) + triangulated_apertures.append(new_adj_aps) + if edit_in is not None: + parents_to_edit.append(edit_in) + adj_check.append(adj_ap.identifier) + return triangulated_apertures, parents_to_edit
+ + +
+[docs] + def triangulated_doors(self): + """Get triangulated versions of the model Doors that have more than 4 sides. + + This is necessary for energy simulation since EnergyPlus cannot accept + sub-faces with more than 4 sides. Note that this method does not alter the + Doors within the Model object but just returns a list of Doors that + all have 3 or 4 sides. + + Returns: + A tuple with two elements + + - triangulated_doors: A list of lists where each list is a set of triangle + Doors meant to replace a Door with more than 4 sides in the model. + + - parents_to_edit: An list of lists that parallels the triangulated_doors + in that each item represents a Door that has been triangulated + in the model. However, each of these lists holds between 1 and 3 values + for the identifiers of the original door and parents of the door. + This information is intended to help edit parent faces that have had + their child faces triangulated. The 3 values are as follows: + + * 0 = The identifier of the original Door that was triangulated. + * 1 = The identifier of the parent Face of the original Door + (if it exists). + * 2 = The identifier of the parent Room of the parent Face of the + original Door (if it exists). + """ + triangulated_doors = [] + parents_to_edit = [] + all_doors = self.doors + adj_check = [] # confirms when interior doors are triangulated by adjacency + for dr in all_doors: + if len(dr.geometry) <= 4: + pass + elif dr.identifier not in adj_check: + # generate the new triangulated doors + dr_mesh3d = dr.triangulated_mesh3d + new_verts = [[dr_mesh3d[v] for v in face] for face in dr_mesh3d.faces] + new_dr_geo = [Face3D(verts, dr.geometry.plane) for verts in new_verts] + new_dr_geo = self._remove_sliver_geometries(new_dr_geo) + new_drs, parent_edit_info = self._replace_door(dr, new_dr_geo) + triangulated_doors.append(new_drs) + if parent_edit_info is not None: + parents_to_edit.append(parent_edit_info) + # coordinate new doors with any adjacent doors + if isinstance(dr.boundary_condition, Surface): + bc_obj_identifier = dr.boundary_condition.boundary_condition_object + for other_dr in all_doors: + if other_dr.identifier == bc_obj_identifier: + adj_dr = other_dr + break + new_adj_dr_geo = [face.flip() for face in new_dr_geo] + new_adj_drs, edit_in = self._replace_door(adj_dr, new_adj_dr_geo) + for new_dr, new_adj_dr in zip(new_drs, new_adj_drs): + new_dr.set_adjacency(new_adj_dr) + triangulated_doors.append(new_adj_drs) + if edit_in is not None: + parents_to_edit.append(edit_in) + adj_check.append(adj_dr.identifier) + return triangulated_doors, parents_to_edit
+ + + def _remove_sliver_geometries(self, face3ds): + """Remove sliver geometries from a list of Face3Ds.""" + clean_face3ds = [] + for face in face3ds: + try: + if face.area >= self.tolerance: + clean_face3ds.append(face.remove_colinear_vertices(self.tolerance)) + except ValueError: + pass # degenerate triangle; remove it + return clean_face3ds + + def _remove_degenerate_faces(self, hb_objs, tolerance): + """Remove degenerate Faces, Apertures, Doors, or Shades from a list.""" + i_to_remove = [] + for i, face in enumerate(hb_objs): + try: + face.remove_colinear_vertices(tolerance) + except ValueError: # degenerate face found! + i_to_remove.append(i) + for i in reversed(i_to_remove): + hb_objs.pop(i) + + def _triangulate_quad_faces(self, hb_objs, tolerance): + """Triangulate quad geometries.""" + clean_objects = [] + for i, geo_obj in enumerate(hb_objs): + geo = geo_obj.geometry + if len(geo.vertices) == 4 and not geo.check_planar(tolerance, False): + verts = geo.vertices + obj_1 = geo_obj.duplicate() + obj_1.identifier = '{}..0'.format(geo_obj.identifier) + obj_1._geometry = Face3D((verts[0], verts[1], verts[2])) + clean_objects.append(obj_1) + obj_2 = geo_obj.duplicate() + obj_2.identifier = '{}..1'.format(geo_obj.identifier) + obj_2._geometry = Face3D((verts[2], verts[3], verts[0])) + clean_objects.append(obj_2) + else: + clean_objects.append(geo_obj) + return clean_objects + + def _replace_aperture(self, original_ap, new_ap_geo): + """Get new Apertures generated from new_ap_geo and the properties of original_ap. + + Note that this method does not re-link the new apertures to new adjacent + apertures in the model. This must be done with the returned apertures. + + Args: + original_ap: The original Aperture object from which properties + are borrowed. + new_ap_geo: A list of ladybug_geometry Face3D objects that will be used + to generate the new Aperture objects. + + Returns: + A tuple with two elements + + - new_aps: A list of the new Aperture objects. + + - parent_edit_info: An array of up to 3 values meant to help edit + parents that have had their child faces triangulated. The 3 values + are as follows: + + * 0 = The identifier of the original Aperture that was triangulated. + * 1 = The identifier of the parent Face of the original Aperture + (if it exists). + * 2 = The identifier of the parent Room of the parent Face of the + original Aperture (if it exists). + """ + # make the new Apertures and add them to the model + new_aps = [] + for i, ap_face in enumerate(new_ap_geo): + new_ap = Aperture('{}..{}'.format(original_ap.identifier, i), + ap_face, None, original_ap.is_operable) + new_ap._properties = original_ap._properties # transfer extension properties + if original_ap.has_parent: + new_ap._parent = original_ap.parent + new_aps.append(new_ap) + + # transfer over any child shades to the first triangulated object + if len(original_ap._indoor_shades) != 0: + new_shds = [shd.duplicate() for shd in original_ap._indoor_shades] + new_aps[0].add_indoor_shades(new_shds) + if len(original_ap._outdoor_shades) != 0: + new_shds = [shd.duplicate() for shd in original_ap._outdoor_shades] + new_aps[0].add_outdoor_shades(new_shds) + + # create the parent edit info + parent_edit_info = [original_ap.identifier] + if original_ap.has_parent: + parent_edit_info.append(original_ap.parent.identifier) + if original_ap.parent.has_parent: + parent_edit_info.append(original_ap.parent.parent.identifier) + return new_aps, parent_edit_info + + def _replace_door(self, original_dr, new_dr_geo): + """Get new Doors generated from new_dr_geo and the properties of original_dr. + + Note that this method does not re-link the new doors to new adjacent + doors in the model. This must be done with the returned doors. + + Args: + original_dr: The original Door object from which properties + are borrowed. + new_dr_geo: A list of ladybug_geometry Face3D objects that will be used + to generate the new Door objects. + + Returns: + A tuple with four elements + + - new_drs: A list of the new Door objects. + + - parent_edit_info: An array of up to 3 values meant to help edit + parents that have had their child faces triangulated. The 3 values + are as follows: + + * 0 = The identifier of the original Door that was triangulated. + * 1 = The identifier of the parent Face of the original Door + (if it exists). + * 2 = The identifier of the parent Room of the parent Face of the + original Door (if it exists). + """ + # make the new doors and add them to the model + new_drs = [] + for i, dr_face in enumerate(new_dr_geo): + new_dr = Door('{}..{}'.format(original_dr.identifier, i), dr_face) + new_dr._properties = original_dr._properties # transfer extension properties + if original_dr.has_parent: + new_dr._parent = original_dr.parent + new_drs.append(new_dr) + + # transfer over any child shades to the first triangulated object + if len(original_dr._indoor_shades) != 0: + new_shds = [shd.duplicate() for shd in original_dr._indoor_shades] + new_drs[0].add_indoor_shades(new_shds) + if len(original_dr._outdoor_shades) != 0: + new_shds = [shd.duplicate() for shd in original_dr._outdoor_shades] + new_drs[0].add_outdoor_shades(new_shds) + + # create the parent edit info + parent_edit_info = [original_dr.identifier] + if original_dr.has_parent: + parent_edit_info.append(original_dr.parent.identifier) + if original_dr.parent.has_parent: + parent_edit_info.append(original_dr.parent.parent.identifier) + return new_drs, parent_edit_info + + @property + def to(self): + """Model writer object. + + Use this method to access Writer class to write the model in other formats. + + Usage: + + .. code-block:: python + + model.to.idf(model) -> idf string. + model.to.radiance(model) -> Radiance string. + """ + return writer + +
+[docs] + def to_dict(self, included_prop=None, triangulate_sub_faces=False, + include_plane=True): + """Return Model as a dictionary. + + Args: + included_prop: List of properties to filter keys that must be included in + output dictionary. For example ['energy'] will include 'energy' key if + available in properties to_dict. By default all the keys will be + included. To exclude all the keys from extensions use an empty list. + triangulate_sub_faces: Boolean to note whether sub-faces (including + Apertures and Doors) should be triangulated if they have more than + 4 sides (True) or whether they should be left as they are (False). + This triangulation is necessary when exporting directly to EnergyPlus + since it cannot accept sub-faces with more than 4 vertices. Note that + setting this to True will only triangulate sub-faces with parent Faces + that also have parent Rooms since orphaned Apertures and Faces are + not relevant for energy simulation. (Default: False). + include_plane: Boolean to note wether the planes of the Face3Ds should be + included in the output. This can preserve the orientation of the + X/Y axes of the planes but is not required and can be removed to + keep the dictionary smaller. (Default: True). + """ + # write all of the geometry objects and their properties + base = {'type': 'Model'} + base['identifier'] = self.identifier + base['display_name'] = self.display_name + base['units'] = self.units + base['properties'] = self.properties.to_dict(included_prop) + if self._rooms != []: + base['rooms'] = [r.to_dict(True, included_prop, include_plane) + for r in self._rooms] + if self._orphaned_faces != []: + base['orphaned_faces'] = [f.to_dict(True, included_prop, include_plane) + for f in self._orphaned_faces] + if self._orphaned_apertures != []: + base['orphaned_apertures'] = [ap.to_dict(True, included_prop, include_plane) + for ap in self._orphaned_apertures] + if self._orphaned_doors != []: + base['orphaned_doors'] = [dr.to_dict(True, included_prop, include_plane) + for dr in self._orphaned_doors] + if self._orphaned_shades != []: + base['orphaned_shades'] = [shd.to_dict(True, included_prop, include_plane) + for shd in self._orphaned_shades] + if self._shade_meshes != []: + base['shade_meshes'] = [sm.to_dict(True, included_prop) + for sm in self._shade_meshes] + if self.tolerance != 0: + base['tolerance'] = self.tolerance + if self.angle_tolerance != 0: + base['angle_tolerance'] = self.angle_tolerance + + # triangulate sub-faces if this was requested + if triangulate_sub_faces: + apertures, parents_to_edit = self.triangulated_apertures() + for tri_aps, edit_infos in zip(apertures, parents_to_edit): + if len(edit_infos) == 3: + for room in base['rooms']: + if room['identifier'] == edit_infos[2]: + break + for face in room['faces']: + if face['identifier'] == edit_infos[1]: + break + for i, ap in enumerate(face['apertures']): + if ap['identifier'] == edit_infos[0]: + break + del face['apertures'][i] + face['apertures'].extend( + [a.to_dict(True, included_prop) for a in tri_aps]) + doors, parents_to_edit = self.triangulated_doors() + for tri_drs, edit_infos in zip(doors, parents_to_edit): + if len(edit_infos) == 3: + for room in base['rooms']: + if room['identifier'] == edit_infos[2]: + break + for face in room['faces']: + if face['identifier'] == edit_infos[1]: + break + for i, ap in enumerate(face['doors']): + if ap['identifier'] == edit_infos[0]: + break + del face['doors'][i] + face['doors'].extend( + [dr.to_dict(True, included_prop) for dr in tri_drs]) + + # write in the optional keys if they are not None + if self.user_data is not None: + base['user_data'] = self.user_data + if folders.honeybee_schema_version is not None: + base['version'] = folders.honeybee_schema_version_str + + return base
+ + +
+[docs] + def to_hbjson(self, name=None, folder=None, indent=None, + included_prop=None, triangulate_sub_faces=False): + """Write Honeybee model to HBJSON. + + Args: + name: A text string for the name of the HBJSON file. If None, the model + identifier wil be used. (Default: None). + folder: A text string for the directory where the HBJSON will be written. + If unspecified, the default simulation folder will be used. This + is usually at "C:\\Users\\USERNAME\\simulation." + indent: A positive integer to set the indentation used in the resulting + HBJSON file. (Default: None). + included_prop: List of properties to filter keys that must be included in + output dictionary. For example ['energy'] will include 'energy' key if + available in properties to_dict. By default all the keys will be + included. To exclude all the keys from extensions use an empty list. + triangulate_sub_faces: Boolean to note whether sub-faces (including + Apertures and Doors) should be triangulated if they have more than + 4 sides (True) or whether they should be left as they are (False). + This triangulation is necessary when exporting directly to EnergyPlus + since it cannot accept sub-faces with more than 4 vertices. Note that + setting this to True will only triangulate sub-faces with parent Faces + that also have parent Rooms since orphaned Apertures and Faces are + not relevant for energy simulation. (Default: False). + """ + # create dictionary from the Honeybee Model + hb_dict = self.to_dict(included_prop=included_prop, + triangulate_sub_faces=triangulate_sub_faces) + + # set up a name and folder for the HBJSON + if name is None: + name = self.identifier + file_name = name if name.lower().endswith('.hbjson') or \ + name.lower().endswith('.json') else '{}.hbjson'.format(name) + folder = folder if folder is not None else folders.default_simulation_folder + hb_file = os.path.join(folder, file_name) + # write HBJSON + with open(hb_file, 'w') as fp: + json.dump(hb_dict, fp, indent=indent) + return hb_file
+ + +
+[docs] + def to_hbpkl(self, name=None, folder=None, included_prop=None, + triangulate_sub_faces=False): + """Write Honeybee model to compressed pickle file (HBpkl). + + Args: + name: A text string for the name of the pickle file. If None, the model + identifier wil be used. (Default: None). + folder: A text string for the directory where the pickle file will be + written. If unspecified, the default simulation folder will be used. + This is usually at "C:\\Users\\USERNAME\\simulation." + included_prop: List of properties to filter keys that must be included in + output dictionary. For example ['energy'] will include 'energy' key if + available in properties to_dict. By default all the keys will be + included. To exclude all the keys from extensions use an empty list. + triangulate_sub_faces: Boolean to note whether sub-faces (including + Apertures and Doors) should be triangulated if they have more than + 4 sides (True) or whether they should be left as they are (False). + This triangulation is necessary when exporting directly to EnergyPlus + since it cannot accept sub-faces with more than 4 vertices. Note that + setting this to True will only triangulate sub-faces with parent Faces + that also have parent Rooms since orphaned Apertures and Faces are + not relevant for energy simulation. (Default: False). + """ + # create dictionary from the Honeybee Model + hb_dict = self.to_dict(included_prop=included_prop, + triangulate_sub_faces=triangulate_sub_faces) + + # set up a name and folder for the HBpkl + if name is None: + name = self.identifier + file_name = name if name.lower().endswith('.hbpkl') or \ + name.lower().endswith('.pkl') else '{}.hbpkl'.format(name) + folder = folder if folder is not None else folders.default_simulation_folder + hb_file = os.path.join(folder, file_name) + # write the Model dictionary into a file + with open(hb_file, 'wb') as fp: + pickle.dump(hb_dict, fp) + return hb_file
+ + +
+[docs] + def to_stl(self, name=None, folder=None): + """Write Honeybee model to an ASCII STL file. + + Note that all geometry is triangulated when it is converted to STL. + + Args: + name: A text string for the name of the STL file. If None, the model + identifier wil be used. (Default: None). + folder: A text string for the directory where the STL will be written. + If unspecified, the default simulation folder will be used. This + is usually at "C:\\Users\\USERNAME\\simulation." + """ + # set up a name and folder for the STL + if name is None: + name = self.identifier + file_name = name if name.lower().endswith('.stl') else '{}.stl'.format(name) + folder = folder if folder is not None else folders.default_simulation_folder + + # collect all of the Face3Ds across the model as triangles and normals + all_geo = [] + for face in self.faces: + all_geo.append(face.punched_geometry) + for ap in self.apertures: + all_geo.append(ap.geometry) + for dr in self.doors: + all_geo.append(dr.geometry) + for shd in self.doors: + all_geo.append(shd.geometry) + + # convert the Face3Ds into a format for export to STL + _face_vertices, _face_normals = [], [] + for face_3d in all_geo: + # add the geometry of a Face3D to the lists for STL export + if len(face_3d) == 3: + _face_vertices.append(face_3d.vertices) + _face_normals.append(face_3d.normal) + else: + tri_mesh = face_3d.triangulated_mesh3d + for m_fac in tri_mesh.face_vertices: + _face_vertices.append(m_fac) + _face_normals.append(face_3d.normal) + + # convert any shade meshes into STL vertices + for sm in self._shade_meshes: + for fvs, fns in zip(sm.geometry.face_vertices, sm.geometry.face_normals): + _face_vertices.append(fvs) + _face_normals.append(fns) + + # write the geometry into an STL file + stl_obj = STL(_face_vertices, _face_normals, self.identifier) + return stl_obj.to_file(folder, file_name)
+ + + def _all_objects(self): + """Get a single list of all the Honeybee objects in a Model.""" + return self._rooms + self._orphaned_faces + self._orphaned_shades + \ + self._orphaned_apertures + self._orphaned_doors + self._shade_meshes + +
+[docs] + @staticmethod + def conversion_factor_to_meters(units): + """Get the conversion factor to meters based on input units. + + Args: + units: Text for the units. Choose from the following: + + * Meters + * Millimeters + * Feet + * Inches + * Centimeters + + Returns: + A number for the conversion factor, which should be multiplied by + all distance units taken from Rhino geometry in order to convert + them to meters. + """ + return conversion_factor_to_meters(units)
+ + + def _self_adj_check(self, obj_type, hb_obj, bc_ids, room_ids, bc_set, detailed): + """Check that an adjacent object is referencing itself or its own room. + + A check will also be performed to ensure the adjacent object doesn't already + have an adjacent pair in the model. + """ + bc_objs = hb_obj.boundary_condition.boundary_condition_objects + bc_obj, bc_room = bc_objs[0], bc_objs[-1] + bc_ids.append(bc_obj) + room_ids.append(bc_room) + msgs = [] + # first ensure that the object is not referencing itself + if hb_obj.identifier == bc_obj: + parent_msg = 'with parent "{}" '.format(hb_obj._top_parent().full_id) \ + if hb_obj.has_parent else '' + msg = '{} "{}" {}cannot reference itself in its Surface boundary ' \ + 'condition.'.format(obj_type, hb_obj.full_id, parent_msg) + msg = self._validation_message_child( + msg, hb_obj, detailed, '000201', + error_type='Self-Referential Adjacency') + msgs.append(msg) + # then ensure that the object is not referencing its own room + if hb_obj.has_parent and hb_obj.parent.has_parent: + if hb_obj.parent.parent.identifier == bc_room: + msg = '{} "{}" and its adjacent object "{}" cannot be a part of the ' \ + 'same Room "{}".'.format(obj_type, hb_obj.full_id, bc_obj, bc_room) + msg = self._validation_message_child( + msg, hb_obj, detailed, '000202', + error_type='Intra-Room Adjacency') + msgs.append(msg) + # lastly make sure the adjacent object doesn't already have an adjacency + if bc_obj in bc_set: + parent_msg1 = 'with parent "{}" '.format(hb_obj._top_parent().full_id) \ + if hb_obj.has_parent else '' + parent_msg2 = ' with parent "{}" '.format(bc_room) if len(bc_objs) > 1 else '' + msg = '{} "{}" {}is adjacent to object "{}"{}, which has another adjacent ' \ + 'object in the Model.'.format( + obj_type, hb_obj.full_id, parent_msg1, bc_obj, parent_msg2) + msg = self._validation_message_child( + msg, hb_obj, detailed, '000203', + error_type='Object with Multiple Adjacencies') + msgs.append(msg) + else: + bc_set.add(bc_obj) + return msgs if detailed else ''.join(msgs) + + def _missing_adj_msg(self, messages, hb_obj, bc_obj, + obj_type='Face', bc_obj_type='Face', detailed=False): + parent_msg = 'with parent "{}" '.format(hb_obj._top_parent().full_id) \ + if hb_obj.has_parent else '' + msg = '{} "{}" {}has an adjacent {} that is missing from the model: ' \ + '{}'.format(obj_type, hb_obj.full_id, parent_msg, bc_obj_type, bc_obj) + msg = self._validation_message_child( + msg, hb_obj, detailed, '000204', error_type='Missing Adjacency') + if detailed: + messages.append([msg]) + else: + messages.append(msg) + + @staticmethod + def _missing_adj_check(id_checking_function, bc_ids): + """Check whether adjacencies are missing from a model.""" + try: + id_checking_function(bc_ids) + return [] + except ValueError as e: + id_pattern = re.compile('\"([^"]*)\"') + return [obj_id for obj_id in id_pattern.findall(str(e))] + + @staticmethod + def _adj_objects(hb_obj): + """Check that an adjacent object is referencing itself.""" + bc_objs = hb_obj.boundary_condition.boundary_condition_objects + return bc_objs[0], bc_objs[-1] + + @staticmethod + def _remove_by_ids(objs, obj_ids): + """Remove items from a list using a list of object IDs.""" + if obj_ids == []: + return objs + new_objs = [] + if obj_ids is not None: + obj_id_set = set(obj_ids) + for obj in objs: + if obj.identifier not in obj_id_set: + new_objs.append(obj) + return new_objs + + def __add__(self, other): + new_model = self.duplicate() + new_model.add_model(other) + return new_model + + def __iadd__(self, other): + self.add_model(other) + return self + + def __copy__(self): + new_model = Model( + self.identifier, + [room.duplicate() for room in self._rooms], + [face.duplicate() for face in self._orphaned_faces], + [shade.duplicate() for shade in self._orphaned_shades], + [aperture.duplicate() for aperture in self._orphaned_apertures], + [door.duplicate() for door in self._orphaned_doors], + [shade_mesh.duplicate() for shade_mesh in self._shade_meshes], + self.units, self.tolerance, self.angle_tolerance) + new_model._display_name = self._display_name + new_model._user_data = None if self.user_data is None else self.user_data.copy() + new_model._properties._duplicate_extension_attr(self._properties) + return new_model + + def __repr__(self): + return 'Model: %s' % self.display_name
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/orientation.html b/docs/_modules/honeybee/orientation.html new file mode 100644 index 00000000..ddca4142 --- /dev/null +++ b/docs/_modules/honeybee/orientation.html @@ -0,0 +1,1275 @@ + + + + + + + honeybee.orientation — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.orientation

+"""Collection of utilities for assigning different properties based on orientation.
+
+The functions here are meant to be adaptable to splitting up the compass based on
+however many bins the user desires, though the most common arrangement is likely
+to be a list of 4 values for North, East South, and West.
+
+Usage:
+
+.. code-block:: python
+
+    # list of constructions + materials to apply to faces of different orientations
+    ep_constructions = [constr_north, constr_east, constr_south, constr_west]
+    rad_materials = [mat_north, mat_east, mat_south, mat_west]
+
+    # check that the inputs align with one another
+    all_inputs = [ep_constructions, rad_materials]
+    all_inputs, num_orient = check_matching_inputs(all_inputs)
+
+    # assign properties based on orientation
+    angles = angles_from_num_orient(num_orient)
+    for face in hb_faces:
+        orient_i = face_orient_index(face, angles)
+        if orient_i is not None:
+            constr, mat = inputs_by_index(orient_i, all_inputs)
+            face.properties.energy.construction = constr
+            face.properties.radiance.modifier = mat
+"""
+from ladybug_geometry.geometry2d.pointvector import Vector2D
+
+
+
+[docs] +def angles_from_num_orient(num_subdivisions=4): + """Get a list of angles based on the number of compass subdivisions. + + Args: + num_subdivisions: An integer for the number of times that the compass + should be subdivided. Default: 4, which will yield angles for North, + East South, and West. + + Returns: + A list of angles in degrees with a length of the num_subdivisions, which + denote the boundaries of each orientation category. + """ + step = 360.0 / num_subdivisions + start = step / 2.0 + angles = [] + while start < 360: + angles.append(start) + start += step + return angles
+ + + +
+[docs] +def face_orient_index(face, angles, north_vector=Vector2D(0, 1)): + """Get the index to be used for a given face/aperture orientation from an angle list. + + Args: + face: A honeybee Face or Aperture object. + angles: A list of angles that denote the boundaries of each orientation + category. + north_vector: An optional ladybug_geometry Vector2D for the north direction. + Default is the Y-axis (0, 1). + + Returns: + An integer for the index used to assign properties to the object of the + input orientation. Will be None if the input Face or Aperture is perfectly + horizontal. + """ + try: + return orient_index(face.horizontal_orientation(north_vector), angles) + except ZeroDivisionError: # input face is perfectly horizontal + return None
+ + + +
+[docs] +def orient_index(orientation, angles): + """Get the index to be used for a given face/aperture orientation from an angle list. + + Args: + orientation: The horizontal cardinal orientation of the Face or Aperture + in degrees. + angles: A list of angles that denote the boundaries of each orientation + category. + + Returns: + An integer for the index used to assign properties to the object of the + input orientation. + """ + for i, ang in enumerate(angles): + if orientation < ang: + return i + return 0
+ + + +
+[docs] +def inputs_by_index(orientation_index, all_inputs): + """Get all of the inputs of a certain index from a list of all_inputs. + + This is useful for getting the set of all inputs that should be assigned to + a given Face or Aperture using its orientation_index. + """ + return [inp[orientation_index] for inp in all_inputs]
+ + + +
+[docs] +def check_matching_inputs(all_inputs, num_orient=None): + """Check that all orientation-specific inputs are coordinated. + + This means that each input is either a array of values to be applied to each + orientation, which is has the same length as other orientation-specific arrays, + or it is a single value to be used for all orientations. + + Args: + all_inputs: An array of arrays where each sub-array corresponds to an + orientation-specific input. + num_orient: An optional integer for the number of orientation categories + to be used. If None, the length of the longest input list in the + all_inputs will be used. + + Returns: + A tuple with two elements + + - all_inputs -- The input all_inputs with all sub-arrays having the same length. + + - num_orient -- An integer for the number of orientations used in the check. + """ + num_orient = max([len(inp) for inp in all_inputs]) if num_orient is None \ + else num_orient + for i, param_list in enumerate(all_inputs): + if len(param_list) == 1: + all_inputs[i] = param_list * num_orient + else: + assert len(param_list) == num_orient, \ + 'The number of items in one of the inputs lists does not match the ' \ + 'others.\nPlease ensure that either the lists match or you put in '\ + 'a single value for all orientations.' + return all_inputs, num_orient
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/properties.html b/docs/_modules/honeybee/properties.html new file mode 100644 index 00000000..34a2c08b --- /dev/null +++ b/docs/_modules/honeybee/properties.html @@ -0,0 +1,1973 @@ + + + + + + + honeybee.properties — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.properties

+# coding: utf-8
+"""Extension properties for Model, Room, Face, Shade, Aperture, Door.
+
+These objects hold all attributes assigned by extensions like honeybee-radiance
+and honeybee-energy.  Note that these Property objects are not intended to exist
+on their own but should have a host object.
+"""
+
+
+class _Properties(object):
+    """Base class for all Properties classes.
+
+    Args:
+        host: A honeybee-core geometry object that hosts these properties
+            (ie. Model, Room, Face, Shade, Aperture, Door).
+    """
+    _exclude = set(
+        ('host', 'move', 'rotate', 'rotate_xy', 'reflect', 'scale', 'is_equivalent',
+         'add_prefix', 'reset_to_default', 'to_dict', 'apply_properties_from_dict',
+         'ToString'))
+
+    def __init__(self, host):
+        """Initialize properties."""
+        self._host = host
+
+    @property
+    def host(self):
+        """Get the object hosting these properties."""
+        return self._host
+
+    @property
+    def _extension_attributes(self):
+        return (atr for atr in dir(self) if not atr.startswith('_')
+                and atr not in self._exclude)
+
+    def move(self, moving_vec):
+        """Apply a move transform to extension attributes.
+
+        This is useful in cases where extension attributes possess geometric data
+        that should be moved alongside the host object. For example, dynamic
+        geometry within the honeybee-radiance state of an aperture should be
+        moved if the host aperture is moved.
+
+        Args:
+            moving_vec: A ladybug_geometry Vector3D with the direction and distance
+                to move the face.
+        """
+        for atr in self._extension_attributes:
+            var = getattr(self, atr)
+            if not hasattr(var, 'move'):
+                continue
+            try:
+                var.move(moving_vec)
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed to move {}: {}'.format(var, e))
+
+    def rotate(self, axis, angle, origin):
+        """Apply a rotation transform to extension attributes.
+
+        This is useful in cases where extension attributes possess geometric data
+        that should be rotated alongside the host object. For example, dynamic
+        geometry within the honeybee-radiance state of an aperture should be
+        rotated if the host aperture is rotated.
+
+        Args:
+            axis: A ladybug_geometry Vector3D axis representing the axis of rotation.
+            angle: An angle for rotation in degrees.
+            origin: A ladybug_geometry Point3D for the origin around which the
+                object will be rotated.
+        """
+        for atr in self._extension_attributes:
+            var = getattr(self, atr)
+            if not hasattr(var, 'rotate'):
+                continue
+            try:
+                var.rotate(axis, angle, origin)
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed to rotate {}: {}'.format(var, e))
+
+    def rotate_xy(self, angle, origin):
+        """Apply a rotation in the XY plane to extension attributes.
+
+        This is useful in cases where extension attributes possess geometric data
+        that should be rotated alongside the host object. For example, dynamic
+        geometry within the honeybee-radiance state of an aperture should be
+        rotated if the host aperture is rotated.
+
+        Args:
+            angle: An angle in degrees.
+            origin: A ladybug_geometry Point3D for the origin around which the
+                object will be rotated.
+        """
+        for atr in self._extension_attributes:
+            var = getattr(self, atr)
+            if not hasattr(var, 'rotate_xy'):
+                continue
+            try:
+                var.rotate_xy(angle, origin)
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed to rotate {}: {}'.format(var, e))
+
+    def reflect(self, plane):
+        """Apply a reflection transform to extension attributes.
+
+        This is useful in cases where extension attributes possess geometric data
+        that should be reflected alongside the host object. For example, dynamic
+        geometry within the honeybee-radiance state of an aperture should be
+        reflected if the host aperture is reflected.
+
+        Args:
+            plane: A ladybug_geometry Plane across which the object will
+                be reflected.
+        """
+        for atr in self._extension_attributes:
+            var = getattr(self, atr)
+            if not hasattr(var, 'reflect'):
+                continue
+            try:
+                var.reflect(plane)
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed to reflect {}: {}'.format(var, e))
+
+    def scale(self, factor, origin=None):
+        """Apply a scale transform to extension attributes.
+
+        This is useful in cases where extension attributes possess geometric data
+        that should be scaled alongside the host object. For example, dynamic
+        geometry within the honeybee-radiance state of an aperture should be
+        scaled if the host aperture is scaled.
+
+        Args:
+            factor: A number representing how much the object should be scaled.
+            origin: A ladybug_geometry Point3D representing the origin from which
+                to scale. If None, it will be scaled from the World origin (0, 0, 0).
+        """
+        for atr in self._extension_attributes:
+            var = getattr(self, atr)
+            if not hasattr(var, 'scale'):
+                continue
+            try:
+                var.scale(factor, origin)
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed to scale {}: {}'.format(var, e))
+
+    def is_equivalent(self, other_properties):
+        """Get a dictionary noting the equivalency of these properties to other ones.
+
+        The keys of this dictionary will note the name of each extension (eg.
+        energy, radiance) and the values will be a boolean for whether the
+        extension properties are equivalent or not.
+
+        Args:
+            other_properties: Properties of another object for which equivalency
+                will be tested.
+        """
+        eq_dict = {}
+        for atr in self._extension_attributes:
+            var = getattr(self, atr)
+            if not hasattr(var, 'is_equivalent'):
+                continue
+            other_var = getattr(other_properties, atr)
+            try:
+                eq_dict[atr] = var.is_equivalent(other_var)
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed test is_equivalent for {}: {}'.format(var, e))
+        return eq_dict
+
+    def _update_by_sync(self, change, existing_prop, updated_prop):
+        """Update properties using change instructions and existing/updated objects."""
+        for atr in self._extension_attributes:
+            up_atr = 'update_{}'.format(atr)
+            if up_atr in change:
+                var = getattr(updated_prop, atr) if change[up_atr] \
+                    else getattr(existing_prop, atr)
+                if not hasattr(var, 'duplicate'):
+                    continue
+                try:
+                    setattr(self, '_' + atr, var.duplicate(self.host))
+                except Exception as e:
+                    import traceback
+                    traceback.print_exc()
+                    raise Exception('Failed to duplicate {}: {}'.format(var, e))
+
+    def _duplicate_extension_attr(self, original_properties):
+        """Duplicate the attributes added by extensions.
+
+        This method should be called within the duplicate or __copy__ methods of
+        each honeybee-core geometry object after the core object has been duplicated.
+        This method only needs to be called on the new (duplicated) core object and
+        the extension properties of the original core object should be passed to
+        this method as the original_properties.
+
+        Args:
+            original_properties: The properties object of the original core
+                object from which the duplicate was derived.
+        """
+        for atr in self._extension_attributes:
+            var = getattr(original_properties, atr)
+            if not hasattr(var, 'duplicate'):
+                continue
+            try:
+                setattr(self, '_' + atr, var.duplicate(self.host))
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed to duplicate {}: {}'.format(var, e))
+
+    def _add_prefix_extension_attr(self, prefix):
+        """Change the name extension attributes unique to this object by adding a prefix.
+
+        This is particularly useful in workflows where you duplicate and edit
+        a starting object and then want to combine it with the original object
+        into one Model (like making a model of repeated rooms).
+
+        Notably, this method only adds the prefix to extension attributes that must
+        be unique to the object and does not add the prefix to attributes that are
+        shared across several objects.
+
+        Args:
+            prefix: Text that will be inserted at the start of the extension attributes'
+                name. It is recommended that this name be short to avoid maxing
+                out the 100 allowable characters for honeybee names.
+        """
+        for atr in self._extension_attributes:
+            var = getattr(self, atr)
+            if not hasattr(var, 'add_prefix'):
+                continue
+            try:
+                var.add_prefix(prefix)
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed to add prefix to {}: {}'.format(var, e))
+
+    def _reset_extension_attr_to_default(self):
+        """Reset all extension attributes for the object to be default.
+
+        This is useful in cases where properties that are hard-assigned to a specific
+        object might be illegal in combination with other properties and so they
+        should be reset upon the setting of the other properties. For example,
+        setting a Face type to AirBoundary typically makes certain types of energy
+        and radiance properties illegal. So calling this function whenever setting
+        Face type to AirBoundary will reset the extension attributes to the legal
+        default values.
+        """
+        for atr in self._extension_attributes:
+            var = getattr(self, atr)
+            if not hasattr(var, 'reset_to_default'):
+                continue
+            try:
+                var.reset_to_default()
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed to reset_to_default for {}: {}'.format(var, e))
+
+    def _add_extension_attr_to_dict(self, base, abridged, include):
+        """Add attributes for extensions to the base dictionary.
+
+        This method should be called within the to_dict method of each honeybee-core
+        geometry object.
+
+        Args:
+            base: The dictionary of the core object without any extension attributes.
+                This method will add extension attributes to this dictionary. For
+                example, energy properties will appear under base['properties']['energy'].
+            abridged: Boolean to note whether the attributes of the extensions should
+                be abridged (True) or full (False). For example, if a Room's energy
+                properties are abridged, the program_type attribute under the energy
+                properties dictionary will just be the identifier of the program_type. If
+                it is full (not abridged), the program_type will be a complete
+                dictionary following the ProgramType schema. Abridged dictionaries
+                should be used within the Model.to_dict but full dictionaries should
+                be used within the to_dict methods of individual objects.
+            include: List of properties to filter keys that must be included in
+                output dictionary. For example ['energy'] will include 'energy' key if
+                available in properties to_dict. By default all the keys will be
+                included. To exclude all the keys from extensions use an empty list.
+        """
+        attr = include if include is not None else self._extension_attributes
+        for atr in attr:
+            var = getattr(self, atr)
+            if not hasattr(var, 'to_dict'):
+                continue
+            try:
+                base.update(var.to_dict(abridged))
+            except Exception as e:
+                import traceback
+                traceback.print_exc()
+                raise Exception('Failed to convert {} to a dict: {}'.format(var, e))
+        return base
+
+    def _load_extension_attr_from_dict(self, property_dict):
+        """Get attributes for extensions from a dictionary of the properties.
+
+        This method should be called within the from_dict method of each honeybee-core
+        geometry object. Specifically, this method should be called on the core
+        object after it has been created from a dictionary but lacks any of the
+        extension attributes in the dictionary.
+
+        Args:
+            property_dict: A dictionary of properties for the object (ie.
+                FaceProperties, RoomProperties). These will be used to load
+                attributes from the dictionary and assign them to the object on
+                which this method is called.
+        """
+        for atr in self._extension_attributes:
+            var = getattr(self, atr)
+            if not hasattr(var, 'from_dict'):
+                continue
+            try:
+                setattr(self, '_' + atr, var.__class__.from_dict(
+                    property_dict[atr], self.host))
+            except KeyError:
+                pass  # the property_dict possesses no properties for that extension
+
+    def ToString(self):
+        """Overwrite .NET ToString method."""
+        return self.__repr__()
+
+    def __repr__(self):
+        """Properties representation."""
+        return 'BaseProperties'
+
+
+
+[docs] +class ModelProperties(_Properties): + """Honeybee Model Properties. + + This class will be extended by extensions. + + Usage: + + .. code-block:: python + + model = Model('New Elementary School', list_of_rooms) + model.properties -> ModelProperties + model.properties.radiance -> ModelRadianceProperties + model.properties.energy -> ModelEnergyProperties + """ + +
+[docs] + def to_dict(self, include=None): + """Convert properties to dictionary. + + Args: + include: A list of keys to be included in dictionary. + If None all the available keys will be included. + """ + base = {'type': 'ModelProperties'} + attr = include if include is not None else self._extension_attributes + for atr in attr: + var = getattr(self, atr) + if not hasattr(var, 'to_dict'): + continue + try: + base.update(var.to_dict()) # no abridged dictionary for model + except Exception as e: + import traceback + traceback.print_exc() + raise Exception('Failed to convert {} to a dict: {}'.format(var, e)) + return base
+ + +
+[docs] + def apply_properties_from_dict(self, data): + """Apply extension properties from a Model dictionary to the host Model. + + Args: + data: A dictionary representation of an entire honeybee-core Model. + """ + for atr in self._extension_attributes: + if atr not in data['properties'] or data['properties'][atr] is None: + continue + var = getattr(self, atr) + if var and not hasattr(var, 'apply_properties_from_dict'): + continue + try: + var.apply_properties_from_dict(data) + except Exception as e: + import traceback + traceback.print_exc() + raise Exception( + 'Failed to apply {} properties to the Model: {}'.format(atr, e))
+ + + def _check_extension_attr(self, detailed=False): + """Check the attributes of extensions. + + This method should be called within the check_all method of the Model object + to ensure that the check_all functions of any extension model properties + are also called. + + Args: + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + """ + msgs = [] + for atr in self._extension_attributes: + check_msg = None + var = getattr(self, atr) + if not hasattr(var, 'check_all'): + continue + try: + try: + check_msg = var.check_all(raise_exception=False, detailed=detailed) + except TypeError: # no option available for detailed error message + check_msg = var.check_all(raise_exception=False) + if detailed and check_msg is not None: + msgs.append(check_msg) + elif check_msg != '': + f_msg = 'Attributes for {} are invalid.\n{}'.format(atr, check_msg) + msgs.append(f_msg) + except Exception as e: + import traceback + traceback.print_exc() + raise Exception('Failed to check_all for {}: {}'.format(var, e)) + return msgs + + def __repr__(self): + """Properties representation.""" + return 'ModelProperties: {}'.format(self.host.display_name)
+ + + +
+[docs] +class RoomProperties(_Properties): + """Honeybee Room Properties. + + This class will be extended by extensions. + + Usage: + + .. code-block:: python + + room = Room('Bedroom', geometry) + room.properties -> RoomProperties + room.properties.radiance -> RoomRadianceProperties + room.properties.energy -> RoomEnergyProperties + """ + +
+[docs] + def to_dict(self, abridged=False, include=None): + """Convert properties to dictionary. + + Args: + abridged: Boolean to note whether the full dictionary describing the + object should be returned (False) or just an abridged version (True). + Default: False. + include: A list of keys to be included in dictionary. + If None all the available keys will be included. + """ + base = {'type': 'RoomProperties'} if not abridged else \ + {'type': 'RoomPropertiesAbridged'} + + base = self._add_extension_attr_to_dict(base, abridged, include) + return base
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier extension attributes unique to this object by adding a prefix. + + Notably, this method only adds the prefix to extension attributes that must + be unique to the Room (eg. single-room HVAC systems) and does not add the + prefix to attributes that are shared across several Rooms (eg. ConstructionSets). + + Args: + prefix: Text that will be inserted at the start of extension attribute identifiers. + """ + self._add_prefix_extension_attr(prefix)
+ + +
+[docs] + def reset_to_default(self): + """Reset the extension properties assigned at the level of this Room to default. + + This typically means erasing any ConstructionSets or ModifierSets assigned + to this Room among other properties. + """ + self._reset_extension_attr_to_default()
+ + + def __repr__(self): + """Properties representation.""" + return 'RoomProperties: {}'.format(self.host.display_name)
+ + + +
+[docs] +class FaceProperties(_Properties): + """Honeybee Face Properties. + + This class will be extended by extensions. + + Usage: + + .. code-block:: python + + face = Face('South Bedroom Wall', geometry) + face.properties -> FaceProperties + face.properties.radiance -> FaceRadianceProperties + face.properties.energy -> FaceEnergyProperties + """ + +
+[docs] + def to_dict(self, abridged=False, include=None): + """Convert properties to dictionary. + + Args: + abridged: Boolean to note whether the full dictionary describing the + object should be returned (False) or just an abridged version (True). + Default: False. + include: A list of keys to be included in dictionary besides Face type + and boundary_condition. If None all the available keys will be included. + """ + base = {'type': 'FaceProperties'} if not abridged else \ + {'type': 'FacePropertiesAbridged'} + base = self._add_extension_attr_to_dict(base, abridged, include) + return base
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier extension attributes unique to this object by adding a prefix. + + Notably, this method only adds the prefix to extension attributes that must + be unique to the Face and does not add the prefix to attributes that are + shared across several Faces. + + Args: + prefix: Text that will be inserted at the start of extension attribute identifiers. + """ + self._add_prefix_extension_attr(prefix)
+ + +
+[docs] + def reset_to_default(self): + """Reset the extension properties assigned at the level of this Face to default. + + This typically means erasing any Constructions or Modifiers assigned to this + Face (having them instead assigned by ConstructionSets and ModifierSets). + """ + self._reset_extension_attr_to_default()
+ + + def __repr__(self): + """Properties representation.""" + return 'FaceProperties: {}'.format(self.host.display_name)
+ + + +
+[docs] +class ApertureProperties(_Properties): + """Honeybee Aperture Properties. + + This class will be extended by extensions. + + Usage: + + .. code-block:: python + + aperture = Aperture('Window to My Soul', geometry) + aperture.properties -> ApertureProperties + aperture.properties.radiance -> ApertureRadianceProperties + aperture.properties.energy -> ApertureEnergyProperties + """ + +
+[docs] + def to_dict(self, abridged=False, include=None): + """Convert properties to dictionary. + + Args: + abridged: Boolean to note whether the full dictionary describing the + object should be returned (False) or just an abridged version (True). + Default: False. + include: A list of keys to be included in dictionary. + If None all the available keys will be included. + """ + base = {'type': 'ApertureProperties'} if not abridged else \ + {'type': 'AperturePropertiesAbridged'} + + base = self._add_extension_attr_to_dict(base, abridged, include) + return base
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier extension attributes unique to this object by adding a prefix. + + Notably, this method only adds the prefix to extension attributes that must + be unique to the Aperture and does not add the prefix to attributes that are + shared across several Apertures. + + Args: + prefix: Text that will be inserted at the start of extension attribute identifiers. + """ + self._add_prefix_extension_attr(prefix)
+ + +
+[docs] + def reset_to_default(self): + """Reset the extension properties assigned to this Aperture to default. + + This typically means erasing any Constructions or Modifiers assigned to this + Aperture (having them instead assigned by ConstructionSets and ModifierSets). + """ + self._reset_extension_attr_to_default()
+ + + def __repr__(self): + """Properties representation.""" + return 'ApertureProperties: {}'.format(self.host.display_name)
+ + + +
+[docs] +class DoorProperties(_Properties): + """Honeybee Door Properties. + + This class will be extended by extensions. + + Usage: + + .. code-block:: python + + door = Door('Front Door', geometry) + door.properties -> DoorProperties + door.properties.radiance -> DoorRadianceProperties + door.properties.energy -> DoorEnergyProperties + """ + +
+[docs] + def to_dict(self, abridged=False, include=None): + """Convert properties to dictionary. + + Args: + abridged: Boolean to note whether the full dictionary describing the + object should be returned (False) or just an abridged version (True). + Default: False. + include: A list of keys to be included in dictionary. + If None all the available keys will be included. + """ + base = {'type': 'DoorProperties'} if not abridged else \ + {'type': 'DoorPropertiesAbridged'} + + base = self._add_extension_attr_to_dict(base, abridged, include) + return base
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier extension attributes unique to this object by adding a prefix. + + Notably, this method only adds the prefix to extension attributes that must + be unique to the Door and does not add the prefix to attributes that are + shared across several Doors. + + Args: + prefix: Text that will be inserted at the start of extension attribute identifiers. + """ + self._add_prefix_extension_attr(prefix)
+ + +
+[docs] + def reset_to_default(self): + """Reset the extension properties assigned to this Door to default. + + This typically means erasing any Constructions or Modifiers assigned to this + Door (having them instead assigned by ConstructionSets and ModifierSets). + """ + self._reset_extension_attr_to_default()
+ + + def __repr__(self): + """Properties representation.""" + return 'DoorProperties: {}'.format(self.host.display_name)
+ + + +
+[docs] +class ShadeProperties(_Properties): + """Honeybee Shade Properties. + + This class will be extended by extensions. + + Usage: + + .. code-block:: python + + shade = Shade('Deep Overhang', geometry) + shade.properties -> ShadeProperties + shade.properties.radiance -> ShadeRadianceProperties + shade.properties.energy -> ShadeEnergyProperties + """ + +
+[docs] + def to_dict(self, abridged=False, include=None): + """Convert properties to dictionary. + + Args: + abridged: Boolean to note whether the full dictionary describing the + object should be returned (False) or just an abridged version (True). + Default: False. + include: A list of keys to be included in dictionary. + If None all the available keys will be included. + """ + base = {'type': 'ShadeProperties'} if not abridged else \ + {'type': 'ShadePropertiesAbridged'} + + base = self._add_extension_attr_to_dict(base, abridged, include) + return base
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier extension attributes unique to this object by adding a prefix. + + Notably, this method only adds the prefix to extension attributes that must + be unique to the Shade and does not add the prefix to attributes that are + shared across several Shades. + + Args: + prefix: Text that will be inserted at the start of extension attribute identifiers. + """ + self._add_prefix_extension_attr(prefix)
+ + +
+[docs] + def reset_to_default(self): + """Reset the extension properties assigned at the level of this Shade to default. + + This typically means erasing any Constructions or Modifiers assigned to this + Shade (having them instead assigned by ConstructionSets and ModifierSets). + """ + self._reset_extension_attr_to_default()
+ + + def __repr__(self): + """Properties representation.""" + return 'ShadeProperties: {}'.format(self.host.display_name)
+ + + +
+[docs] +class ShadeMeshProperties(_Properties): + """Honeybee ShadeMesh Properties. + + This class will be extended by extensions. + + Usage: + + .. code-block:: python + + shade = ShadeMesh('Hilly Terrain', geometry) + shade.properties -> ShadeMeshProperties + shade.properties.radiance -> ShadeMeshRadianceProperties + shade.properties.energy -> ShadeMeshEnergyProperties + """ + +
+[docs] + def to_dict(self, abridged=False, include=None): + """Convert properties to dictionary. + + Args: + abridged: Boolean to note whether the full dictionary describing the + object should be returned (False) or just an abridged version (True). + Default: False. + include: A list of keys to be included in dictionary. + If None all the available keys will be included. + """ + base = {'type': 'ShadeMeshProperties'} if not abridged else \ + {'type': 'ShadeMeshPropertiesAbridged'} + + base = self._add_extension_attr_to_dict(base, abridged, include) + return base
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier extension attributes unique to this object by adding a prefix. + + Notably, this method only adds the prefix to extension attributes that must + be unique to the ShadeMesh and does not add the prefix to attributes that are + shared across several ShadeMeshes (eg. modifier). + + Args: + prefix: Text that will be inserted at the start of extension attribute identifiers. + """ + self._add_prefix_extension_attr(prefix)
+ + +
+[docs] + def reset_to_default(self): + """Reset the extension properties assigned to this ShadeMesh to default. + + This typically means erasing any Constructions or Modifiers assigned to this + ShadeMesh. + """ + self._reset_extension_attr_to_default()
+ + + def __repr__(self): + """Properties representation.""" + return 'ShadeMeshProperties: {}'.format(self.host.display_name)
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/room.html b/docs/_modules/honeybee/room.html new file mode 100644 index 00000000..3c65d3f2 --- /dev/null +++ b/docs/_modules/honeybee/room.html @@ -0,0 +1,4092 @@ + + + + + + + honeybee.room — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.room

+# coding: utf-8
+"""Honeybee Room."""
+from __future__ import division
+import math
+import uuid
+
+from ladybug_geometry.geometry2d import Point2D, Vector2D, Polygon2D
+from ladybug_geometry.geometry3d import Point3D, Vector3D, Ray3D, Plane, Face3D, \
+    Mesh3D, Polyface3D
+from ladybug_geometry_polyskel.polysplit import perimeter_core_subpolygons
+
+import honeybee.writer.room as writer
+from ._basewithshade import _BaseWithShade
+from .typing import float_in_range, int_in_range, clean_string, \
+    invalid_dict_error
+from .properties import RoomProperties
+from .face import Face
+from .aperture import Aperture
+from .facetype import AirBoundary, Wall, Floor, RoofCeiling, get_type_from_normal
+from .boundarycondition import get_bc_from_position, Outdoors, Ground, Surface, \
+    boundary_conditions
+from .orientation import angles_from_num_orient, orient_index
+try:
+    ad_bc = boundary_conditions.adiabatic
+except AttributeError:  # honeybee_energy is not loaded and adiabatic does not exist
+    ad_bc = None
+
+
+
+[docs] +class Room(_BaseWithShade): + """A volume enclosed by faces, representing a single room or space. + + Note that, if zero is input for tolerance and angle_tolerance, no checks + will be performed to determine whether the room is a closed volume + and no attempt will be made to flip faces in the event that they are not + facing outward from the room volume. As such, an input tolerance of 0 + is intended for workflows where the solidity of the room volume has been + evaluated elsewhere. + + Args: + identifier: Text string for a unique Room ID. Must be < 100 characters and + not contain any spaces or special characters. + faces: A list or tuple of honeybee Face objects that together form the + closed volume of a room. + tolerance: The maximum difference between x, y, and z values + at which vertices of adjacent faces are considered equivalent. This is + used in determining whether the faces form a closed volume. Default + is 0, which makes no attempt to evaluate whether the Room volume + is closed. + angle_tolerance: The max angle difference in degrees that vertices are + allowed to differ from one another in order to consider them colinear. + Default is 0, which makes no attempt to evaluate whether the Room + volume is closed. + + Properties: + * identifier + * display_name + * faces + * multiplier + * story + * exclude_floor_area + * indoor_furniture + * indoor_shades + * outdoor_shades + * walls + * floors + * roof_ceilings + * air_boundaries + * doors + * apertures + * exterior_apertures + * geometry + * center + * min + * max + * volume + * floor_area + * exposed_area + * exterior_wall_area + * exterior_aperture_area + * exterior_wall_aperture_area + * exterior_skylight_aperture_area + * average_floor_height + * user_data + """ + __slots__ = ( + '_geometry', '_faces', + '_multiplier', '_story', '_exclude_floor_area', '_parent') + + def __init__(self, identifier, faces, tolerance=0, angle_tolerance=0): + """Initialize Room.""" + _BaseWithShade.__init__(self, identifier) # process the identifier + + # process the zone volume geometry + if not isinstance(faces, tuple): + faces = tuple(faces) + for face in faces: + assert isinstance(face, Face), \ + 'Expected honeybee Face. Got {}'.format(type(face)) + face._parent = self + + if tolerance == 0: + self._faces = faces + self._geometry = None # calculated later from faces or added by classmethods + else: + # try to get a closed volume between the faces + room_polyface = Polyface3D.from_faces( + tuple(face.geometry for face in faces), tolerance) + if not room_polyface.is_solid and angle_tolerance != 0: + ang_tol = math.radians(angle_tolerance) + room_polyface = room_polyface.merge_overlapping_edges(tolerance, ang_tol) + # replace honeybee face geometry with versions that are facing outwards + if room_polyface.is_solid: + for i, correct_face3d in enumerate(room_polyface.faces): + face = faces[i] + norm_init = face._geometry.normal + face._geometry = correct_face3d + if face.has_sub_faces: # flip sub-faces to align with parent Face + if norm_init.angle(face._geometry.normal) > (math.pi / 2): + for ap in face._apertures: + ap._geometry = ap._geometry.flip() + for dr in face._doors: + dr._geometry = dr._geometry.flip() + self._faces = faces + self._geometry = room_polyface + + self._multiplier = 1 # default value that can be overridden later + self._story = None # default value that can be overridden later + self._exclude_floor_area = False # default value that can be overridden later + self._parent = None # completely hidden as it is only used by Dragonfly + self._properties = RoomProperties(self) # properties for extensions + +
+[docs] + @classmethod + def from_dict(cls, data, tolerance=0, angle_tolerance=0): + """Initialize an Room from a dictionary. + + Args: + data: A dictionary representation of a Room object. + tolerance: The maximum difference between x, y, and z values + at which vertices of adjacent faces are considered equivalent. This is + used in determining whether the faces form a closed volume. Default + is 0, which makes no attempt to evaluate whether the Room volume + is closed. + angle_tolerance: The max angle difference in degrees that vertices are + allowed to differ from one another in order to consider them colinear. + Default is 0, which makes no attempt to evaluate whether the Room + volume is closed. + """ + try: + # check the type of dictionary + assert data['type'] == 'Room', 'Expected Room dictionary. ' \ + 'Got {}.'.format(data['type']) + + # create the room object and assign properties + faces = [] + for f_dict in data['faces']: + try: + faces.append(Face.from_dict(f_dict)) + except Exception as e: + invalid_dict_error(f_dict, e) + room = cls(data['identifier'], faces, tolerance, angle_tolerance) + if 'display_name' in data and data['display_name'] is not None: + room.display_name = data['display_name'] + if 'user_data' in data and data['user_data'] is not None: + room.user_data = data['user_data'] + if 'multiplier' in data and data['multiplier'] is not None: + room.multiplier = data['multiplier'] + if 'story' in data and data['story'] is not None: + room.story = data['story'] + if 'exclude_floor_area' in data and data['exclude_floor_area'] is not None: + room.exclude_floor_area = data['exclude_floor_area'] + room._recover_shades_from_dict(data) + + if data['properties']['type'] == 'RoomProperties': + room.properties._load_extension_attr_from_dict(data['properties']) + return room + except Exception as e: + cls._from_dict_error_message(data, e)
+ + +
+[docs] + @classmethod + def from_polyface3d(cls, identifier, polyface, roof_angle=60, floor_angle=130, + ground_depth=0): + """Initialize a Room from a ladybug_geometry Polyface3D object. + + Args: + identifier: Text string for a unique Room ID. Must be < 100 characters and + not contain any spaces or special characters. + polyface: A ladybug_geometry Polyface3D object representing the closed + volume of a room. The Polyface3D.is_solid property can be used to + determine whether the polyface is a closed solid before input here. + roof_angle: A number between 0 and 90 to set the angle from the horizontal + plane below which faces will be considered roofs instead of + walls. 90 indicates that all vertical faces are roofs and 0 + indicates that all horizontal faces are walls. (Default: 60, + recommended by the ASHRAE 90.1 standard). + floor_angle: A number between 90 and 180 to set the angle from the horizontal + plane above which faces will be considered floors instead of + walls. 180 indicates that all vertical faces are floors and 0 + indicates that all horizontal faces are walls. (Default: 130, + recommended by the ASHRAE 90.1 standard). + ground_depth: The Z value above which faces are considered Outdoors + instead of Ground. Faces will have a Ground boundary condition if + all of their vertices lie at or below this value. Default: 0. + """ + assert isinstance(polyface, Polyface3D), \ + 'Expected ladybug_geometry Polyface3D. Got {}'.format(type(polyface)) + faces = [] + for i, face in enumerate(polyface.faces): + faces.append(Face('{}..Face{}'.format(identifier, i), face, + get_type_from_normal(face.normal, roof_angle, floor_angle), + get_bc_from_position(face.boundary, ground_depth))) + room = cls(identifier, faces) + room._geometry = polyface + return room
+ + +
+[docs] + @classmethod + def from_box(cls, identifier, width=3.0, depth=6.0, height=3.2, + orientation_angle=0, origin=Point3D(0, 0, 0)): + """Initialize a Room from parameters describing a box. + + The resulting faces of the room will always be ordered as follows: + (Bottom, Front, Right, Back, Left, Top) where the front is facing the + cardinal direction of the orientation_angle. + + Args: + identifier: Text string for a unique Room ID. Must be < 100 characters and + not contain any spaces or special characters. + width: Number for the width of the box (in the X direction). Default: 3.0. + depth: Number for the depth of the box (in the Y direction). Default: 6.0. + height: Number for the height of the box (in the Z direction). Default: 3.2. + orientation_angle: A number between 0 and 360 for the clockwise + orientation of the box in degrees. + (0 = North, 90 = East, 180 = South, 270 = West) + origin: A ladybug_geometry Point3D for the origin of the room. + """ + # create a box Polyface3D + x_axis = Vector3D(1, 0, 0) + if orientation_angle != 0: + angle = -1 * math.radians( + float_in_range(orientation_angle, 0, 360, 'orientation_angle')) + x_axis = x_axis.rotate_xy(angle) + base_plane = Plane(Vector3D(0, 0, 1), origin, x_axis) + polyface = Polyface3D.from_box(width, depth, height, base_plane) + + # create the honeybee Faces + directions = ('Bottom', 'Front', 'Right', 'Back', 'Left', 'Top') + faces = [] + for face, dir in zip(polyface.faces, directions): + faces.append(Face('{}_{}'.format(identifier, dir), face, + get_type_from_normal(face.normal), + get_bc_from_position(face.boundary))) + room = cls(identifier, faces) + room._geometry = polyface + return room
+ + + @property + def faces(self): + """Get a tuple of all honeybee Faces making up this room volume.""" + return self._faces + + @property + def multiplier(self): + """Get or set an integer noting how many times this Room is repeated. + + Multipliers are used to speed up the calculation when similar Rooms are + repeated more than once. Essentially, a given simulation with the + Room is run once and then the result is multiplied by the multiplier. + This means that the "repetition" isn't in a particular direction (it's + essentially in the exact same location) and this comes with some + inaccuracy. However, this error might not be too large if the Rooms + are similar enough and it can often be worth it since it can greatly + speed up the calculation. + """ + return self._multiplier + + @multiplier.setter + def multiplier(self, value): + self._multiplier = int_in_range(value, 1, input_name='room multiplier') + + @property + def story(self): + """Get or set text for the story identifier to which this Room belongs. + + Rooms sharing the same story identifier are considered part of the same + story in a Model. Note that the story identifier has no character + restrictions much like display_name. + """ + return self._story + + @story.setter + def story(self, value): + if value is not None: + try: + self._story = str(value) + except UnicodeEncodeError: # Python 2 machine lacking the character set + self._story = value # keep it as unicode + else: + self._story = value + + @property + def exclude_floor_area(self): + """Get or set a boolean for whether the floor area contributes to the Model. + + Note that this will not affect the floor_area property of this Room but + it will ensure the Room's floor area is excluded from any calculations + when the Room is part of a Model. + """ + return self._exclude_floor_area + + @exclude_floor_area.setter + def exclude_floor_area(self, value): + self._exclude_floor_area = bool(value) + + @property + def indoor_furniture(self): + """Array of all indoor furniture Shade objects assigned to this Room. + + Note that this property is identical to the indoor_shades property but + it is provided here under an alternate name to make it clear that indoor + furniture objects should be added here to the Room. + """ + return tuple(self._indoor_shades) + + @property + def walls(self): + """Get a tuple of all of the Wall Faces of the Room.""" + return tuple(face for face in self._faces if isinstance(face.type, Wall)) + + @property + def floors(self): + """Get a tuple of all of the Floor Faces of the Room.""" + return tuple(face for face in self._faces if isinstance(face.type, Floor)) + + @property + def roof_ceilings(self): + """Get a tuple of all of the RoofCeiling Faces of the Room.""" + return tuple(face for face in self._faces if isinstance(face.type, RoofCeiling)) + + @property + def air_boundaries(self): + """Get a tuple of all of the AirBoundary Faces of the Room.""" + return tuple(face for face in self._faces if isinstance(face.type, AirBoundary)) + + @property + def doors(self): + """Get a tuple of all Doors of the Room.""" + drs = [] + for face in self._faces: + if len(face._doors) > 0: + drs.extend(face._doors) + return tuple(drs) + + @property + def apertures(self): + """Get a tuple of all Apertures of the Room.""" + aps = [] + for face in self._faces: + if len(face._apertures) > 0: + aps.extend(face._apertures) + return tuple(aps) + + @property + def exterior_apertures(self): + """Get a tuple of all exterior Apertures of the Room.""" + aps = [] + for face in self._faces: + if isinstance(face.boundary_condition, Outdoors) and \ + len(face._apertures) > 0: + aps.extend(face._apertures) + return tuple(aps) + + @property + def geometry(self): + """Get a ladybug_geometry Polyface3D object representing the room.""" + if self._geometry is None: + self._geometry = Polyface3D.from_faces( + tuple(face.geometry for face in self._faces), 0) # use 0 tolerance + return self._geometry + + @property + def center(self): + """Get a ladybug_geometry Point3D for the center of the room. + + Note that this is the center of the bounding box around the room Polyface + geometry and not the volume centroid. Also note that shades assigned to + this room are not included in this center calculation. + """ + return self.geometry.center + + @property + def min(self): + """Get a Point3D for the minimum of the bounding box around the object. + + This includes any shades assigned to this object or its children. + """ + all_geo = self._outdoor_shades + self._indoor_shades + all_geo.extend(self._faces) + return self._calculate_min(all_geo) + + @property + def max(self): + """Get a Point3D for the maximum of the bounding box around the object. + + This includes any shades assigned to this object or its children. + """ + all_geo = self._outdoor_shades + self._indoor_shades + all_geo.extend(self._faces) + return self._calculate_max(all_geo) + + @property + def volume(self): + """Get the volume of the room. + + Note that, if this room faces do not form a closed solid the value of this + property will not be accurate. + """ + return self.geometry.volume + + @property + def floor_area(self): + """Get the combined area of all room floor faces.""" + return sum([face.area for face in self._faces if isinstance(face.type, Floor)]) + + @property + def exposed_area(self): + """Get the combined area of all room faces with outdoor boundary conditions. + + Useful for estimating infiltration, often expressed as a flow per + unit exposed envelope area. + """ + return sum([face.area for face in self._faces if + isinstance(face.boundary_condition, Outdoors)]) + + @property + def exterior_wall_area(self): + """Get the combined area of all exterior walls on the room. + + This is NOT the area of the wall's punched_geometry and it includes BOTH + the area of opaque and transparent parts of the walls. + """ + wall_areas = 0 + for f in self._faces: + if isinstance(f.boundary_condition, Outdoors) and isinstance(f.type, Wall): + wall_areas += f.area + return wall_areas + + @property + def exterior_roof_area(self): + """Get the combined area of all exterior roofs on the room. + + This is NOT the area of the roof's punched_geometry and it includes BOTH + the area of opaque and transparent parts of the roofs. + """ + wall_areas = 0 + for f in self._faces: + if isinstance(f.boundary_condition, Outdoors) and \ + isinstance(f.type, RoofCeiling): + wall_areas += f.area + return wall_areas + + @property + def exterior_aperture_area(self): + """Get the combined area of all exterior apertures on the room.""" + ap_areas = 0 + for face in self._faces: + if isinstance(face.boundary_condition, Outdoors) and \ + len(face._apertures) > 0: + ap_areas += sum(ap.area for ap in face._apertures) + return ap_areas + + @property + def exterior_wall_aperture_area(self): + """Get the combined area of all apertures on exterior walls of the room.""" + ap_areas = 0 + for face in self._faces: + if isinstance(face.boundary_condition, Outdoors) and \ + isinstance(face.type, Wall) and len(face._apertures) > 0: + ap_areas += sum(ap.area for ap in face._apertures) + return ap_areas + + @property + def exterior_skylight_aperture_area(self): + """Get the combined area of all apertures on exterior roofs of the room.""" + ap_areas = 0 + for face in self._faces: + if isinstance(face.boundary_condition, Outdoors) and \ + isinstance(face.type, RoofCeiling) and len(face._apertures) > 0: + ap_areas += sum(ap.area for ap in face._apertures) + return ap_areas + + @property + def average_floor_height(self): + """Get the height of the room floor averaged over all floor faces in the room. + + The resulting value is weighted by the area of each of the floor faces. + Will be the minimum Z value of the Room volume if the room possesses no floors. + """ + heights = 0 + areas = 0 + for face in self._faces: + if isinstance(face.type, Floor): + heights += face.center.z * face.area + areas += face.area + return heights / areas if areas != 0 else self.geometry.min.z + + @property + def has_parent(self): + """Always False as Rooms cannot have parents.""" + return False + +
+[docs] + def is_extrusion(self, tolerance=0.01, angle_tolerance=1.0): + """Test if this Room is an extruded floor plate with a flat roof. + + Args: + tolerance: The absolute tolerance with which the Room geometry will + be evaluated. (Default: 0.01, suitable for objects in meters). + angle_tolerance: The angle tolerance at which the geometry will + be evaluated in degrees. (Default: 1 degree). + + Returns: + True if the 3D Room is a pure extrusion. False if not. + """ + # set up the parameters for evaluating vertical or horizontal + vert_vec = Vector3D(0, 0, 1) + min_v_ang = math.radians(angle_tolerance) + max_v_ang = math.pi - min_v_ang + min_h_ang = (math.pi / 2) - min_v_ang + max_h_ang = (math.pi / 2) + min_v_ang + + # loop through the 3D Room faces and test them + for face in self._faces: + try: # first make sure that the geometry is not degenerate + clean_geo = face.geometry.remove_colinear_vertices(tolerance) + v_ang = clean_geo.normal.angle(vert_vec) + if v_ang <= min_v_ang or v_ang >= max_v_ang: + continue + elif min_h_ang <= v_ang <= max_h_ang: + continue + return False + except AssertionError: # degenerate face to ignore + pass + return True
+ + +
+[docs] + def average_orientation(self, north_vector=Vector2D(0, 1)): + """Get a number between 0 and 360 for the average orientation of exposed walls. + + 0 = North, 90 = East, 180 = South, 270 = West. Will be None if the zone has + no exterior walls. Resulting value is weighted by the area of each of the + wall faces. + + Args: + north_vector: A ladybug_geometry Vector2D for the north direction. + Default is the Y-axis (0, 1). + """ + orientations = 0 + areas = 0 + for face in self._faces: + if isinstance(face.type, Wall) and \ + isinstance(face.boundary_condition, Outdoors): + orientations += face.horizontal_orientation(north_vector) * face.area + areas += face.area + return orientations / areas if areas != 0 else None
+ + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier of this object and child objects by inserting a prefix. + + This is particularly useful in workflows where you duplicate and edit + a starting object and then want to combine it with the original object + into one Model (like making a model of repeated rooms) since all objects + within a Model must have unique identifiers. + + Args: + prefix: Text that will be inserted at the start of this object's + (and child objects') identifier and display_name. It is recommended + that this prefix be short to avoid maxing out the 100 allowable + characters for honeybee identifiers. + """ + self._identifier = clean_string('{}_{}'.format(prefix, self.identifier)) + self.display_name = '{}_{}'.format(prefix, self.display_name) + self.properties.add_prefix(prefix) + for face in self._faces: + face.add_prefix(prefix) + self._add_prefix_shades(prefix)
+ + +
+[docs] + def horizontal_boundary(self, match_walls=False, tolerance=0.01): + """Get a Face3D representing the horizontal boundary around the Room. + + This will be generated from all downward-facing Faces of the Room (essentially + the Floor faces but can also include overhanging slanted walls). So, for + a valid closed-volume Honeybee Room, the result should always represent + the Room in the XY plane. + + The Z height of the resulting Face3D will be at the minimum floor height. + + Note that, if this Room is not solid, the computation of the horizontal + boundary may fail with an exception. + + Args: + match_walls: Boolean to note whether vertices should be inserted into + the final Face3D that will help match the segments of the result + back to the walls that are adjacent to the floors. If False, the + result may lack some colinear vertices that relate the Face3D + to the Walls, though setting this to True does not guarantee that + all walls will relate to a segment in the result. (Default: False). + tolerance: The minimum difference between x, y, and z coordinate values + at which points are considered distinct. (Default: 0.01, + suitable for objects in Meters). + """ + # get the starting horizontal boundary + try: + horiz_bound = self._base_horiz_boundary(tolerance) + except Exception as e: + msg = 'Room "{}" is not solid and so a valid horizontal boundary for ' \ + 'the Room could not be established.\n{}'.format(self.full_id, e) + raise ValueError(msg) + if match_walls: # insert the wall vertices + return self._match_walls_to_horizontal_faces([horiz_bound], tolerance)[0] + return horiz_bound
+ + +
+[docs] + def horizontal_floor_boundaries(self, match_walls=False, tolerance=0.01): + """Get a list of horizontal Face3D for the boundaries around the Room's Floors. + + Unlike the horizontal_boundary method, which uses all downward-pointing + geometries, this method will derive horizontal boundaries using only the + Floors. This is useful when the resulting geometry is used to specify the + floor area in the result. + + The Z height of the resulting Face3D will be at the minimum floor height. + + Args: + match_walls: Boolean to note whether vertices should be inserted into + the final Face3Ds that will help match the segments of the result + back to the walls that are adjacent to the floors. If False, the + result may lack some colinear vertices that relate the Face3Ds + to the Walls, though setting this to True does not guarantee that + all walls will relate to a segment in the result. (Default: False). + tolerance: The minimum difference between x, y, and z coordinate values + at which points are considered distinct. (Default: 0.01, + suitable for objects in Meters). + """ + # gather all of the floor geometries + flr_geo = [face.geometry for face in self.floors] + + # ensure that all geometries are horizontal with as few faces as possible + if len(flr_geo) == 0: # degenerate face + return [] + elif len(flr_geo) == 1: + if flr_geo[0].is_horizontal(tolerance): + horiz_bound = flr_geo + else: + floor_height = self.geometry.min.z + bound = [Point3D(p.x, p.y, floor_height) for p in flr_geo[0].boundary] + holes = None + if flr_geo[0].has_holes: + holes = [[Point3D(p.x, p.y, floor_height) for p in hole] + for hole in flr_geo[0].holes] + horiz_bound = [Face3D(bound, holes=holes)] + else: # multiple geometries to be joined together + floor_height = self.geometry.min.z + horiz_geo = [] + for fg in flr_geo: + if fg.is_horizontal(tolerance) and \ + abs(floor_height - fg.min.z) <= tolerance: + horiz_geo.append(fg) + else: # project the face geometry into the XY plane + bound = [Point3D(p.x, p.y, floor_height) for p in fg.boundary] + holes = None + if fg.has_holes: + holes = [[Point3D(p.x, p.y, floor_height) for p in hole] + for hole in fg.holes] + horiz_geo.append(Face3D(bound, holes=holes)) + # join the coplanar horizontal faces together + horiz_bound = Face3D.join_coplanar_faces(horiz_geo, tolerance) + + if match_walls: # insert the wall vertices + return self._match_walls_to_horizontal_faces(horiz_bound, tolerance) + return horiz_bound
+ + +
+[docs] + def remove_indoor_furniture(self): + """Remove all indoor furniture assigned to this Room. + + Note that this method is identical to the remove_indoor_shade method but + it is provided here under an alternate name to make it clear that indoor + furniture objects should be added here to the Room. + """ + self.remove_indoor_shades()
+ + +
+[docs] + def add_indoor_furniture(self, shade): + """Add a Shade object representing furniture to the Room. + + Note that this method is identical to the add_indoor_shade method but + it is provided here under an alternate name to make it clear that indoor + furniture objects should be added here to the Room. + + Args: + shade: A Shade object to add to the indoors of this Room, representing + furniture, desks, partitions, etc. + """ + self.add_indoor_shade(shade)
+ + +
+[docs] + def generate_grid(self, x_dim, y_dim=None, offset=1.0): + """Get a gridded Mesh3D objects offset from the floors of this room. + + Note that the x_dim and y_dim refer to dimensions within the XY coordinate + system of the floor faces's planes. So rotating the planes of the floor faces + will result in rotated grid cells. + + Will be None if the Room has no floor faces. + + Args: + x_dim: The x dimension of the grid cells as a number. + y_dim: The y dimension of the grid cells as a number. Default is None, + which will assume the same cell dimension for y as is set for x. + offset: A number for how far to offset the grid from the base face. + Default is 1.0, which will offset the grid to be 1 unit above + the floor. + + Usage: + + .. code-block:: python + + room = Room.from_box(3.0, 6.0, 3.2, 180) + floor_mesh = room.generate_grid(0.5, 0.5, 1) + test_points = floor_mesh.face_centroids + """ + floor_grids = [] + for face in self._faces: + if isinstance(face.type, Floor): + try: + floor_grids.append( + face.geometry.mesh_grid(x_dim, y_dim, offset, True)) + except AssertionError: # grid tolerance not fine enough + pass + if len(floor_grids) == 1: + return floor_grids[0] + elif len(floor_grids) > 1: + return Mesh3D.join_meshes(floor_grids) + return None
+ + +
+[docs] + def generate_exterior_face_grid( + self, dimension, offset=0.1, face_type='Wall', punched_geometry=False): + """Get a gridded Mesh3D offset from the exterior Faces of this Room. + + This will be None if the Room has no exterior Faces. + + Args: + dimension: The dimension of the grid cells as a number. + offset: A number for how far to offset the grid from the base face. + Positive numbers indicate an offset towards the exterior. (Default + is 0.1, which will offset the grid to be 0.1 unit from the faces). + face_type: Text to specify the type of face that will be used to + generate grids. Note that only Faces with Outdoors boundary + conditions will be used, meaning that most Floors will typically + be excluded unless they represent the underside of a cantilever. + Choose from the following. (Default: Wall). + + * Wall + * Roof + * Floor + * All + + punched_geometry: Boolean to note whether the punched_geometry of the faces + should be used (True) with the areas of sub-faces removed from the grid + or the full geometry should be used (False). (Default:False). + + Usage: + + .. code-block:: python + + room = Room.from_box(3.0, 6.0, 3.2, 180) + face_mesh = room.generate_exterior_face_grid(0.5) + test_points = face_mesh.face_centroids + """ + # select the correct face type based on the input + face_t = face_type.title() + if face_t == 'Wall': + ft = Wall + elif face_t in ('Roof', 'Roofceiling'): + ft = RoofCeiling + elif face_t == 'All': + ft = (Wall, RoofCeiling, Floor) + elif face_t == 'Floor': + ft = Floor + else: + raise ValueError('Unrecognized face_type "{}".'.format(face_type)) + face_attr = 'punched_geometry' if punched_geometry else 'geometry' + # loop through the faces and generate grids + face_grids = [] + for face in self._faces: + if isinstance(face.type, ft) and \ + isinstance(face.boundary_condition, Outdoors): + try: + f_geo = getattr(face, face_attr) + face_grids.append( + f_geo.mesh_grid(dimension, None, offset, False)) + except AssertionError: # grid tolerance not fine enough + pass + # join the grids together if there are several ones + if len(face_grids) == 1: + return face_grids[0] + elif len(face_grids) > 1: + return Mesh3D.join_meshes(face_grids) + return None
+ + +
+[docs] + def generate_exterior_aperture_grid( + self, dimension, offset=0.1, aperture_type='All'): + """Get a gridded Mesh3D offset from the exterior Apertures of this room. + + Will be None if the Room has no exterior Apertures. + + Args: + dimension: The dimension of the grid cells as a number. + offset: A number for how far to offset the grid from the base aperture. + Positive numbers indicate an offset towards the exterior while + negative numbers indicate an offset towards the interior, essentially + modeling the value of sun on the building interior. (Default + is 0.1, which will offset the grid to be 0.1 unit from the apertures). + aperture_type: Text to specify the type of Aperture that will be used to + generate grids. Window indicates Apertures in Walls. Choose from + the following. (Default: All). + + * Window + * Skylight + * All + + Usage: + + .. code-block:: python + + room = Room.from_box(3.0, 6.0, 3.2, 180) + room[3].apertures_by_ratio(0.4) + aperture_mesh = room.generate_exterior_aperture_grid(0.5) + test_points = aperture_mesh.face_centroids + """ + # select the correct face type based on the input + ap_t = aperture_type.title() + if ap_t == 'Window': + ft = Wall + elif ap_t == 'Skylight': + ft = RoofCeiling + elif ap_t == 'All': + ft = (Wall, RoofCeiling, Floor) + else: + raise ValueError('Unrecognized aperture_type "{}".'.format(aperture_type)) + # loop through the faces and generate grids + ap_grids = [] + for face in self._faces: + if isinstance(face.type, ft) and \ + isinstance(face.boundary_condition, Outdoors): + for ap in face.apertures: + try: + ap_grids.append( + ap.geometry.mesh_grid(dimension, None, offset, False)) + except AssertionError: # grid tolerance not fine enough + pass + # join the grids together if there are several ones + if len(ap_grids) == 1: + return ap_grids[0] + elif len(ap_grids) > 1: + return Mesh3D.join_meshes(ap_grids) + return None
+ + +
+[docs] + def wall_apertures_by_ratio(self, ratio, tolerance=0.01): + """Add apertures to all exterior walls given a ratio of aperture to face area. + + Note this method removes any existing apertures and doors on the Room's walls. + This method attempts to generate as few apertures as necessary to meet the ratio. + + Args: + ratio: A number between 0 and 1 (but not perfectly equal to 1) + for the desired ratio between aperture area and face area. + tolerance: The maximum difference between point values for them to be + considered equivalent. (Default: 0.01, suitable for objects in meters). + + Usage: + + .. code-block:: python + + room = Room.from_box(3.0, 6.0, 3.2, 180) + room.wall_apertures_by_ratio(0.4) + """ + for face in self._faces: + if isinstance(face.boundary_condition, Outdoors) and \ + isinstance(face.type, Wall): + face.apertures_by_ratio(ratio, tolerance)
+ + +
+[docs] + def skylight_apertures_by_ratio(self, ratio, tolerance=0.01): + """Add apertures to all exterior roofs given a ratio of aperture to face area. + + Note this method removes any existing apertures and overhead doors on the + Room's roofs. This method attempts to generate as few apertures as + necessary to meet the ratio. + + Args: + ratio: A number between 0 and 1 (but not perfectly equal to 1) + for the desired ratio between aperture area and face area. + tolerance: The maximum difference between point values for them to be + considered equivalent. (Default: 0.01, suitable for objects in meters). + + Usage: + + .. code-block:: python + + room = Room.from_box(3.0, 6.0, 3.2, 180) + room.skylight_apertures_by_ratio(0.05) + """ + for face in self._faces: + if isinstance(face.boundary_condition, Outdoors) and \ + isinstance(face.type, RoofCeiling): + face.apertures_by_ratio(ratio, tolerance)
+ + +
+[docs] + def simplify_apertures(self, tolerance=0.01): + """Convert all Apertures on this Room to be a simple window ratio. + + This is useful for studies where faster simulation times are desired and + the window ratio is the critical factor driving the results (as opposed + to the detailed geometry of the window). Apertures assigned to concave + Faces will not be simplified given that the apertures_by_ratio method + likely won't improve the cleanliness of the apertures for such cases. + + Args: + tolerance: The maximum difference between point values for them to be + considered equivalent. (Default: 0.01, suitable for objects in meters). + """ + for face in self.faces: + f_ap = face._apertures + if len(f_ap) != 0 and face.geometry.is_convex: + # reset boundary conditions to outdoors so new apertures can be added + if not isinstance(face.boundary_condition, Outdoors): + face.boundary_condition = boundary_conditions.outdoors + face.apertures_by_ratio(face.aperture_ratio, tolerance)
+ + +
+[docs] + def rectangularize_apertures( + self, subdivision_distance=None, max_separation=None, merge_all=False, + tolerance=0.01, angle_tolerance=1.0): + """Convert all Apertures on this Room to be rectangular. + + This is useful when exporting to simulation engines that only accept + rectangular window geometry. This method will always result ing Rooms where + all Apertures are rectangular. However, if the subdivision_distance is not + set, some Apertures may extend past the parent Face or may collide with + one another. + + Args: + subdivision_distance: A number for the resolution at which the + non-rectangular Apertures will be subdivided into smaller + rectangular units. Specifying a number here ensures that the + resulting rectangular Apertures do not extend past the parent + Face or collide with one another. If None, all non-rectangular + Apertures will be rectangularized by taking the bounding rectangle + around the Aperture. (Default: None). + max_separation: A number for the maximum distance between non-rectangular + Apertures at which point the Apertures will be merged into a single + rectangular geometry. This is often helpful when there are several + triangular Apertures that together make a rectangle when they are + merged across their frames. In such cases, this max_separation + should be set to a value that is slightly larger than the window frame. + If None, no merging of Apertures will happen before they are + converted to rectangles. (Default: None). + merge_all: Boolean to note whether all apertures should be merged before + they are rectangularized. If False, only non-rectangular apertures + will be merged before rectangularization. Note that this argument + has no effect when the max_separation is None. (Default: False). + tolerance: The maximum difference between point values for them to be + considered equivalent. (Default: 0.01, suitable for objects in meters). + angle_tolerance: The max angle in degrees that the corners of the + rectangle can differ from a right angle before it is not + considered a rectangle. (Default: 1). + """ + for face in self._faces: + face.rectangularize_apertures( + subdivision_distance, max_separation, merge_all, + tolerance, angle_tolerance + )
+ + +
+[docs] + def ground_by_custom_surface(self, ground_geometry, tolerance=0.01, + angle_tolerance=1.0): + """Set ground boundary conditions using an array of Face3D for the ground. + + Room faces that are coplanar with the ground surface or lie completely below it + will get a Ground boundary condition while those above will get an Outdoors + boundary condition. Existing Faces with an indoor boundary condition will + be unaffected. + + Args: + ground_geometry: An array of ladybug_geometry Face3D that together + represent the ground surface. + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. (Default: 0.01, + suitable for objects in meters). + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered + coplanar. (Default: 1). + """ + select_faces = self.faces_by_guide_surface( + ground_geometry, Vector3D(0, 0, -1), tolerance, angle_tolerance) + for face in select_faces: + if face.can_be_ground and \ + isinstance(face.boundary_condition, (Outdoors, Ground)): + face.boundary_condition = boundary_conditions.ground
+ + +
+[docs] + def faces_by_guide_surface(self, surface_geometry, directional_vector=None, + tolerance=0.01, angle_tolerance=1.0): + """Get the Faces of the Room that are touching and coplanar with a given surface. + + This is useful in workflows were one would like to set the properties + of a group of Faces using a guide surface, like setting a series of faces + along a given stretch of a parti wall to be adiabatic. + + Args: + surface_geometry: An array of ladybug_geometry Face3D that together + represent the guide surface. + directional_vector: An optional Vector3D to select the room Faces that + lie on a certain side of the surface_geometry. For example, using + (0, 0, -1) will include all Faces that lie below the surface_geometry + in the resulting selection. + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. (Default: 0.01, + suitable for objects in meters). + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered + coplanar. (Default: 1). + """ + selected_faces, ang_tol = [], math.radians(angle_tolerance) + if directional_vector is None: # only check for co-planarity + for face in self.faces: + for srf_geo in surface_geometry: + pl1, pl2 = face.geometry.plane, srf_geo.plane + if pl1.is_coplanar_tolerance(pl2, tolerance, ang_tol): + pt_on_face = face.geometry._point_on_face(tolerance * 2) + if srf_geo.is_point_on_face(pt_on_face, tolerance): + selected_faces.append(face) + break + else: # first check to see if the Face is on the correct side of the surface + rev_vector = directional_vector.reverse() + for face in self.faces: + ray = Ray3D(face.center, rev_vector) + for srf_geo in surface_geometry: + if srf_geo.intersect_line_ray(ray): + selected_faces.append(face) + break + pl1, pl2 = face.geometry.plane, srf_geo.plane + if pl1.is_coplanar_tolerance(pl2, tolerance, ang_tol): + pt_on_face = face.geometry._point_on_face(tolerance * 2) + if srf_geo.is_point_on_face(pt_on_face, tolerance): + selected_faces.append(face) + break + return selected_faces
+ + +
+[docs] + def move(self, moving_vec): + """Move this Room along a vector. + + Args: + moving_vec: A ladybug_geometry Vector3D with the direction and distance + to move the room. + """ + for face in self._faces: + face.move(moving_vec) + self.move_shades(moving_vec) + self.properties.move(moving_vec) + if self._geometry is not None: + self._geometry = self.geometry.move(moving_vec)
+ + +
+[docs] + def rotate(self, axis, angle, origin): + """Rotate this Room by a certain angle around an axis and origin. + + Args: + axis: A ladybug_geometry Vector3D axis representing the axis of rotation. + angle: An angle for rotation in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + for face in self._faces: + face.rotate(axis, angle, origin) + self.rotate_shades(axis, angle, origin) + self.properties.rotate(axis, angle, origin) + if self._geometry is not None: + self._geometry = self.geometry.rotate(axis, math.radians(angle), origin)
+ + +
+[docs] + def rotate_xy(self, angle, origin): + """Rotate this Room counterclockwise in the world XY plane by a certain angle. + + Args: + angle: An angle in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + for face in self._faces: + face.rotate_xy(angle, origin) + self.rotate_xy_shades(angle, origin) + self.properties.rotate_xy(angle, origin) + if self._geometry is not None: + self._geometry = self.geometry.rotate_xy(math.radians(angle), origin)
+ + +
+[docs] + def reflect(self, plane): + """Reflect this Room across a plane. + + Args: + plane: A ladybug_geometry Plane across which the object will + be reflected. + """ + for face in self._faces: + face.reflect(plane) + self.reflect_shades(plane) + self.properties.reflect(plane) + if self._geometry is not None: + self._geometry = self.geometry.reflect(plane.n, plane.o)
+ + +
+[docs] + def scale(self, factor, origin=None): + """Scale this Room by a factor from an origin point. + + Args: + factor: A number representing how much the object should be scaled. + origin: A ladybug_geometry Point3D representing the origin from which + to scale. If None, it will be scaled from the World origin (0, 0, 0). + """ + for face in self._faces: + face.scale(factor, origin) + self.scale_shades(factor, origin) + self.properties.scale(factor, origin) + if self._geometry is not None: + self._geometry = self.geometry.scale(factor, origin)
+ + +
+[docs] + def remove_colinear_vertices_envelope(self, tolerance=0.01, delete_degenerate=False): + """Remove colinear and duplicate vertices from this object's Faces and Sub-faces. + + If degenerate geometry is found in the process of removing colinear vertices, + an exception will be raised. Note that this does not affect the assigned Shades. + + Args: + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered colinear. Default: 0.01, + suitable for objects in meters. + delete_degenerate: Boolean to note whether degenerate Faces, Apertures and + Doors (objects that evaluate to less than 3 vertices at the tolerance) + should be deleted from the Room instead of raising a ValueError. + (Default: False). + """ + if delete_degenerate: + new_faces, i_to_remove = list(self._faces), [] + for i, face in enumerate(new_faces): + try: + face.remove_colinear_vertices(tolerance) + face.remove_degenerate_sub_faces(tolerance) + except ValueError: # degenerate face found! + i_to_remove.append(i) + for i in reversed(i_to_remove): + new_faces.pop(i) + self._faces = tuple(new_faces) + else: + try: + for face in self._faces: + face.remove_colinear_vertices(tolerance) + for ap in face._apertures: + ap.remove_colinear_vertices(tolerance) + for dr in face._doors: + dr.remove_colinear_vertices(tolerance) + except ValueError as e: + raise ValueError( + 'Room "{}" contains invalid geometry.\n {}'.format( + self.full_id, str(e).replace('\n', '\n '))) + if self._geometry is not None: + self._geometry = Polyface3D.from_faces( + tuple(face.geometry for face in self._faces), tolerance)
+ + +
+[docs] + def clean_envelope(self, adjacency_dict, tolerance=0.01): + """Remove colinear and duplicate vertices from this object's Faces and Sub-faces. + + This method also automatically removes degenerate Faces and coordinates + adjacent Faces with the adjacency_dict to ensure matching numbers of + vertices, which is a requirement for engines like EnergyPlus. + + Args: + adjacency_dict: A dictionary containing the identifiers of Room Faces as + keys and Honeybee Face objects as values. This is used to indicate the + target number of vertices that each Face should have after colinear + vertices are removed. This can be used to ensure adjacent Faces + have matching numbers of vertices, which is a requirement for + certain interfaces like EnergyPlus. + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered colinear. Default: 0.01, + suitable for objects in meters. + + Returns: + A dictionary containing the identifiers of adjacent Faces as keys and + Honeybee Face objects as values. This can be used as an input in future + Rooms on which this method is run to ensure adjacent Faces have matching + numbers of vertices, which is a requirement for certain interfaces + like EnergyPlus. + """ + adj_dict = {} + new_faces, i_to_remove = list(self._faces), [] + for i, face in enumerate(new_faces): + try: # first make sure that the geometry is not degenerate + new_geo = face.geometry.remove_colinear_vertices(tolerance) + except AssertionError: # degenerate face found! + i_to_remove.append(i) + continue + # see if the geometry matches its adjacent geometry + if isinstance(face.boundary_condition, Surface): + try: + adj_face = adjacency_dict[face.identifier] + if len(new_geo) != len(adj_face.geometry): + new_geo = adj_face.geometry.flip() + except KeyError: # the adjacent object has not been found yet + pass + adj_dict[face.boundary_condition.boundary_condition_object] = face + # update geometry and remove degenerate Apertures and Doors + face._geometry = new_geo + face._punched_geometry = None # reset so that it can be re-computed + face.remove_degenerate_sub_faces(tolerance) + # remove any degenerate Faces from the Room + for i in reversed(i_to_remove): + new_faces.pop(i) + self._faces = tuple(new_faces) + if self._geometry is not None: + self._geometry = Polyface3D.from_faces( + tuple(face.geometry for face in self._faces), tolerance) + return adj_dict
+ + +
+[docs] + def is_geo_equivalent(self, room, tolerance=0.01): + """Get a boolean for whether this object is geometrically equivalent to another. + + This will also check all child Faces, Apertures, Doors and Shades + for equivalency. + + Args: + room: Another Room for which geometric equivalency will be tested. + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered geometrically equivalent. + + Returns: + True if geometrically equivalent. False if not geometrically equivalent. + """ + met_1 = (self.display_name, self.multiplier, self.story, self.exclude_floor_area) + met_2 = (room.display_name, room.multiplier, room.story, room.exclude_floor_area) + if met_1 != met_2: + return False + if len(self._faces) != len(room._faces): + return False + for f1, f2 in zip(self._faces, room._faces): + if not f1.is_geo_equivalent(f2, tolerance): + return False + if not self._are_shades_equivalent(room, tolerance): + return False + return True
+ + +
+[docs] + def check_solid(self, tolerance=0.01, angle_tolerance=1, raise_exception=True, + detailed=False): + """Check whether the Room is a closed solid to within the input tolerances. + + Args: + tolerance: tolerance: The maximum difference between x, y, and z values + at which face vertices are considered equivalent. Default: 0.01, + suitable for objects in meters. + angle_tolerance: The max angle difference in degrees that vertices are + allowed to differ from one another in order to consider them colinear. + Default: 1 degree. + raise_exception: Boolean to note whether a ValueError should be raised + if the room geometry does not form a closed solid. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + if self._geometry is not None and self.geometry.is_solid: + return [] if detailed else '' + face_geometries = tuple(face.geometry for face in self._faces) + self._geometry = Polyface3D.from_faces(face_geometries, tolerance) + if self.geometry.is_solid: + return [] if detailed else '' + ang_tol = math.radians(angle_tolerance) + self._geometry = self.geometry.merge_overlapping_edges(tolerance, ang_tol) + if self.geometry.is_solid: + return [] if detailed else '' + msg = 'Room "{}" is not closed to within {} tolerance and {} angle ' \ + 'tolerance.\n {} naked edges found\n {} non-manifold edges found'.format( + self.full_id, tolerance, angle_tolerance, + len(self._geometry.naked_edges), len(self._geometry.non_manifold_edges)) + full_msg = self._validation_message( + msg, raise_exception, detailed, '000106', + error_type='Non-Solid Room Geometry') + if detailed: # add the naked and non-manifold edges to helper_geometry + help_edges = [ln.to_dict() for ln in self.geometry.naked_edges] + help_edges.extend([ln.to_dict() for ln in self.geometry.non_manifold_edges]) + full_msg[0]['helper_geometry'] = help_edges + return full_msg
+ + +
+[docs] + def check_sub_faces_valid(self, tolerance=0.01, angle_tolerance=1, + raise_exception=True, detailed=False): + """Check that room's sub-faces are co-planar with faces and in the face boundary. + + Note this does not check the planarity of the sub-faces themselves, whether + they self-intersect, or whether they have a non-zero area. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. Default: 0.01, + suitable for objects in meters. + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered coplanar. + Default: 1 degree. + raise_exception: Boolean to note whether a ValueError should be raised + if an sub-face is not valid. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + detailed = False if raise_exception else detailed + msgs = [] + for f in self._faces: + msg = f.check_sub_faces_valid(tolerance, angle_tolerance, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + if len(msgs) == 0: + return [] if detailed else '' + elif detailed: + return msgs + full_msg = 'Room "{}" contains invalid sub-faces (Apertures and Doors).' \ + '\n {}'.format(self.full_id, '\n '.join(msgs)) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_sub_faces_overlapping( + self, tolerance=0.01, raise_exception=True, detailed=False): + """Check that this Room's sub-faces do not overlap with one another. + + Args: + tolerance: The minimum distance that two sub-faces must overlap in order + for them to be considered overlapping and invalid. (Default: 0.01, + suitable for objects in meters). + raise_exception: Boolean to note whether a ValueError should be raised + if a sub-faces overlap with one another. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + detailed = False if raise_exception else detailed + msgs = [] + for f in self._faces: + msg = f.check_sub_faces_overlapping(tolerance, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + if len(msgs) == 0: + return [] if detailed else '' + elif detailed: + return msgs + full_msg = 'Room "{}" contains overlapping sub-faces.' \ + '\n {}'.format(self.full_id, '\n '.join(msgs)) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_upside_down_faces( + self, angle_tolerance=1, raise_exception=True, detailed=False): + """Check whether the Room's Faces have the correct direction for the face type. + + This method will only report Floors that are pointing upwards or RoofCeilings + that are pointed downwards. These cases are likely modeling errors and are in + danger of having their vertices flipped by EnergyPlus, causing them to + not see the sun. + + Args: + angle_tolerance: The max angle in degrees that the Face normal can + differ from up or down before it is considered a case of a downward + pointing RoofCeiling or upward pointing Floor. Default: 1 degree. + raise_exception: Boolean to note whether an ValueError should be + raised if the Face is an an upward pointing Floor or a downward + pointing RoofCeiling. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + detailed = False if raise_exception else detailed + msgs = [] + for f in self._faces: + msg = f.check_upside_down(angle_tolerance, False, detailed) + if detailed: + msgs.extend(msg) + elif msg != '': + msgs.append(msg) + if len(msgs) == 0: + return [] if detailed else '' + elif detailed: + return msgs + full_msg = 'Room "{}" contains upside down Faces.' \ + '\n {}'.format(self.full_id, '\n '.join(msgs)) + if raise_exception and len(msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_planar(self, tolerance=0.01, raise_exception=True, detailed=False): + """Check that all of the Room's geometry components are planar. + + This includes all of the Room's Faces, Apertures, Doors and Shades. + + Args: + tolerance: The minimum distance between a given vertex and a the + object's plane at which the vertex is said to lie in the plane. + Default: 0.01, suitable for objects in meters. + raise_exception: Boolean to note whether an ValueError should be + raised if a vertex does not lie within the object's plane. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + detailed = False if raise_exception else detailed + msgs = [self._check_planar_shades(tolerance, detailed)] + for face in self._faces: + msgs.append(face.check_planar(tolerance, False, detailed)) + msgs.append(face._check_planar_shades(tolerance, detailed)) + for ap in face._apertures: + msgs.append(ap.check_planar(tolerance, False, detailed)) + msgs.append(ap._check_planar_shades(tolerance, detailed)) + for dr in face._doors: + msgs.append(dr.check_planar(tolerance, False, detailed)) + msgs.append(dr._check_planar_shades(tolerance, detailed)) + full_msgs = [msg for msg in msgs if msg] + if len(full_msgs) == 0: + return [] if detailed else '' + elif detailed: + return [m for megs in full_msgs for m in megs] + full_msg = 'Room "{}" contains non-planar geometry.' \ + '\n {}'.format(self.full_id, '\n '.join(full_msgs)) + if raise_exception and len(full_msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_self_intersecting(self, tolerance=0.01, raise_exception=True, + detailed=False): + """Check that no edges of the Room's geometry components self-intersect. + + This includes all of the Room's Faces, Apertures, Doors and Shades. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. Default: 0.01, + suitable for objects in meters. + raise_exception: If True, a ValueError will be raised if an object + intersects with itself (like a bow tie). (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + detailed = False if raise_exception else detailed + msgs = [self._check_self_intersecting_shades(tolerance, detailed)] + for face in self._faces: + msgs.append(face.check_self_intersecting(tolerance, False, detailed)) + msgs.append(face._check_self_intersecting_shades(tolerance, detailed)) + for ap in face._apertures: + msgs.append(ap.check_self_intersecting(tolerance, False, detailed)) + msgs.append(ap._check_self_intersecting_shades(tolerance, detailed)) + for dr in face._doors: + msgs.append(dr.check_self_intersecting(tolerance, False, detailed)) + msgs.append(dr._check_self_intersecting_shades(tolerance, detailed)) + full_msgs = [msg for msg in msgs if msg] + if len(full_msgs) == 0: + return [] if detailed else '' + elif detailed: + return [m for megs in full_msgs for m in megs] + full_msg = 'Room "{}" contains self-intersecting geometry.' \ + '\n {}'.format(self.full_id, '\n '.join(full_msgs)) + if raise_exception and len(full_msgs) != 0: + raise ValueError(full_msg) + return full_msg
+ + +
+[docs] + def check_degenerate(self, tolerance=0.01, raise_exception=True, detailed=False): + """Check whether the Room is degenerate with zero volume. + + Args: + tolerance: tolerance: The maximum difference between x, y, and z values + at which face vertices are considered equivalent. (Default: 0.01, + suitable for objects in meters). + raise_exception: Boolean to note whether a ValueError should be raised + if the room geometry is degenerate. (Default: True). + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + if len(self._faces) >= 4 and self.volume > tolerance: + return [] if detailed else '' + msg = 'Room "{}" is degenerate with zero volume. It should be deleted'.format( + self.full_id) + return self._validation_message( + msg, raise_exception, detailed, '000107', + error_type='Degenerate Room Volume')
+ + +
+[docs] + def merge_coplanar_faces( + self, tolerance=0.01, angle_tolerance=1, orthogonal_only=False): + """Merge coplanar Faces of this Room. + + This is often useful before running Room.intersect_adjacency between + multiple Rooms as it will ensure the result is clean with any previous + intersections erased. + + This method attempts to preserve as many properties as possible for the + split Faces but, when Faces are merged, the properties of one of the + merged faces will determine the face type and boundary condition. Also, all + Face extension attributes will be removed (reset to default) and, if merged + Faces originally had Surface boundary conditions, they will be reset + to Outdoors. + + Args: + tolerance: The minimum difference between the coordinate values of two + faces at which they can be considered adjacent. Default: 0.01, + suitable for objects in meters. + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered + coplanar. (Default: 1 degree). + orthogonal_only: A boolean to note whether only vertical and horizontal + coplanar faces should be merged, leaving faces with any other tilt + intact. Useful for cases where alignment of walls with the + Room.horizontal_boundary is desired without disrupting the roof + geometry. (Default: False). + + Returns: + A list containing only the new Faces that were created as part of the + merging process. These new Faces will have as many properties of the + original Face assigned to them as possible but they will not have a + Surface boundary condition if the original Face had one. Having + the new Faces here can be used in operations like setting new Surface + boundary conditions or re-assigning extension attributes. + """ + # group the Faces of the Room by their co-planarity + tol, a_tol = tolerance, math.radians(angle_tolerance) + coplanar_dict = {self._faces[0].geometry.plane: [self._faces[0]]} + if not orthogonal_only: + for face in self._faces[1:]: + for pln, f_list in coplanar_dict.items(): + if face.geometry.plane.is_coplanar_tolerance(pln, tol, a_tol): + f_list.append(face) + break + else: # the first face with this type of plane + coplanar_dict[face.geometry.plane] = [face] + else: + up_vec = Vector3D(0, 0, 1) + min_ang, max_ang = (math.pi / 2) - a_tol, (math.pi / 2) + a_tol + max_h_ang = math.pi + a_tol + for face in self._faces[1:]: + v_ang = up_vec.angle(face.normal) + if v_ang < a_tol or min_ang < v_ang < max_ang or v_ang > max_h_ang: + for pln, f_list in coplanar_dict.items(): + if face.geometry.plane.is_coplanar_tolerance(pln, tol, a_tol): + f_list.append(face) + break + else: # the first face with this type of plane + coplanar_dict[face.geometry.plane] = [face] + else: + coplanar_dict[face.geometry.plane] = [face] + + # merge any of the coplanar Faces together + all_faces, new_faces = [], [] + for face_list in coplanar_dict.values(): + if len(face_list) == 1: # no faces to merge + all_faces.append(face_list[0]) + else: # there are faces to merge + f_geos = [f.geometry for f in face_list] + joined_geos = Face3D.join_coplanar_faces(f_geos, tolerance) + if len(joined_geos) < len(f_geos): # faces were merged + prop_f = face_list[0] + apertures, doors, in_shades, out_shades = [], [], [], [] + for f in face_list: + apertures.extend(f._apertures) + doors.extend(f._doors) + in_shades.extend(f._indoor_shades) + out_shades.extend(f._outdoor_shades) + for i, new_geo in enumerate(joined_geos): + fid = prop_f.identifier if i == 0 else \ + '{}_{}'.format(prop_f.identifier, i) + fbc = prop_f.boundary_condition if not \ + isinstance(prop_f.boundary_condition, Surface) \ + else boundary_conditions.outdoors + nf = Face(fid, new_geo, prop_f.type, fbc) + for ap in apertures: + if nf.geometry.is_sub_face(ap.geometry, tol, a_tol): + nf.add_aperture(ap) + for dr in doors: + if nf.geometry.is_sub_face(dr.geometry, tol, a_tol): + nf.add_door(dr) + if i == 0: # add all assigned shades to this face + nf.add_indoor_shades(in_shades) + nf.add_outdoor_shades(out_shades) + nf._parent = self + all_faces.append(nf) + new_faces.append(nf) + else: # faces don't overlap and were not merged + all_faces.extend(face_list) + if len(new_faces) == 0: + return new_faces # nothing has been merged + + # make a new polyface from the updated faces + room_polyface = Polyface3D.from_faces( + tuple(face.geometry for face in all_faces), tolerance) + if not room_polyface.is_solid: + room_polyface = room_polyface.merge_overlapping_edges(tolerance, a_tol) + # replace honeybee face geometry with versions that are facing outwards + if room_polyface.is_solid: + for i, correct_face3d in enumerate(room_polyface.faces): + face = all_faces[i] + norm_init = face._geometry.normal + face._geometry = correct_face3d + if face.has_sub_faces: # flip sub-faces to align with parent Face + if norm_init.angle(face._geometry.normal) > (math.pi / 2): + for ap in face._apertures: + ap._geometry = ap._geometry.flip() + for dr in face._doors: + dr._geometry = dr._geometry.flip() + # reset the faces and geometry of the room with the new faces + self._faces = tuple(all_faces) + self._geometry = room_polyface + return new_faces
+ + +
+[docs] + def coplanar_split(self, geometry, tolerance=0.01, angle_tolerance=1): + """Split the Faces of this Room with coplanar geometry (Polyface3D or Face3D). + + This method attempts to preserve as many properties as possible for the + split Faces, including all extension attributes and sub-faces (as long + as they don't fall in the path of the intersection). + + Args: + geometry: A list of coplanar geometry (either Polyface3D or Face3D) + that will be used to split the Faces of this Room. Typically, these + are Polyface3D of other Room geometries to be intersected with this + one but they can also be Face3D if only one intersection is desired. + tolerance: The minimum difference between the coordinate values of two + faces at which they can be considered adjacent. Default: 0.01, + suitable for objects in meters. + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered + coplanar. (Default: 1 degree). + + Returns: + A list containing only the new Faces that were created as part of the + splitting process. These new Faces will have as many properties of the + original Face assigned to them as possible but they will not have a + Surface boundary condition if the original Face had one. Having just + the new Faces here can be used in operations like setting new Surface + boundary conditions. + """ + # make a dictionary of all face geometry to be intersected + geo_dict = {f.identifier: [f.geometry] for f in self.faces} + + # loop through the polyface geometries and intersect this room's geometry + ang_tol = math.radians(angle_tolerance) + for s_geo in geometry: + if isinstance(s_geo, Polyface3D) and not \ + Polyface3D.overlapping_bounding_boxes( + self.geometry, s_geo, tolerance): + continue # no overlap in bounding box; intersection impossible + s_geos = s_geo.faces if isinstance(s_geo, Polyface3D) else [s_geo] + for face_1 in self.faces: + for face_2 in s_geos: + if not face_1.geometry.plane.is_coplanar_tolerance( + face_2.plane, tolerance, ang_tol): + continue # not coplanar; intersection impossible + if face_1.geometry.is_centered_adjacent(face_2, tolerance): + tol_area = math.sqrt(face_1.geometry.area) * tolerance + if abs(face_1.geometry.area - face_2.area) < tol_area: + continue # already intersected; no need to re-do + new_geo = [] + for f_geo in geo_dict[face_1.identifier]: + f_split, _ = Face3D.coplanar_split( + f_geo, face_2, tolerance, ang_tol) + for sp_g in f_split: + try: + sp_g = sp_g.remove_colinear_vertices(tolerance) + new_geo.append(sp_g) + except AssertionError: # degenerate geometry to ignore + pass + geo_dict[face_1.identifier] = new_geo + + # use the intersected geometry to remake this room's faces + all_faces, new_faces = [], [] + for face in self.faces: + int_faces = geo_dict[face.identifier] + if len(int_faces) == 1: # just use the old Face object + all_faces.append(face) + else: # make new Face objects + new_bc = face.boundary_condition \ + if not isinstance(face.boundary_condition, Surface) \ + else boundary_conditions.outdoors + new_aps = [ap.duplicate() for ap in face.apertures] + new_drs = [dr.duplicate() for dr in face.doors] + for x, nf_geo in enumerate(int_faces): + new_id = '{}_{}'.format(face.identifier, x) + new_face = Face(new_id, nf_geo, face.type, new_bc) + new_face._display_name = face._display_name + new_face._user_data = None if face.user_data is None \ + else face.user_data.copy() + for ap in new_aps: + if nf_geo.is_sub_face(ap.geometry, tolerance, ang_tol): + new_face.add_aperture(ap) + for dr in new_drs: + if nf_geo.is_sub_face(dr.geometry, tolerance, ang_tol): + new_face.add_door(dr) + if x == 0: + face._duplicate_child_shades(new_face) + new_face._parent = face._parent + new_face._properties._duplicate_extension_attr(face._properties) + new_faces.append(new_face) + all_faces.append(new_face) + if len(new_faces) == 0: + return new_faces # nothing has been intersected + + # make a new polyface from the updated faces + room_polyface = Polyface3D.from_faces( + tuple(face.geometry for face in all_faces), tolerance) + if not room_polyface.is_solid: + room_polyface = room_polyface.merge_overlapping_edges(tolerance, ang_tol) + # replace honeybee face geometry with versions that are facing outwards + if room_polyface.is_solid: + for i, correct_face3d in enumerate(room_polyface.faces): + face = all_faces[i] + norm_init = face._geometry.normal + face._geometry = correct_face3d + if face.has_sub_faces: # flip sub-faces to align with parent Face + if norm_init.angle(face._geometry.normal) > (math.pi / 2): + for ap in face._apertures: + ap._geometry = ap._geometry.flip() + for dr in face._doors: + dr._geometry = dr._geometry.flip() + # reset the faces and geometry of the room with the new faces + self._faces = tuple(all_faces) + self._geometry = room_polyface + return new_faces
+ + +
+[docs] + @staticmethod + def intersect_adjacency(rooms, tolerance=0.01, angle_tolerance=1): + """Intersect the Faces of an array of Rooms to ensure matching adjacencies. + + Note that this method may remove Apertures and Doors if they align with + an intersection so it is typically recommended that this method be used + before sub-faces are assigned (if possible). Sub-faces that do not fall + along an intersection will be preserved. + + Also note that this method does not actually set the walls that are next to one + another to be adjacent. The solve_adjacency method must be used for this after + running this method. + + Args: + rooms: A list of Rooms for which adjacent Faces will be intersected. + tolerance: The minimum difference between the coordinate values of two + faces at which they can be considered adjacent. Default: 0.01, + suitable for objects in meters. + angle_tolerance: The max angle in degrees that the plane normals can + differ from one another in order for them to be considered + coplanar. (Default: 1 degree). + + Returns: + An array of Rooms that have been intersected with one another. + """ + # get all of the room polyfaces + room_geos = [r.geometry for r in rooms] + # intersect all adjacencies between rooms + for i, room in enumerate(rooms): + other_rooms = room_geos[:i] + room_geos[i + 1:] + room.coplanar_split(other_rooms, tolerance, angle_tolerance)
+ + +
+[docs] + @staticmethod + def solve_adjacency(rooms, tolerance=0.01): + """Solve for adjacencies between a list of rooms. + + Note that this method will mutate the input rooms by setting Surface + boundary conditions for any adjacent objects. However, it does NOT overwrite + existing Surface boundary conditions and only adds new ones if faces are + found to be adjacent with equivalent areas. + + Args: + rooms: A list of rooms for which adjacencies will be solved. + tolerance: The minimum difference between the coordinate values of two + faces at which they can be considered centered adjacent. Default: 0.01, + suitable for objects in meters. + + Returns: + A dictionary of information about the objects that had their adjacency set. + The dictionary has the following keys. + + - adjacent_faces - A list of tuples with each tuple containing 2 objects + for Faces paired in the process of solving adjacency. This data can + be used to assign custom properties to the new adjacent Faces (like + making all adjacencies an AirBoundary face type or assigning custom + materials/constructions). + + - adjacent_apertures - A list of tuples with each tuple containing 2 + objects for Apertures paired in the process of solving adjacency. + + - adjacent_doors - A list of tuples with each tuple containing 2 objects + for Doors paired in the process of solving adjacency. + """ + # lists of adjacencies to track + adj_info = {'adjacent_faces': [], 'adjacent_apertures': [], + 'adjacent_doors': []} + + # solve all adjacencies between rooms + for i, room_1 in enumerate(rooms): + try: + for room_2 in rooms[i + 1:]: + if not Polyface3D.overlapping_bounding_boxes( + room_1.geometry, room_2.geometry, tolerance): + continue # no overlap in bounding box; adjacency impossible + for face_1 in room_1._faces: + for face_2 in room_2._faces: + if not isinstance(face_2.boundary_condition, Surface): + if face_1.geometry.is_centered_adjacent( + face_2.geometry, tolerance): + face_info = face_1.set_adjacency(face_2) + adj_info['adjacent_faces'].append((face_1, face_2)) + adj_info['adjacent_apertures'].extend( + face_info['adjacent_apertures']) + adj_info['adjacent_doors'].extend( + face_info['adjacent_doors']) + break + except IndexError: + pass # we have reached the end of the list of rooms + return adj_info
+ + +
+[docs] + @staticmethod + def find_adjacency(rooms, tolerance=0.01): + """Get a list with all adjacent pairs of Faces between input rooms. + + Note that this method does not change any boundary conditions of the input + rooms or mutate them in any way. It's purely a geometric analysis of the + faces between rooms. + + Args: + rooms: A list of rooms for which adjacencies will be solved. + tolerance: The minimum difference between the coordinate values of two + faces at which they can be considered centered adjacent. Default: 0.01, + suitable for objects in meters. + + Returns: + A list of tuples with each tuple containing 2 objects for Faces that + are adjacent to one another. + """ + adj_faces = [] # lists of adjacencies to track + for i, room_1 in enumerate(rooms): + try: + for room_2 in rooms[i + 1:]: + if not Polyface3D.overlapping_bounding_boxes( + room_1.geometry, room_2.geometry, tolerance): + continue # no overlap in bounding box; adjacency impossible + for face_1 in room_1._faces: + for face_2 in room_2._faces: + if face_1.geometry.is_centered_adjacent( + face_2.geometry, tolerance): + adj_faces.append((face_1, face_2)) + break + except IndexError: + pass # we have reached the end of the list of zones + return adj_faces
+ + +
+[docs] + @staticmethod + def group_by_adjacency(rooms): + """Group Rooms together that are connected by adjacencies. + + This is useful for separating rooms in the case where a Model contains + multiple buildings or sections that are separated by adiabatic or + outdoor boundary conditions. + + Args: + rooms: A list of rooms to be grouped by their adjacency. + + Returns: + A list of list with each sub-list containing rooms that share adjacencies. + """ + return Room._adjacency_grouping(rooms, Room._find_adjacent_rooms)
+ + +
+[docs] + @staticmethod + def group_by_air_boundary_adjacency(rooms): + """Group Rooms together that share air boundaries. + + This is useful for understanding the radiant enclosures that will exist + when a model is exported to EnergyPlus. + + Args: + rooms: A list of rooms to be grouped by their air boundary adjacency. + + Returns: + A list of list with each sub-list containing rooms that share adjacent + air boundaries. If a Room has no air boundaries it will the the only + item within its sub-list. + """ + return Room._adjacency_grouping(rooms, Room._find_adjacent_air_boundary_rooms)
+ + +
+[docs] + @staticmethod + def group_by_orientation(rooms, group_count=None, north_vector=Vector2D(0, 1)): + """Group Rooms with the same average outdoor wall orientation. + + Args: + rooms: A list of honeybee rooms to be grouped by orientation. + group_count: An optional positive integer to set the number of orientation + groups to use. For example, setting this to 4 will result in rooms + being grouped by four orientations (North, East, South, West). If None, + the maximum number of unique groups will be used. + north_vector: A ladybug_geometry Vector2D for the north direction. + Default is the Y-axis (0, 1). + + Returns: + A tuple with three items. + + - grouped_rooms - A list of lists of honeybee rooms with each sub-list + representing a different orientation. + + - core_rooms - A list of honeybee rooms with no identifiable orientation. + + - orientations - A list of numbers between 0 and 360 with one orientation + for each branch of the output grouped_rooms. This will be a list of + angle ranges if a value is input for group_count. + """ + # loop through each of the rooms and get the orientation + orient_dict = {} + core_rooms = [] + for room in rooms: + ori = room.average_orientation(north_vector) + if ori is None: + core_rooms.append(room) + else: + try: + orient_dict[ori].append(room) + except KeyError: + orient_dict[ori] = [] + orient_dict[ori].append(room) + + # sort the rooms by orientation values + room_mtx = sorted(orient_dict.items(), key=lambda d: float(d[0])) + orientations = [r_tup[0] for r_tup in room_mtx] + grouped_rooms = [r_tup[1] for r_tup in room_mtx] + + # group orientations if there is an input group_count + if group_count is not None: + angs = angles_from_num_orient(group_count) + p_rooms = [[] for i in range(group_count)] + for ori, rm in zip(orientations, grouped_rooms): + or_ind = orient_index(ori, angs) + p_rooms[or_ind].extend(rm) + orientations = ['{} - {}'.format(int(angs[i - 1]), int(angs[i])) + for i in range(group_count)] + grouped_rooms = p_rooms + return grouped_rooms, core_rooms, orientations
+ + +
+[docs] + @staticmethod + def group_by_floor_height(rooms, min_difference=0.01): + """Group Rooms according to their average floor height. + + Args: + rooms: A list of honeybee rooms to be grouped by floor height. + min_difference: An float value to denote the minimum difference + in floor heights that is considered meaningful. This can be used + to ensure rooms like those representing stair landings are grouped + with those below them. Default: 0.01, which means that virtually + any minor difference in floor heights will result in a new group. + This assumption is suitable for models in meters. + + Returns: + A tuple with two items. + + - grouped_rooms - A list of lists of honeybee rooms with each sub-list + representing a different floor height. + + - floor_heights - A list of floor heights with one floor height for each + sub-list of the output grouped_rooms. + """ + # loop through each of the rooms and get the floor height + flrhgt_dict = {} + for room in rooms: + flrhgt = room.average_floor_height + try: # assume there is already a story with the room's floor height + flrhgt_dict[flrhgt].append(room) + except KeyError: # this is the first room with this floor height + flrhgt_dict[flrhgt] = [] + flrhgt_dict[flrhgt].append(room) + + # sort the rooms by floor heights + room_mtx = sorted(flrhgt_dict.items(), key=lambda d: float(d[0])) + flr_hgts = [r_tup[0] for r_tup in room_mtx] + rooms = [r_tup[1] for r_tup in room_mtx] + + # group floor heights if they differ by less than the min_difference + floor_heights = [flr_hgts[0]] + grouped_rooms = [rooms[0]] + for flrh, rm in zip(flr_hgts[1:], rooms[1:]): + if flrh - floor_heights[-1] < min_difference: + grouped_rooms[-1].extend(rm) + else: + grouped_rooms.append(rm) + floor_heights.append(flrh) + return grouped_rooms, floor_heights
+ + +
+[docs] + @staticmethod + def stories_by_floor_height(rooms, min_difference=2.0): + """Assign story properties to a set of Rooms using their floor heights. + + Stories will be named with a standard convention ('Floor1', 'Floor2', etc.). + Note that this method will only assign stories to Rooms that do not have + a story identifier already assigned to them. + + Args: + rooms: A list of rooms for which story properties will be automatically + assigned. + min_difference: An float value to denote the minimum difference + in floor heights that is considered meaningful. This can be used + to ensure rooms like those representing stair landings are grouped + with those below them. Default: 2.0, which means that any difference + in floor heights less than 2.0 will be considered a part of the + same story. This assumption is suitable for models in meters. + + Returns: + A list of the unique story names that were assigned to the input rooms. + """ + # group the rooms by floor height + new_rooms, _ = Room.group_by_floor_height(rooms, min_difference) + + # assign the story property to each of the groups + story_names = [] + for i, room_list in enumerate(new_rooms): + story_name = 'Floor{}'.format(i + 1) + story_names.append(story_name) + for room in room_list: + if room.story is not None: + continue # preserve any existing user-assigned story values + room.story = story_name + return story_names
+ + +
+[docs] + @staticmethod + def check_room_volume_collisions(rooms, tolerance=0.01, detailed=False): + """Check whether the volumes of Rooms collide with one another beyond tolerance. + + At the moment, this method only checks for the case where coplanar Floor + Faces of different Rooms overlap with one another, which clearly indicates + that there is definitely a collision between the Room volumes. In the + future, this method may be amended to sense more complex cases of + colliding Room volumes. For now, it is designed to only detect the most + common cases. + + Args: + rooms: A list of rooms that will be checked for volumetric collisions. + For this method to run most efficiently, these input Rooms should + be at the same horizontal floor level. The Room.group_by_floor_height() + method can be used to group the Rooms of a model according to their + height before running this method. + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. (Default: 0.01, + suitable for objects in meters. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + # create Polygon2Ds from the floors of the rooms + polys = [ + [(Polygon2D(Point2D(p.x, p.y) for p in flr.vertices), flr.geometry[0].z) + for flr in room.floors if flr.geometry.is_horizontal(tolerance)] + for room in rooms + ] + + # find the number of overlaps across the Rooms + msgs = [] + for i, (room_1, polys_1) in enumerate(zip(rooms, polys)): + overlap_rooms = [] + if len(polys_1) == 0: + continue + try: + for room_2, polys_2 in zip(rooms[i + 1:], polys[i + 1:]): + collision_found = False + for ply_1, z1 in polys_1: + if collision_found: + break + for ply_2, z2 in polys_2: + if collision_found: + break + if abs(z1 - z2) < tolerance: + if ply_1.polygon_relationship(ply_2, tolerance) >= 0: + overlap_rooms.append(room_2) + collision_found = True + break + except IndexError: + pass # we have reached the end of the list + + # of colliding rooms were found, create error messages + if len(overlap_rooms) != 0: + for room_2 in overlap_rooms: + msg = 'Room "{}" has a volume that collides with the volume ' \ + 'of Room "{}" more than the tolerance ({}).'.format( + room_1.display_name, room_2.display_name, tolerance) + msg = Room._validation_message_child( + msg, room_1, detailed, '000108', + error_type='Colliding Room Volumes') + if detailed: + msg['element_id'].append(room_2.identifier) + msg['element_name'].append(room_2.display_name) + msg['parents'].append(msg['parents'][0]) + msgs.append(msg) + # report any errors + if detailed: + return msgs + full_msg = '\n '.join(msgs) + return full_msg
+ + +
+[docs] + @staticmethod + def grouped_horizontal_boundary( + rooms, min_separation=0, tolerance=0.01, floors_only=True): + """Get a list of Face3D for the horizontal boundary around several Rooms. + + This method will attempt to produce a boundary that follows along the + outer parts of the Floors of the Rooms so it is not suitable for groups + of Rooms that overlap one another in plan. This method may return an empty + list if the min_separation is so large that a continuous boundary could not + be determined. + + Args: + rooms: A list of Honeybee Rooms for which the horizontal boundary will + be computed. + min_separation: A number for the minimum distance between Rooms that + is considered a meaningful separation. Gaps between Rooms that + are less than this distance will be ignored and the boundary + will continue across the gap. When the input rooms represent + volumes of interior Faces, this input can be thought of as the + maximum interior wall thickness, which should be ignored in + the calculation of the overall boundary of the Rooms. When Rooms + are touching one another (with Room volumes representing center lines + of walls), this value can be set to zero or anything less than + or equal to the tolerance. Doing so will yield a cleaner result for + the boundary, which will be faster. Note that care should be taken + not to set this value higher than the length of any meaningful + exterior wall segments. Otherwise, the exterior segments + will be ignored in the result. This can be particularly dangerous + around curved exterior walls that have been planarized through + subdivision into small segments. (Default: 0). + tolerance: The maximum difference between coordinate values of two + vertices at which they can be considered equivalent. (Default: 0.01, + suitable for objects in meters). + floors_only: A boolean to note whether the grouped boundary should only + surround the Floor geometries of the Rooms (True) or if they should + surround the entirety of the Room volumes in plan (False). + """ + # get the horizontal boundary geometry of each room + floor_geos = [] + if floors_only: + for room in rooms: + floor_geos.extend(room.horizontal_floor_boundaries(tolerance=tolerance)) + else: + for room in rooms: + floor_geos.append(room.horizontal_boundary(tolerance=tolerance)) + + # remove colinear vertices and degenerate faces + clean_floor_geos = [] + for geo in floor_geos: + try: + clean_floor_geos.append(geo.remove_colinear_vertices(tolerance)) + except AssertionError: # degenerate geometry to ignore + pass + if len(clean_floor_geos) == 0: + return [] # no Room boundary to be found + + # convert the floor Face3Ds into counterclockwise Polygon2Ds + floor_polys, z_vals = [], [] + for flr_geo in clean_floor_geos: + z_vals.append(flr_geo.min.z) + b_poly = Polygon2D([Point2D(pt.x, pt.y) for pt in flr_geo.boundary]) + floor_polys.append(b_poly) + if flr_geo.has_holes: + for hole in flr_geo.holes: + h_poly = Polygon2D([Point2D(pt.x, pt.y) for pt in hole]) + floor_polys.append(h_poly) + z_min = min(z_vals) + + # if the min_separation is small, use the more reliable intersection method + if min_separation <= tolerance: + closed_polys = Polygon2D.joined_intersected_boundary(floor_polys, tolerance) + else: # otherwise, use the more intense and less reliable gap crossing method + closed_polys = Polygon2D.gap_crossing_boundary( + floor_polys, min_separation, tolerance) + + # remove colinear vertices from the resulting polygons + clean_polys = [] + for poly in closed_polys: + try: + clean_polys.append(poly.remove_colinear_vertices(tolerance)) + except AssertionError: + pass # degenerate polygon to ignore + + # figure out if polygons represent holes in the others and make Face3D + if len(clean_polys) == 0: + return [] + elif len(clean_polys) == 1: # can be represented with a single Face3D + pts3d = [Point3D(pt.x, pt.y, z_min) for pt in clean_polys[0]] + return [Face3D(pts3d)] + else: # need to separate holes from distinct Face3Ds + bound_faces = [] + for poly in clean_polys: + pts3d = tuple(Point3D(pt.x, pt.y, z_min) for pt in poly) + bound_faces.append(Face3D(pts3d)) + return Face3D.merge_faces_to_holes(bound_faces, tolerance)
+ + +
+[docs] + @staticmethod + def rooms_from_rectangle_plan( + width, length, floor_to_floor_height, perimeter_offset=0, story_count=1, + orientation_angle=0, outdoor_roof=True, ground_floor=True, + unique_id=None, tolerance=0.01): + """Create a Rooms that represent a rectangular floor plan. + + Note that the resulting Rooms won't have any windows or solved adjacencies. + These can be added by using the Room.solve_adjacency method and the + various Face.apertures_by_XXX methods. + + Args: + width: Number for the width of the plan (in the X direction). + length: Number for the length of the plan (in the Y direction). + floor_to_floor_height: Number for the height of each floor of the model + (in the Z direction). + perimeter_offset: An optional positive number that will be used to offset + the perimeter to create core/perimeter Rooms. If this value is 0, + no offset will occur and each floor will have one Room. (Default: 0). + story_count: An integer for the number of stories to generate. (Default: 1). + orientation_angle: A number between 0 and 360 for the counterclockwise + orientation that the width of the box faces. (0=North, 90=East, + 180=South, 270=West). (Default: 0). + outdoor_roof: Boolean to note whether the roof faces of the top floor + should be outdoor or adiabatic. (Default: True). + ground_floor: Boolean to note whether the floor faces of the bottom + floor should be ground or adiabatic. (Default: True). + unique_id: Text for a unique identifier to be incorporated into all + of the Room identifiers. If None, a default one will be generated. + tolerance: The maximum difference between x, y, and z values at which + vertices are considered equivalent. (Default: 0.01, suitable + for objects in meters). + """ + footprint = [Face3D.from_rectangle(width, length)] + if perimeter_offset != 0: # use the straight skeleton methods + assert perimeter_offset > 0, 'perimeter_offset cannot be less than than 0.' + try: + footprint = [] + base = Polygon2D.from_rectangle(Point2D(), Vector2D(0, 1), width, length) + sub_polys_perim, sub_polys_core = perimeter_core_subpolygons( + polygon=base, distance=perimeter_offset, tolerance=tolerance) + for s_poly in sub_polys_perim + sub_polys_core: + sub_face = Face3D([Point3D(pt.x, pt.y, 0) for pt in s_poly]) + footprint.append(sub_face) + except RuntimeError: + pass + # create the honeybee rooms + if unique_id is None: + unique_id = str(uuid.uuid4())[:8] # unique identifier for the rooms + rm_ids = ['Room'] if len(footprint) == 1 else ['Front', 'Right', 'Back', 'Left'] + if len(footprint) == 5: + rm_ids.append('Core') + return Room.rooms_from_footprint( + footprint, floor_to_floor_height, rm_ids, unique_id, orientation_angle, + story_count, outdoor_roof, ground_floor)
+ + +
+[docs] + @staticmethod + def rooms_from_l_shaped_plan( + width_1, length_1, width_2, length_2, floor_to_floor_height, + perimeter_offset=0, story_count=1, orientation_angle=0, + outdoor_roof=True, ground_floor=True, unique_id=None, tolerance=0.01): + """Create a Rooms that represent an L-shaped floor plan. + + Note that the resulting Rooms in the model won't have any windows or solved + adjacencies. These can be added by using the Room.solve_adjacency method + and the various Face.apertures_by_XXX methods. + + Args: + width_1: Number for the width of the lower part of the L segment. + length_1: Number for the length of the lower part of the L segment, not + counting the overlap between the upper and lower segments. + width_2: Number for the width of the upper (left) part of the L segment. + length_2: Number for the length of the upper (left) part of the L segment, + not counting the overlap between the upper and lower segments. + floor_to_floor_height: Number for the height of each floor of the model + (in the Z direction). + perimeter_offset: An optional positive number that will be used to offset + the perimeter to create core/perimeter Rooms. If this value is 0, + no offset will occur and each floor will have one Room. (Default: 0). + story_count: An integer for the number of stories to generate. (Default: 1). + orientation_angle: A number between 0 and 360 for the counterclockwise + orientation that the width of the box faces. (0=North, 90=East, + 180=South, 270=West). (Default: 0). + outdoor_roof: Boolean to note whether the roof faces of the top floor + should be outdoor or adiabatic. (Default: True). + ground_floor: Boolean to note whether the floor faces of the bottom + floor should be ground or adiabatic. (Default: True). + unique_id: Text for a unique identifier to be incorporated into all + of the Room identifiers. If None, a default one will be generated. + tolerance: The maximum difference between x, y, and z values at which + vertices are considered equivalent. (Default: 0.01, suitable + for objects in meters). + """ + # create the geometry of the rooms for the first floor + max_x, max_y = width_2 + length_1, width_1 + length_2 + pts = [(0, 0), (max_x, 0), (max_x, width_1), (width_2, width_1), + (width_2, max_y), (0, max_y)] + footprint = Face3D(tuple(Point3D(*pt) for pt in pts)) + if perimeter_offset != 0: # use the straight skeleton methods + assert perimeter_offset > 0, 'perimeter_offset cannot be less than than 0.' + try: + footprint = [] + base = Polygon2D(tuple(Point2D(*pt) for pt in pts)) + sub_polys_perim, sub_polys_core = perimeter_core_subpolygons( + polygon=base, distance=perimeter_offset, tolerance=tolerance) + for s_poly in sub_polys_perim + sub_polys_core: + sub_face = Face3D([Point3D(pt.x, pt.y, 0) for pt in s_poly]) + footprint.append(sub_face) + except RuntimeError: + pass + # create the honeybee rooms + unique_id = '' if unique_id is None else '_{}'.format(unique_id) + rm_ids = ['Room'] if len(footprint) == 1 else \ + ['LongEdge1', 'End1', 'ShortEdge1', 'ShortEdge2', 'End2', 'LongEdge2'] + if len(footprint) == 7: + rm_ids.append('Core') + return Room.rooms_from_footprint( + footprint, floor_to_floor_height, rm_ids, unique_id, orientation_angle, + story_count, outdoor_roof, ground_floor)
+ + +
+[docs] + @staticmethod + def rooms_from_footprint( + footprints, floor_to_floor_height, room_ids=None, unique_id=None, + orientation_angle=0, story_count=1, outdoor_roof=True, ground_floor=True): + """Create several Honeybee Rooms from footprint Face3Ds. + + Args: + footprints: A list of Face3Ds representing the floors of Rooms. + floor_to_floor_height: Number for the height of each floor of the model + (in the Z direction). + room_ids: A list of strings for the identifiers of the Rooms to be generated. + If None, default unique IDs will be generated. (Default: None) + unique_id: Text for a unique identifier to be incorporated into all + Room identifiers. (Default: None). + orientation_angle: A number between 0 and 360 for the counterclockwise + orientation that the width of the box faces. (0=North, 90=East, + 180=South, 270=West). (Default: 0). + story_count: An integer for the number of stories to generate. (Default: 1). + outdoor_roof: Boolean to note whether the roof faces of the top floor + should be outdoor or adiabatic. (Default: True). + ground_floor: Boolean to note whether the floor faces of the bottom + floor should be ground or adiabatic. (Default: True). + """ + # set default identifiers if not provided + if room_ids is None: + room_ids = ['Room_{}'.format(str(uuid.uuid4())[:8]) for _ in footprints] + # extrude the footprint into solids + first_floor = [Polyface3D.from_offset_face(geo, floor_to_floor_height) + for geo in footprints] + # rotate the geometries if an orientation angle is specified + if orientation_angle != 0: + angle, origin = math.radians(orientation_angle), Point3D() + first_floor = [geo.rotate_xy(angle, origin) for geo in first_floor] + # create the initial rooms for the first floor + rooms = [] + unique_id = '' if unique_id is None else '_{}'.format(unique_id) + for polyface, rmid in zip(first_floor, room_ids): + rooms.append(Room.from_polyface3d('{}{}'.format(rmid, unique_id), polyface)) + # if there are multiple stories, duplicate the first floor rooms + if story_count != 1: + all_rooms = [] + for i in range(story_count): + for room in rooms: + new_room = room.duplicate() + new_room.add_prefix('Floor{}'.format(i + 1)) + m_vec = Vector3D(0, 0, floor_to_floor_height * i) + new_room.move(m_vec) + all_rooms.append(new_room) + rooms = all_rooms + # assign readable names for the display_name (without the UUID) + for room in rooms: + room.display_name = room.identifier[:-9] + # assign adiabatic boundary conditions if requested + if not outdoor_roof and ad_bc: + for room in rooms[-len(first_floor):]: + room[-1].boundary_condition = ad_bc # make the roof adiabatic + if not ground_floor and ad_bc: + for room in rooms[:len(first_floor)]: + room[0].boundary_condition = ad_bc # make the floor adiabatic + return rooms
+ + +
+[docs] + def display_dict(self): + """Get a list of DisplayFace3D dictionaries for visualizing the object.""" + base = [] + for f in self._faces: + base.extend(f.display_dict()) + for shd in self.shades: + base.extend(shd.display_dict()) + return base
+ + + @property + def to(self): + """Room writer object. + + Use this method to access Writer class to write the room in other formats. + + Usage: + + .. code-block:: python + + room.to.idf(room) -> idf string. + room.to.radiance(room) -> Radiance string. + """ + return writer + +
+[docs] + def to_extrusion(self, tolerance=0.01, angle_tolerance=1.0): + """Get a version of this Room that is an extruded floor plate with a flat roof. + + All boundary conditions and windows applied to vertical walls will be + preserved and the resulting Room should have a volume that matches the + current Room. If adding back apertures to the room extrusion results in + these apertures going past the parent wall Face, the windows of the Face + will be reduced to a simple window ratio. Any Surface boundary conditions + will be converted to Adiabatic (if honeybee-energy is installed) or + Outdoors (if not). + + The multiplier and all extension properties will also be preserved. + + This method is useful for exporting to platforms that cannot model Room + geometry beyond simple extrusions. The fact that the resulting room has + window areas and volumes that match the original detailed geometry + should help ensure the results in these platforms are close to what they + would be had the detailed geometry been modeled. + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which point they are considered co-located. (Default: 0.01, + suitable for objects in meters). + angle_tolerance: The angle tolerance at which the geometry will + be evaluated in degrees. (Default: 1 degree). + + Returns: + A Room that is an extruded floor plate with a flat roof. Note that, + if the Room is already an extrusion, the current Room instance will + be returned. + """ + # first, check whether the room is already an extrusion + if self.is_extrusion(tolerance, angle_tolerance): + return self + + # get the floor_geometry for the Room2D using the horizontal boundary + flr_geo = self.horizontal_boundary(match_walls=True, tolerance=tolerance) + flr_geo = flr_geo if flr_geo.normal.z >= 0 else flr_geo.flip() + + # match the segments of the floor geometry to walls of the Room + segs = flr_geo.boundary_segments if flr_geo.holes is None else \ + flr_geo.boundary_segments + \ + tuple(seg for hole in flr_geo.hole_segments for seg in hole) + wall_bcs = [boundary_conditions.outdoors] * len(segs) + sub_faces = [None] * len(segs) + for i, seg in enumerate(segs): + wall_f = self._segment_wall_face(seg, tolerance) + if wall_f is not None: + wall_bcs[i] = wall_f.boundary_condition + if len(wall_f._apertures) != 0 or len(wall_f._doors) != 0: + sf_objs = [h.duplicate() for h in wall_f._apertures + wall_f._doors] + if abs(wall_f.normal.z) <= 0.01: # vertical wall + sub_faces[i] = sf_objs + else: # angled wall; scale the Y to covert to vertical + w_geos = [sf.geometry for sf in sf_objs] + w_p = Plane(Vector3D(seg.v.y, -seg.v.x, 0), seg.p, seg.v) + w3d = [Face3D([p.project(w_p.n, w_p.o) for p in geo.boundary]) + for geo in w_geos] + proj_sf_objs = [] + for proj_geo, sf_obj in zip(w3d, sf_objs): + sf_obj._geometry = proj_geo + proj_sf_objs.append(sf_obj) + sub_faces[i] = proj_sf_objs + + # determine the ceiling height, and top/bottom boundary conditions + floor_to_ceiling_height = self.volume / flr_geo.area + is_ground_contact = all([isinstance(f.boundary_condition, Ground) + for f in self.faces if isinstance(f.type, Floor)]) + is_top_exposed = all([isinstance(f.boundary_condition, Outdoors) + for f in self.faces if isinstance(f.type, RoofCeiling)]) + + # create the new extruded Room object + ext_p_face = Polyface3D.from_offset_face(flr_geo, floor_to_ceiling_height) + ext_room = Room.from_polyface3d( + self.identifier, ext_p_face, ground_depth=float('-inf')) + + # assign BCs and replace any Surface conditions to be set on the story level + for i, bc in enumerate(wall_bcs): + if not isinstance(bc, Surface): + ext_room[i + 1]._boundary_condition = bc + elif ad_bc is not None: + ext_room[i + 1]._boundary_condition = ad_bc + + # assign windows and doors to walls + for i, sub_objs in enumerate(sub_faces): + if sub_objs is not None: + ext_f = ext_room[i + 1] + if isinstance(ext_f.boundary_condition, Outdoors): + ext_f.add_sub_faces(sub_objs) + subs_valid = ext_f.check_sub_faces_valid( + tolerance, angle_tolerance, False) == '' + if not subs_valid: # convert them to a simple ratio + wwr = ext_f.aperture_ratio + wwr = 0.99 if wwr > 0.99 else wwr + ext_f.apertures_by_ratio(wwr, tolerance) + base_ap = sub_objs[0] \ + if isinstance(sub_objs[0], Aperture) else None + if base_ap is not None: + for ap in ext_f.apertures: + ap._is_operable = base_ap._is_operable + ap._display_name = base_ap._display_name + ap._properties._duplicate_extension_attr( + base_ap._properties) + + # assign boundary conditions for the roof and floor + if is_ground_contact: + ext_room[0].boundary_condition = boundary_conditions.ground + elif ad_bc is not None: + ext_room[0].boundary_condition = ad_bc + if not is_top_exposed: + if ad_bc is not None: + ext_room[-1].boundary_condition = ad_bc + else: # check if there are any skylights to be added + rf_ht = flr_geo[0].z + floor_to_ceiling_height + skylights = [] + for f in self.faces: + if isinstance(f.type, RoofCeiling): + sf_objs = f._apertures + f._doors + for sf in sf_objs: + new_sf = sf.duplicate() + pts = [Point3D(pt.x, pt.y, rf_ht) for pt in sf.geometry.boundary] + new_sf._geometry = Face3D(pts) + new_sf.remove_shades() + skylights.append(new_sf) + if len(skylights) != 0: + ext_room[-1].add_sub_faces(skylights) + + # add the extra room attributes + ext_room._display_name = self._display_name + ext_room._user_data = None if self.user_data is None else self.user_data.copy() + ext_room._multiplier = self.multiplier + ext_room._story = self.story + ext_room._exclude_floor_area = self.exclude_floor_area + ext_room._properties._duplicate_extension_attr(self._properties) + return ext_room
+ + + def _segment_wall_face(self, segment, tolerance): + """Get a Wall Face that corresponds with a certain wall segment. + + Args: + segment: A LineSegment3D along one of the walls of the room. + tolerance: The maximum difference between values at which point vertices + are considered to be the same. + """ + for face in self.faces: + if isinstance(face.type, (Wall, AirBoundary)): + fg = face.geometry + try: + verts = fg._remove_colinear( + fg._boundary, fg.boundary_polygon2d, tolerance) + except AssertionError: + return None + for v1 in verts: + if segment.p1.is_equivalent(v1, tolerance): + p2 = segment.p2 + for v2 in verts: + if p2.is_equivalent(v2, tolerance): + return face + +
+[docs] + def to_dict(self, abridged=False, included_prop=None, include_plane=True): + """Return Room as a dictionary. + + Args: + abridged: Boolean to note whether the extension properties of the + object (ie. construction sets) should be included in detail + (False) or just referenced by identifier (True). Default: False. + included_prop: List of properties to filter keys that must be included in + output dictionary. For example ['energy'] will include 'energy' key if + available in properties to_dict. By default all the keys will be + included. To exclude all the keys from extensions use an empty list. + include_plane: Boolean to note wether the planes of the Face3Ds should be + included in the output. This can preserve the orientation of the + X/Y axes of the planes but is not required and can be removed to + keep the dictionary smaller. (Default: True). + """ + base = {'type': 'Room'} + base['identifier'] = self.identifier + base['display_name'] = self.display_name + base['properties'] = self.properties.to_dict(abridged, included_prop) + base['faces'] = [f.to_dict(abridged, included_prop, include_plane) + for f in self._faces] + self._add_shades_to_dict(base, abridged, included_prop, include_plane) + if self.multiplier != 1: + base['multiplier'] = self.multiplier + if self.story is not None: + base['story'] = self.story + if self.exclude_floor_area: + base['exclude_floor_area'] = self.exclude_floor_area + if self.user_data is not None: + base['user_data'] = self.user_data + return base
+ + + def _base_horiz_boundary(self, tolerance=0.01): + """Get a starting horizontal boundary for the Room. + + This is the raw result obtained by merging all downward-facing Faces of the Room. + + Args: + tolerance: The minimum difference between x, y, and z coordinate values + at which points are considered distinct. (Default: 0.01, + suitable for objects in Meters). + """ + z_axis = Vector3D(0, 0, 1) + flr_geo = [] + for face in self.faces: + if math.degrees(z_axis.angle(face.normal)) >= 91: + flr_geo.append(face.geometry) + if len(flr_geo) == 1: + if flr_geo[0].is_horizontal(tolerance): + return flr_geo[0] + else: + floor_height = self.geometry.min.z + bound = [Point3D(p.x, p.y, floor_height) for p in flr_geo[0].boundary] + holes = None + if flr_geo[0].has_holes: + holes = [[Point3D(p.x, p.y, floor_height) for p in hole] + for hole in flr_geo[0].holes] + return Face3D(bound, holes=holes) + else: # multiple geometries to be joined together + floor_height = self.geometry.min.z + horiz_geo = [] + for fg in flr_geo: + if fg.is_horizontal(tolerance) and \ + abs(floor_height - fg.min.z) <= tolerance: + horiz_geo.append(fg) + else: # project the face geometry into the XY plane + bound = [Point3D(p.x, p.y, floor_height) for p in fg.boundary] + holes = None + if fg.has_holes: + holes = [[Point3D(p.x, p.y, floor_height) for p in hole] + for hole in fg.holes] + horiz_geo.append(Face3D(bound, holes=holes)) + # sense if there are overlapping geometries to be boolean unioned + overlap_groups = Face3D.group_by_coplanar_overlap(horiz_geo, tolerance) + if all(len(g) == 1 for g in overlap_groups): # no overlaps; just join + return Face3D.join_coplanar_faces(horiz_geo, tolerance)[0] + # we must do a boolean union + clean_geo = [] + for og in overlap_groups: + if len(og) == 1: + clean_geo.extend(og) + else: + a_tol = math.radians(1) + union = Face3D.coplanar_union_all(og, tolerance, a_tol) + if len(union) == 1: + clean_geo.extend(union) + else: + sort_geo = sorted(union, key=lambda x: x.area, reverse=True) + clean_geo.append(sort_geo[0]) + if len(clean_geo) == 1: + return clean_geo[0] + return Face3D.join_coplanar_faces(clean_geo, tolerance)[0] + + def _match_walls_to_horizontal_faces(self, faces, tolerance): + """Insert vertices to horizontal faces so they align with the Room's Walls. + + Args: + faces: A list of Face3D into which the vertices of the walls will + be inserted. + tolerance: The minimum difference between x, y, and z coordinate values + at which points are considered distinct. (Default: 0.01, + suitable for objects in Meters). + """ + # get 2D vertices for all of the walls + wall_st_pts = [ + f.geometry.lower_left_counter_clockwise_vertices[0] for f in self.walls] + wall_st_pts_2d = [Point2D(v[0], v[1]) for v in wall_st_pts] + # insert the wall points into each of the faces + wall_faces = [] + for horiz_bound in faces: + # get 2D polygons for the horizontal boundary + z_val = horiz_bound[0].z + polys = [Polygon2D([Point2D(v.x, v.y) for v in horiz_bound.boundary])] + if horiz_bound.holes is not None: + for hole in horiz_bound.holes: + polys.append(Polygon2D([Point2D(v.x, v.y) for v in hole])) + # insert the wall vertices into the polygon + wall_polys = [] + for st_poly in polys: + st_poly = st_poly.remove_colinear_vertices(tolerance) + polygon_update = [] + for pt in wall_st_pts_2d: + for v in st_poly.vertices: # check if pt is already included + if pt.is_equivalent(v, tolerance): + break + else: + values = [seg.distance_to_point(pt) for seg in st_poly.segments] + if min(values) < tolerance: + index_min = min(range(len(values)), key=values.__getitem__) + polygon_update.append((index_min, pt)) + if polygon_update: + end_poly = Polygon2D._insert_updates_in_order(st_poly, polygon_update) + wall_polys.append(end_poly) + else: + wall_polys.append(st_poly) + # rebuild the Face3D from the polygons + pts_3d = [[Point3D(p.x, p.y, z_val) for p in poly] for poly in wall_polys] + wall_faces.append(Face3D(pts_3d[0], holes=pts_3d[1:])) + return wall_faces + + @staticmethod + def _adjacency_grouping(rooms, adj_finding_function): + """Group Rooms together according to an adjacency finding function. + + Args: + rooms: A list of rooms to be grouped by their adjacency. + adj_finding_function: A function that denotes which rooms are adjacent + to another. + + Returns: + A list of list with each sub-list containing rooms that share adjacencies. + """ + # create a room lookup table and duplicate the list of rooms + room_lookup = {rm.identifier: rm for rm in rooms} + all_rooms = list(rooms) + adj_network = [] + + # loop through the rooms and find air boundary adjacencies + for room in all_rooms: + adj_ids = adj_finding_function(room) + if len(adj_ids) == 0: # a room that is its own solar enclosure + adj_network.append([room]) + else: # there are other adjacent rooms to find + local_network = [room] + local_ids, first_id = set(adj_ids), room.identifier + while len(adj_ids) != 0: + # add the current rooms to the local network + adj_objs = [room_lookup[rm_id] for rm_id in adj_ids] + local_network.extend(adj_objs) + adj_ids = [] # reset the list of new adjacencies + # find any rooms that are adjacent to the adjacent rooms + for obj in adj_objs: + all_new_ids = adj_finding_function(obj) + new_ids = [rid for rid in all_new_ids + if rid not in local_ids and rid != first_id] + for rm_id in new_ids: + local_ids.add(rm_id) + adj_ids.extend(new_ids) + # after the local network is understood, clean up duplicated rooms + adj_network.append(local_network) + i_to_remove = [i for i, room_obj in enumerate(all_rooms) + if room_obj.identifier in local_ids] + for i in reversed(i_to_remove): + all_rooms.pop(i) + return adj_network + + @staticmethod + def _find_adjacent_rooms(room): + """Find the identifiers of all rooms with adjacency to a room.""" + adj_rooms = [] + for face in room._faces: + if isinstance(face.boundary_condition, Surface): + adj_rooms.append(face.boundary_condition.boundary_condition_objects[-1]) + return adj_rooms + + @staticmethod + def _find_adjacent_air_boundary_rooms(room): + """Find the identifiers of all rooms with air boundary adjacency to a room.""" + adj_rooms = [] + for face in room._faces: + if isinstance(face.type, AirBoundary) and \ + isinstance(face.boundary_condition, Surface): + adj_rooms.append(face.boundary_condition.boundary_condition_objects[-1]) + return adj_rooms + + def __copy__(self): + new_r = Room(self.identifier, tuple(face.duplicate() for face in self._faces)) + new_r._display_name = self._display_name + new_r._user_data = None if self.user_data is None else self.user_data.copy() + new_r._multiplier = self.multiplier + new_r._story = self.story + new_r._exclude_floor_area = self.exclude_floor_area + self._duplicate_child_shades(new_r) + new_r._geometry = self._geometry + new_r._properties._duplicate_extension_attr(self._properties) + return new_r + + def __len__(self): + return len(self._faces) + + def __getitem__(self, key): + return self._faces[key] + + def __iter__(self): + return iter(self._faces) + + def __repr__(self): + return 'Room: %s' % self.display_name
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/search.html b/docs/_modules/honeybee/search.html new file mode 100644 index 00000000..76946e24 --- /dev/null +++ b/docs/_modules/honeybee/search.html @@ -0,0 +1,1238 @@ + + + + + + + honeybee.search — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.search

+"""Collection of methods for searching for keywords and filtering lists by keywords.
+This module also included methods to get nested attributes of objects.
+
+This is useful for cases like the following:
+
+* Searching through the honeybee-radiance modifier library.
+* Searching through the honeybee-energy material, construction, schedule,
+  constructionset, or programtype libraries.
+* Searching through EnergyPlus IDD or RDD to find possible output variables
+  to request form the simulation.
+"""
+
+
+
+[docs] +def filter_array_by_keywords(array, keywords, parse_phrases=True): + """Filter an array of strings to get only those containing the given keywords. + + This method is case insensitive, allowing the searching of keywords across + different cases of letters. + + Args: + array: An array of strings which will be filtered to get only those containing + the given keywords. + keywords: An array of strings representing keywords. + parse_phrases: If True, this method will automatically parse any strings of + multiple keywords (separated by spaces) into separate keywords for + searching. This results in a greater likelihood that someone finds what + they are searching for in large arrays but it may not be appropriate for + all cases. You may want to set it to False when you are searching for a + specific phrase that includes spaces. Default: True. + """ + # split any keywords separated by spaces + if parse_phrases: + keywords = [kw for words in keywords for kw in words.upper().split()] + else: + keywords = [kw.upper() for kw in keywords] + + # filter the input array + return [item for item in array if any_keywords_in_string(item.upper(), keywords)]
+ + + +
+[docs] +def any_keywords_in_string(name, keywords): + """Check whether any keywords in an array exist within a given string. + + Args: + name: A string which will be tested for whether it possesses any of the keywords. + keywords: An array of strings representing keywords, which will be searched for + in the name. + """ + return all(kw in name for kw in keywords)
+ + + +
+[docs] +def get_attr_nested(obj_instance, attr_name, decimal_count=None, cast_to_str=True): + """Get the attribute of an object while allowing the request of nested attributes. + + Args: + obj_instance: An instance of a Python object. Typically, this is a honeybee + object like a Model, Room, Face, Aperture, Door, or Shade. + attr_name: A string of an attribute that the input obj_instance should have. + This can have '.' that separate the nested attributes from one another. + For example, 'properties.energy.construction'. + decimal_count: An optional integer to be used to round the property to a + number of decimal places if it is a float. (Default: None). + cast_to_str: Boolean to note whether attributes with a type other than + float should be cast to strings. If False, the attribute will be + returned with the original object type. (Default: True). + + Returns: + A string or number for tha attribute assigned ot the obj_instance. If the + input attr_name is a valid attribute for the object but None is assigned, + the output will be 'None'. If the input attr_name is not valid for + the input object, 'N/A' will be returned. + """ + if '.' in attr_name: # nested attribute + attributes = attr_name.split('.') # get all the sub-attributes + current_obj = obj_instance + try: + for attribute in attributes: + if current_obj is None: + raise AttributeError + elif isinstance(current_obj, dict): + current_obj = current_obj.get(attribute, None) + else: + current_obj = getattr(current_obj, attribute) + if isinstance(current_obj, float) and decimal_count: + return round(current_obj, decimal_count) + else: + return str(current_obj) if cast_to_str else current_obj + except AttributeError as e: + if 'NoneType' in str(e): # it's a valid attribute but it's not assigned + return 'None' + else: # it's not a valid attribute + return 'N/A' + else: # honeybee-core attribute + try: + current_obj = getattr(obj_instance, attr_name) + if isinstance(current_obj, float) and decimal_count: + return round(current_obj, decimal_count) + else: + return str(current_obj) if cast_to_str else current_obj + except AttributeError: + return 'N/A'
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/shade.html b/docs/_modules/honeybee/shade.html new file mode 100644 index 00000000..665f3df3 --- /dev/null +++ b/docs/_modules/honeybee/shade.html @@ -0,0 +1,1659 @@ + + + + + + + honeybee.shade — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.shade

+# coding: utf-8
+"""Honeybee Shade."""
+from __future__ import division
+import math
+
+from ladybug_geometry.geometry3d.pointvector import Point3D
+from ladybug_geometry.geometry3d.face import Face3D
+from ladybug.color import Color
+
+from ._base import _Base
+from .typing import clean_string
+from .properties import ShadeProperties
+import honeybee.writer.shade as writer
+
+
+
+[docs] +class Shade(_Base): + """A single planar shade. + + Args: + identifier: Text string for a unique Shade ID. Must be < 100 characters and + not contain any spaces or special characters. + geometry: A ladybug-geometry Face3D. + is_detached: Boolean to note whether this object is detached from other + geometry. Cases where this should be True include shade representing + surrounding buildings or context. (Default: False). + + Properties: + * identifier + * display_name + * is_detached + * parent + * top_level_parent + * has_parent + * is_indoor + * geometry + * vertices + * upper_left_vertices + * normal + * center + * area + * perimeter + * min + * max + * tilt + * altitude + * azimuth + * type_color + * bc_color + * user_data + """ + __slots__ = ('_geometry', '_parent', '_is_indoor', '_is_detached') + TYPE_COLORS = { + (False, False): Color(120, 75, 190), + (False, True): Color(80, 50, 128), + (True, False): Color(159, 99, 255), + (True, True): Color(159, 99, 255) + } + BC_COLOR = Color(120, 75, 190) + + def __init__(self, identifier, geometry, is_detached=False): + """A single planar shade.""" + _Base.__init__(self, identifier) # process the identifier + + # process the geometry and basic properties + assert isinstance(geometry, Face3D), \ + 'Expected ladybug_geometry Face3D. Got {}'.format(type(geometry)) + self._geometry = geometry + self._parent = None # _parent will be set when the Shade is added to an object + self._is_indoor = False # this will be set by the _parent + self.is_detached = is_detached + + # initialize properties for extensions + self._properties = ShadeProperties(self) + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize an Shade from a dictionary. + + Args: + data: A dictionary representation of an Shade object. + """ + try: + # check the type of dictionary + assert data['type'] == 'Shade', 'Expected Shade dictionary. ' \ + 'Got {}.'.format(data['type']) + + is_detached = data['is_detached'] if 'is_detached' in data else False + shade = cls( + data['identifier'], Face3D.from_dict(data['geometry']), is_detached) + if 'display_name' in data and data['display_name'] is not None: + shade.display_name = data['display_name'] + if 'user_data' in data and data['user_data'] is not None: + shade.user_data = data['user_data'] + + if data['properties']['type'] == 'ShadeProperties': + shade.properties._load_extension_attr_from_dict(data['properties']) + return shade + except Exception as e: + cls._from_dict_error_message(data, e)
+ + +
+[docs] + @classmethod + def from_vertices(cls, identifier, vertices, is_detached=False): + """Create a Shade from vertices with each vertex as an iterable of 3 floats. + + Note that this method is not recommended for a shade with one or more holes + since the distinction between hole vertices and boundary vertices cannot + be derived from a single list of vertices. + + Args: + identifier: Text string for a unique Shade ID. Must be < 100 characters and + not contain any spaces or special characters. + vertices: A flattened list of 3 or more vertices as (x, y, z). + is_detached: Boolean to note whether this object is detached from other + geometry. Cases where this should be True include shade representing + surrounding buildings or context. (Default: False). + """ + geometry = Face3D(tuple(Point3D(*v) for v in vertices)) + return cls(identifier, geometry, is_detached)
+ + + @property + def is_detached(self): + """Get or set a boolean for whether this object is detached from other geometry. + + This will automatically be set to False if the shade is assigned to + parent objects. + """ + return self._is_detached + + @is_detached.setter + def is_detached(self, value): + try: + self._is_detached = bool(value) + if self._is_detached: + assert not self.has_parent, 'Shade cannot be detached when it has ' \ + 'a parent Room, Face, Aperture or Door.' + except TypeError: + raise TypeError( + 'Expected boolean for Shade.is_detached. Got {}.'.format(value)) + + @property + def parent(self): + """Get the parent object if assigned. None if not assigned. + + The parent object can be either a Room, Face, Aperture or Door. + """ + return self._parent + + @property + def top_level_parent(self): + """Get the top-level parent object if assigned. + + This will be the highest-level parent in the hierarchy of the parent-child + chain. Will be None if no parent is assigned. + """ + if self.has_parent: + if self._parent.has_parent: + if self._parent._parent.has_parent: + return self._parent._parent._parent + return self._parent._parent + return self._parent + return None + + @property + def has_parent(self): + """Get a boolean noting whether this Shade has a parent object.""" + return self._parent is not None + + @property + def is_indoor(self): + """Get a boolean for whether this Shade is on the indoors of its parent object. + + Note that, if there is no parent assigned to this Shade, this property will + be False. + """ + return self._is_indoor + + @property + def geometry(self): + """Get a ladybug_geometry Face3D object representing the Shade.""" + return self._geometry + + @property + def vertices(self): + """Get a list of vertices for the shade (in counter-clockwise order).""" + return self._geometry.vertices + + @property + def upper_left_vertices(self): + """Get a list of vertices starting from the upper-left corner. + + This property should be used when exporting to EnergyPlus / OpenStudio. + """ + return self._geometry.upper_left_counter_clockwise_vertices + + @property + def normal(self): + """Get a ladybug_geometry Vector3D for the direction the shade is pointing. + """ + return self._geometry.normal + + @property + def center(self): + """Get a ladybug_geometry Point3D for the center of the shade. + + Note that this is the center of the bounding rectangle around this geometry + and not the area centroid. + """ + return self._geometry.center + + @property + def area(self): + """Get the area of the shade.""" + return self._geometry.area + + @property + def perimeter(self): + """Get the perimeter of the shade.""" + return self._geometry.perimeter + + @property + def min(self): + """Get a Point3D for the minimum of the bounding box around the object.""" + return self._geometry.min + + @property + def max(self): + """Get a Point3D for the maximum of the bounding box around the object.""" + return self._geometry.max + + @property + def tilt(self): + """Get the tilt of the geometry between 0 (up) and 180 (down).""" + return math.degrees(self._geometry.tilt) + + @property + def altitude(self): + """Get the altitude of the geometry between +90 (up) and -90 (down).""" + return math.degrees(self._geometry.altitude) + + @property + def azimuth(self): + """Get the azimuth of the geometry, between 0 and 360. + + Given Y-axis as North, 0 = North, 90 = East, 180 = South, 270 = West + This will be zero if the Face3D is perfectly horizontal. + """ + return math.degrees(self._geometry.azimuth) + + @property + def type_color(self): + """Get a Color to be used in visualizations by type.""" + return self.TYPE_COLORS[(self.is_indoor, self.is_detached)] + + @property + def bc_color(self): + """Get a Color to be used in visualizations by boundary condition.""" + return self.BC_COLOR + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier of this object by inserting a prefix. + + This is particularly useful in workflows where you duplicate and edit + a starting object and then want to combine it with the original object + into one Model (like making a model of repeated rooms) since all objects + within a Model must have unique identifiers. + + Args: + prefix: Text that will be inserted at the start of this object's identifier + and display_name. It is recommended that this prefix be short to + avoid maxing out the 100 allowable characters for honeybee identifiers. + """ + self._identifier = clean_string('{}_{}'.format(prefix, self.identifier)) + self.display_name = '{}_{}'.format(prefix, self.display_name) + self.properties.add_prefix(prefix)
+ + +
+[docs] + def move(self, moving_vec): + """Move this Shade along a vector. + + Args: + moving_vec: A ladybug_geometry Vector3D with the direction and distance + to move the face. + """ + self._geometry = self.geometry.move(moving_vec) + self.properties.move(moving_vec)
+ + +
+[docs] + def rotate(self, axis, angle, origin): + """Rotate this Shade by a certain angle around an axis and origin. + + Args: + axis: A ladybug_geometry Vector3D axis representing the axis of rotation. + angle: An angle for rotation in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate(axis, math.radians(angle), origin) + self.properties.rotate(axis, angle, origin)
+ + +
+[docs] + def rotate_xy(self, angle, origin): + """Rotate this Shade counterclockwise in the world XY plane by a certain angle. + + Args: + angle: An angle in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate_xy(math.radians(angle), origin) + self.properties.rotate_xy(angle, origin)
+ + +
+[docs] + def reflect(self, plane): + """Reflect this Shade across a plane. + + Args: + plane: A ladybug_geometry Plane across which the object will + be reflected. + """ + self._geometry = self.geometry.reflect(plane.n, plane.o) + self.properties.reflect(plane)
+ + +
+[docs] + def scale(self, factor, origin=None): + """Scale this Shade by a factor from an origin point. + + Args: + factor: A number representing how much the object should be scaled. + origin: A ladybug_geometry Point3D representing the origin from which + to scale. If None, it will be scaled from the World origin (0, 0, 0). + """ + self._geometry = self.geometry.scale(factor, origin) + self.properties.scale(factor, origin)
+ + +
+[docs] + def remove_colinear_vertices(self, tolerance=0.01): + """Remove all colinear and duplicate vertices from this object's geometry. + + Args: + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered colinear. Default: 0.01, + suitable for objects in meters. + """ + try: + self._geometry = self.geometry.remove_colinear_vertices(tolerance) + except AssertionError as e: # usually a sliver face of some kind + raise ValueError( + 'Shade "{}" is invalid with dimensions less than the ' + 'tolerance.\n{}'.format(self.full_id, e))
+ + +
+[docs] + def is_geo_equivalent(self, shade, tolerance=0.01): + """Get a boolean for whether this object is geometrically equivalent to another. + + The total number of vertices and the ordering of these vertices can be + different but the geometries must share the same center point and be + next to one another to within the tolerance. + + Args: + shade: Another Shade for which geometric equivalency will be tested. + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered geometrically equivalent. + + Returns: + True if geometrically equivalent. False if not geometrically equivalent. + """ + meta_1 = (self.display_name, self.is_detached) + meta_2 = (shade.display_name, shade.is_detached) + if meta_1 != meta_2: + return False + if abs(self.area - shade.area) > tolerance * self.area: + return False + return self.geometry.is_centered_adjacent(shade.geometry, tolerance)
+ + +
+[docs] + def check_planar(self, tolerance=0.01, raise_exception=True, detailed=False): + """Check whether all of the Shade's vertices lie within the same plane. + + Args: + tolerance: The minimum distance between a given vertex and a the + object's plane at which the vertex is said to lie in the plane. + Default: 0.01, suitable for objects in meters. + raise_exception: Boolean to note whether an ValueError should be + raised if a vertex does not lie within the object's plane. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + try: + self.geometry.check_planar(tolerance, raise_exception=True) + except ValueError as e: + msg = 'Shade "{}" is not planar.\n{}'.format(self.full_id, e) + full_msg = self._validation_message( + msg, raise_exception, detailed, '000101', + error_type='Non-Planar Geometry') + if detailed: # add the out-of-plane points to helper_geometry + help_pts = [ + p.to_dict() for p in self.geometry.non_planar_vertices(tolerance) + ] + full_msg[0]['helper_geometry'] = help_pts + return full_msg + return [] if detailed else ''
+ + +
+[docs] + def check_self_intersecting(self, tolerance=0.01, raise_exception=True, + detailed=False): + """Check whether the edges of the Shade intersect one another (like a bowtie). + + Args: + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered equivalent. Default: 0.01, + suitable for objects in meters. + raise_exception: If True, a ValueError will be raised if the object + intersects with itself. Default: True. + detailed: Boolean for whether the returned object is a detailed list of + dicts with error info or a string with a message. (Default: False). + + Returns: + A string with the message or a list with a dictionary if detailed is True. + """ + if self.geometry.is_self_intersecting: + msg = 'Shade "{}" has self-intersecting edges.'.format(self.full_id) + try: # see if it is self-intersecting because of a duplicate vertex + new_geo = self.geometry.remove_duplicate_vertices(tolerance) + if not new_geo.is_self_intersecting: + return [] if detailed else '' # valid with removed dup vertex + except AssertionError: + return [] if detailed else '' # degenerate geometry + full_msg = self._validation_message( + msg, raise_exception, detailed, '000102', + error_type='Self-Intersecting Geometry') + if detailed: # add the self-intersection points to helper_geometry + help_pts = [p.to_dict() for p in self.geometry.self_intersection_points] + full_msg[0]['helper_geometry'] = help_pts + return full_msg + return [] if detailed else ''
+ + +
+[docs] + def display_dict(self): + """Get a list of DisplayFace3D dictionaries for visualizing the object.""" + return [self._display_face(self.geometry, self.type_color)]
+ + + @property + def to(self): + """Shade writer object. + + Use this method to access Writer class to write the shade in different formats. + + Usage: + + .. code-block:: python + + shade.to.idf(shade) -> idf string. + shade.to.radiance(shade) -> Radiance string. + """ + return writer + +
+[docs] + def to_dict(self, abridged=False, included_prop=None, include_plane=True): + """Return Shade as a dictionary. + + Args: + abridged: Boolean to note whether the extension properties of the + object (ie. modifiers, transmittance schedule) should be included in + detail (False) or just referenced by identifier (True). Default: False. + included_prop: List of properties to filter keys that must be included in + output dictionary. For example ['energy'] will include 'energy' key if + available in properties to_dict. By default all the keys will be + included. To exclude all the keys from extensions use an empty list. + include_plane: Boolean to note wether the plane of the Face3D should be + included in the output. This can preserve the orientation of the + X/Y axes of the plane but is not required and can be removed to + keep the dictionary smaller. (Default: True). + """ + base = {'type': 'Shade'} + base['identifier'] = self.identifier + base['display_name'] = self.display_name + base['properties'] = self.properties.to_dict(abridged, included_prop) + enforce_upper_left = True if 'energy' in base['properties'] else False + base['geometry'] = self._geometry.to_dict(include_plane, enforce_upper_left) + if self.is_detached: + base['is_detached'] = self.is_detached + if self.user_data is not None: + base['user_data'] = self.user_data + return base
+ + + def __copy__(self): + new_shade = Shade(self.identifier, self.geometry, self.is_detached) + new_shade._display_name = self._display_name + new_shade._user_data = None if self.user_data is None else self.user_data.copy() + new_shade._properties._duplicate_extension_attr(self._properties) + return new_shade + + def __repr__(self): + return 'Shade: %s' % self.display_name
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/shademesh.html b/docs/_modules/honeybee/shademesh.html new file mode 100644 index 00000000..5da889bf --- /dev/null +++ b/docs/_modules/honeybee/shademesh.html @@ -0,0 +1,1509 @@ + + + + + + + honeybee.shademesh — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.shademesh

+# coding: utf-8
+"""Honeybee ShadeMesh."""
+from __future__ import division
+import math
+
+from ladybug_geometry.geometry3d import Mesh3D, Face3D
+from ladybug.color import Color
+
+from ._base import _Base
+from .typing import clean_string
+from .properties import ShadeMeshProperties
+import honeybee.writer.shademesh as writer
+
+
+
+[docs] +class ShadeMesh(_Base): + """A single planar shade. + + Args: + identifier: Text string for a unique Shade ID. Must be < 100 characters and + not contain any spaces or special characters. + geometry: A ladybug-geometry Mesh3D. + is_detached: Boolean to note whether this object is detached from other + geometry. Cases where this should be True include shade representing + surrounding buildings or context. (Default: True). + + Properties: + * identifier + * display_name + * is_detached + * geometry + * vertices + * faces + * center + * area + * min + * max + * type_color + * bc_color + * user_data + """ + __slots__ = ('_geometry', '_is_detached') + TYPE_COLORS = { + False: Color(120, 75, 190), + True: Color(80, 50, 128) + } + BC_COLOR = Color(120, 75, 190) + + def __init__(self, identifier, geometry, is_detached=True): + """A single planar shade.""" + _Base.__init__(self, identifier) # process the identifier + + # process the geometry and basic properties + assert isinstance(geometry, Mesh3D), \ + 'Expected ladybug_geometry Mesh3D. Got {}'.format(type(geometry)) + self._geometry = geometry + self.is_detached = is_detached + + # initialize properties for extensions + self._properties = ShadeMeshProperties(self) + +
+[docs] + @classmethod + def from_dict(cls, data): + """Initialize an ShadeMesh from a dictionary. + + Args: + data: A dictionary representation of an ShadeMesh object. + """ + try: + # check the type of dictionary + assert data['type'] == 'ShadeMesh', 'Expected ShadeMesh dictionary. ' \ + 'Got {}.'.format(data['type']) + + is_detached = data['is_detached'] if 'is_detached' in data else True + shade = cls( + data['identifier'], Mesh3D.from_dict(data['geometry']), is_detached) + if 'display_name' in data and data['display_name'] is not None: + shade.display_name = data['display_name'] + if 'user_data' in data and data['user_data'] is not None: + shade.user_data = data['user_data'] + + if data['properties']['type'] == 'ShadeMeshProperties': + shade.properties._load_extension_attr_from_dict(data['properties']) + return shade + except Exception as e: + cls._from_dict_error_message(data, e)
+ + + @property + def is_detached(self): + """Get or set a boolean for whether this object is detached from other geometry. + """ + return self._is_detached + + @is_detached.setter + def is_detached(self, value): + try: + self._is_detached = bool(value) + except TypeError: + raise TypeError( + 'Expected boolean for ShadeMesh.is_detached. Got {}.'.format(value)) + + @property + def geometry(self): + """Get a ladybug_geometry Mesh3D object representing the Shade.""" + return self._geometry + + @property + def vertices(self): + """Get a tuple of ladybug_geometry Point3D for the vertices of the mesh.""" + return self._geometry.vertices + + @property + def faces(self): + """Get a tuple of tuples for the faces of the mesh.""" + return self._geometry.faces + + @property + def center(self): + """Get a ladybug_geometry Point3D for the center of the shade. + + Note that this is the center of the bounding box around this geometry + and not the area or volume centroid. + """ + return self._geometry.center + + @property + def area(self): + """Get the surface area of the shade mesh.""" + return self._geometry.area + + @property + def min(self): + """Get a Point3D for the minimum of the bounding box around the object.""" + return self._geometry.min + + @property + def max(self): + """Get a Point3D for the maximum of the bounding box around the object.""" + return self._geometry.max + + @property + def type_color(self): + """Get a Color to be used in visualizations by type.""" + return self.TYPE_COLORS[self.is_detached] + + @property + def bc_color(self): + """Get a Color to be used in visualizations by boundary condition.""" + return self.BC_COLOR + +
+[docs] + def add_prefix(self, prefix): + """Change the identifier of this object by inserting a prefix. + + This is particularly useful in workflows where you duplicate and edit + a starting object and then want to combine it with the original object + into one Model (like making a model of repeated rooms) since all objects + within a Model must have unique identifiers. + + Args: + prefix: Text that will be inserted at the start of this object's identifier + and display_name. It is recommended that this prefix be short to + avoid maxing out the 100 allowable characters for honeybee identifiers. + """ + self._identifier = clean_string('{}_{}'.format(prefix, self.identifier)) + self.display_name = '{}_{}'.format(prefix, self.display_name) + self.properties.add_prefix(prefix)
+ + +
+[docs] + def move(self, moving_vec): + """Move this Shade along a vector. + + Args: + moving_vec: A ladybug_geometry Vector3D with the direction and distance + to move the face. + """ + self._geometry = self.geometry.move(moving_vec) + self.properties.move(moving_vec)
+ + +
+[docs] + def rotate(self, axis, angle, origin): + """Rotate this Shade by a certain angle around an axis and origin. + + Args: + axis: A ladybug_geometry Vector3D axis representing the axis of rotation. + angle: An angle for rotation in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate(axis, math.radians(angle), origin) + self.properties.rotate(axis, angle, origin)
+ + +
+[docs] + def rotate_xy(self, angle, origin): + """Rotate this Shade counterclockwise in the world XY plane by a certain angle. + + Args: + angle: An angle in degrees. + origin: A ladybug_geometry Point3D for the origin around which the + object will be rotated. + """ + self._geometry = self.geometry.rotate_xy(math.radians(angle), origin) + self.properties.rotate_xy(angle, origin)
+ + +
+[docs] + def reflect(self, plane): + """Reflect this Shade across a plane. + + Args: + plane: A ladybug_geometry Plane across which the object will + be reflected. + """ + self._geometry = self.geometry.reflect(plane.n, plane.o) + self.properties.reflect(plane)
+ + +
+[docs] + def scale(self, factor, origin=None): + """Scale this Shade by a factor from an origin point. + + Args: + factor: A number representing how much the object should be scaled. + origin: A ladybug_geometry Point3D representing the origin from which + to scale. If None, it will be scaled from the World origin (0, 0, 0). + """ + self._geometry = self.geometry.scale(factor, origin) + self.properties.scale(factor, origin)
+ + +
+[docs] + def triangulate_and_remove_degenerate_faces(self, tolerance=0.01): + """Triangulate non-planar faces in the mesh and remove all degenerate faces. + + This is helpful for certain geometry interfaces that require perfectly + planar geometry without duplicate or colinear vertices. + + Args: + tolerance: The minimum distance between a vertex and the boundary segments + at which point the vertex is considered colinear. Default: 0.01, + suitable for objects in meters. + """ + new_faces, verts = [], self.geometry.vertices + for shd in self.faces: + shd_verts = [verts[v] for v in shd] + shf = Face3D(shd_verts) + if len(shd_verts) == 4 and not \ + shf.check_planar(tolerance, raise_exception=False): + shades = ((shd[0], shd[1], shd[2]), (shd[2], shd[3], shd[0])) + for shade in shades: + shd_verts = [verts[v] for v in shade] + shade_face = Face3D(shd_verts) + try: + shade_face.remove_colinear_vertices(tolerance) + except AssertionError: + continue # degenerate face to remove + new_faces.append(shade) + else: + try: + new_face = shf.remove_colinear_vertices(tolerance) + except AssertionError: + continue # degenerate face to remove + if len(new_face.vertices) == len(shd): + new_faces.append(shd) + else: # quad face with duplicate or colinear verts + new_sh = tuple(shd[shd_verts.index(v)] for v in new_face.vertices) + new_faces.append(new_sh) + self._geometry = Mesh3D(verts, new_faces)
+ + +
+[docs] + def is_geo_equivalent(self, shade_mesh, tolerance=0.01): + """Get a boolean for whether this object is geometrically equivalent to another. + + The total number of vertices and the ordering of these vertices can be + different but the geometries must share the same center point and be + next to one another to within the tolerance. + + Args: + shade_mesh: Another ShadeMesh for which geometric equivalency will be tested. + tolerance: The minimum difference between the coordinate values of two + vertices at which they can be considered geometrically equivalent. + + Returns: + True if geometrically equivalent. False if not geometrically equivalent. + """ + meta_1 = (self.display_name, self.is_detached) + meta_2 = (shade_mesh.display_name, shade_mesh.is_detached) + if meta_1 != meta_2: + return False + if len(self.geometry.vertices) != len(shade_mesh.geometry.vertices): + return False + if len(self.geometry.faces) != len(shade_mesh.geometry.faces): + return False + return all(pt.is_equivalent(o_pt, tolerance) for pt, o_pt in + zip(self.geometry.vertices, shade_mesh.geometry.vertices))
+ + +
+[docs] + def display_dict(self): + """Get a list of DisplayMesh3D dictionaries for visualizing the object.""" + return [self._display_mesh(self.geometry, self.type_color)]
+ + + @property + def to(self): + """ShadeMesh writer object. + + Use this method to access Writer class to write the shade in different formats. + + Usage: + + .. code-block:: python + + shade_mesh.to.idf(shade) -> idf string. + shade_mesh.to.radiance(shade) -> Radiance string. + """ + return writer + +
+[docs] + def to_dict(self, abridged=False, included_prop=None): + """Return Shade as a dictionary. + + Args: + abridged: Boolean to note whether the extension properties of the + object (ie. modifiers, transmittance schedule) should be included in + detail (False) or just referenced by identifier (True). Default: False. + included_prop: List of properties to filter keys that must be included in + output dictionary. For example ['energy'] will include 'energy' key if + available in properties to_dict. By default all the keys will be + included. To exclude all the keys from extensions use an empty list. + """ + base = {'type': 'ShadeMesh'} + base['identifier'] = self.identifier + base['display_name'] = self.display_name + base['properties'] = self.properties.to_dict(abridged, included_prop) + base['geometry'] = self._geometry.to_dict() + if not self.is_detached: + base['is_detached'] = self.is_detached + if self.user_data is not None: + base['user_data'] = self.user_data + return base
+ + + @staticmethod + def _display_mesh(mesh3d, color): + """Create a DisplayMesh3D dictionary from a Mesh3D and color.""" + return { + 'type': 'DisplayMesh3D', + 'geometry': mesh3d.to_dict(), + 'color': color.to_dict(), + 'display_mode': 'SurfaceWithEdges' + } + + def __copy__(self): + new_shade = ShadeMesh(self.identifier, self.geometry, self.is_detached) + new_shade._display_name = self._display_name + new_shade._user_data = None if self.user_data is None else self.user_data.copy() + new_shade._properties._duplicate_extension_attr(self._properties) + return new_shade + + def __repr__(self): + return 'ShadeMesh: %s' % self.display_name
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/typing.html b/docs/_modules/honeybee/typing.html new file mode 100644 index 00000000..614d2b99 --- /dev/null +++ b/docs/_modules/honeybee/typing.html @@ -0,0 +1,1693 @@ + + + + + + + honeybee.typing — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.typing

+"""Collection of methods for type input checking."""
+import re
+import os
+import math
+import uuid
+
+try:
+    INFPOS = math.inf
+    INFNEG = -1 * math.inf
+except AttributeError:
+    # python 2
+    INFPOS = float('inf')
+    INFNEG = float('-inf')
+
+
+
+[docs] +def valid_string(value, input_name=''): + """Check that a string is valid for both Radiance and EnergyPlus. + + This is used for honeybee geometry object names. + """ + try: + illegal_match = re.search(r'[^.A-Za-z0-9_-]', value) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + assert illegal_match is None, 'Illegal character "{}" found in {}'.format( + illegal_match.group(0), input_name) + assert len(value) > 0, 'Input {} "{}" contains no characters.'.format( + input_name, value) + assert len(value) <= 100, 'Input {} "{}" must be less than 100 characters.'.format( + input_name, value) + return value
+ + + +
+[docs] +def valid_rad_string(value, input_name=''): + """Check that a string is valid for Radiance. + + This is used for radiance modifier names, etc. + """ + try: + illegal_match = re.search(r'[^.A-Za-z0-9_-]', value) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + assert illegal_match is None, 'Illegal character "{}" found in {}'.format( + illegal_match.group(0), input_name) + assert len(value) > 0, 'Input {} "{}" contains no characters.'.format( + input_name, value) + return value
+ + + +
+[docs] +def valid_ep_string(value, input_name=''): + """Check that a string is valid for EnergyPlus. + + This is used for energy material names, schedule names, etc. + """ + try: + non_ascii = tuple(i for i in value if ord(i) >= 128) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + assert non_ascii == (), 'Illegal characters {} found in {}'.format( + non_ascii, input_name) + illegal_match = re.search(r'[,;!\n\t]', value) + assert illegal_match is None, 'Illegal character "{}" found in {}'.format( + illegal_match.group(0), input_name) + assert len(value) > 0, 'Input {} "{}" contains no characters.'.format( + input_name, value) + assert len(value) <= 100, 'Input {} "{}" must be less than 100 characters.'.format( + input_name, value) + return value
+ + + +def _number_check(value, input_name): + """Check if value is a number.""" + try: + number = float(value) + except (ValueError, TypeError): + raise TypeError('Input {} must be a number. Got {}: {}.'.format( + input_name, type(value), value)) + return number + + +
+[docs] +def float_in_range(value, mi=INFNEG, ma=INFPOS, input_name=''): + """Check a float value to be between minimum and maximum.""" + number = _number_check(value, input_name) + assert mi <= number <= ma, 'Input number {} must be between {} and {}. ' \ + 'Got {}'.format(input_name, mi, ma, value) + return number
+ + + +
+[docs] +def float_in_range_excl(value, mi=INFNEG, ma=INFPOS, input_name=''): + """Check a float value to be greater than minimum and less than maximum.""" + number = _number_check(value, input_name) + assert mi < number < ma, 'Input number {} must be greater than {} ' \ + 'and less than {}. Got {}'.format(input_name, mi, ma, value) + return number
+ + + +
+[docs] +def float_in_range_excl_incl(value, mi=INFNEG, ma=INFPOS, input_name=''): + """Check a float value to be greater than minimum and less than/equal to maximum.""" + number = _number_check(value, input_name) + assert mi < number <= ma, 'Input number {} must be greater than {} and less than ' \ + 'or equal to {}. Got {}'.format(input_name, mi, ma, value) + return number
+ + + +
+[docs] +def float_in_range_incl_excl(value, mi=INFNEG, ma=INFPOS, input_name=''): + """Check a float value to be greater than/equal to minimum and less than maximum.""" + number = _number_check(value, input_name) + assert mi <= number < ma, 'Input number {} must be greater than or equal to {} ' \ + 'and less than {}. Got {}'.format(input_name, mi, ma, value) + return number
+ + + +
+[docs] +def int_in_range(value, mi=INFNEG, ma=INFPOS, input_name=''): + """Check an integer value to be between minimum and maximum.""" + try: + number = int(value) + except ValueError: + # try to convert to float and then digit if possible + try: + number = int(float(value)) + except (ValueError, TypeError): + raise TypeError('Input {} must be an integer. Got {}: {}.'.format( + input_name, type(value), value)) + except (ValueError, TypeError): + raise TypeError('Input {} must be an integer. Got {}: {}.'.format( + input_name, type(value), value)) + assert mi <= number <= ma, 'Input integer {} must be between {} and {}. ' \ + 'Got {}.'.format(input_name, mi, ma, value) + return number
+ + + +
+[docs] +def float_positive(value, input_name=''): + """Check a float value to be positive.""" + return float_in_range(value, 0, INFPOS, input_name)
+ + + +
+[docs] +def int_positive(value, input_name=''): + """Check if an integer value is positive.""" + return int_in_range(value, 0, INFPOS, input_name)
+ + + +
+[docs] +def tuple_with_length(value, length=3, item_type=float, input_name=''): + """Try to create a tuple with a certain value.""" + try: + value = tuple(item_type(v) for v in value) + except (ValueError, TypeError): + raise TypeError('Input {} must be a {}.'.format( + input_name, item_type)) + assert len(value) == length, 'Input {} length must be {} not {}'.format( + input_name, length, len(value)) + return value
+ + + +
+[docs] +def list_with_length(value, length=3, item_type=float, input_name=''): + """Try to create a list with a certain value.""" + try: + value = [item_type(v) for v in value] + except (ValueError, TypeError): + raise TypeError('Input {} must be a {}.'.format( + input_name, item_type)) + assert len(value) == length, 'Input {} length must be {} not {}'.format( + input_name, length, len(value)) + return value
+ + + +
+[docs] +def clean_string(value, input_name=''): + """Clean a string so that it is valid for both Radiance and EnergyPlus. + + This will strip out spaces and special characters and raise an error if the + string is empty after stripping or has more than 100 characters. + """ + try: + value = value.replace(' ', '_') # spaces > underscores for readability + val = re.sub(r'[^.A-Za-z0-9_-]', '', value) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + assert len(val) > 0, 'Input {} "{}" contains no valid characters.'.format( + input_name, value) + assert len(val) <= 100, 'Input {} "{}" must be less than 100 characters.'.format( + input_name, value) + return val
+ + + +
+[docs] +def clean_rad_string(value, input_name=''): + """Clean a string for Radiance that can be used for rad material names. + + This includes stripping out illegal characters and white spaces as well as + raising an error if no legal characters are found. + """ + try: + value = value.replace(' ', '_') # spaces > underscores for readability + val = re.sub(r'[^.A-Za-z0-9_-]', '', value) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + assert len(val) > 0, 'Input {} "{}" contains no valid characters.'.format( + input_name, value) + return val
+ + + +
+[docs] +def clean_ep_string(value, input_name=''): + """Clean a string for EnergyPlus that can be used for energy material names. + + This includes stripping out all illegal characters, removing trailing spaces, + and rasing an error if the name is not longer than 100 characters or no legal + characters found. + """ + try: + val = ''.join(i for i in value if ord(i) < 128) # strip out non-ascii + val = re.sub(r'[,;!\n\t]', '', val) # strip out E+ special characters + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + val = val.strip() + assert len(val) > 0, 'Input {} "{}" contains no valid characters.'.format( + input_name, value) + assert len(val) <= 100, 'Input {} "{}" must be less than 100 characters.'.format( + input_name, value) + return val
+ + + +
+[docs] +def clean_and_id_string(value, input_name=''): + """Clean a string and add 8 unique characters to it to make it unique. + + Strings longer than 50 characters will be truncated before adding the ID. + The resulting string will be valid for both Radiance and EnergyPlus. + """ + try: + value = value.replace(' ', '_') # spaces > underscores for readability + val = re.sub(r'[^.A-Za-z0-9_-]', '', value) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + if len(val) > 50: + val = val[:50] + return val + '_' + str(uuid.uuid4())[:8]
+ + + +
+[docs] +def clean_and_id_rad_string(value, input_name=''): + """Clean a string and add 8 unique characters to it to make it unique for Radiance. + + This includes stripping out illegal characters and white spaces. + """ + try: + value = value.replace(' ', '_') # spaces > underscores for readability + val = re.sub(r'[^.A-Za-z0-9_-]', '', value) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + return val + '_' + str(uuid.uuid4())[:8]
+ + + +
+[docs] +def clean_and_id_ep_string(value, input_name=''): + """Clean a string and add 8 unique characters to it to make it unique for EnergyPlus. + + This includes stripping out all illegal characters and removing trailing white spaces. + Strings longer than 50 characters will be truncated before adding the ID. + """ + try: + val = ''.join(i for i in value if ord(i) < 128) # strip out non-ascii + val = re.sub(r'[,;!\n\t]', '', val) # strip out E+ special characters + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + val = val.strip() + if len(val) > 50: + val = val[:50] + return val + '_' + str(uuid.uuid4())[:8]
+ + + +
+[docs] +def clean_and_number_string(value, existing_dict, input_name=''): + """Clean a string and add an integer to it if it is found in the existing_dict. + + The resulting string will be valid for both Radiance and EnergyPlus. + + Args: + value: The text string to be cleaned and possibly given a unique integer. + existing_dict: A dictionary where the keys are text strings of existing items + and the values are the number of times that the item has appeared in + the model already. + """ + try: + value = value.replace(' ', '_') # spaces > underscores for readability + val = re.sub(r'[^.A-Za-z0-9_-]', '_', value) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + if len(val) > 95: + val = val[:95] + if val in existing_dict: + existing_dict[val] += 1 + return val + '_' + str(existing_dict[val]) + else: + existing_dict[val] = 1 + return val
+ + + +
+[docs] +def clean_and_number_rad_string(value, existing_dict, input_name=''): + """Clean a string for Radiance and add an integer if found in the existing_dict. + + This includes stripping out illegal characters and white spaces. + + Args: + value: The text string to be cleaned and possibly given a unique integer. + existing_dict: A dictionary where the keys are text strings of existing items + and the values are the number of times that the item has appeared in + the model already. + """ + try: + value = value.replace(' ', '_') # spaces > underscores for readability + val = re.sub(r'[^.A-Za-z0-9_-]', '_', value) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + if val in existing_dict: + existing_dict[val] += 1 + return val + '_' + str(existing_dict[val]) + else: + existing_dict[val] = 1 + return val
+ + + +
+[docs] +def clean_and_number_ep_string(value, existing_dict, input_name=''): + """Clean a string for EnergyPlus and add an integer if found in the existing_dict. + + This includes stripping out all illegal characters and removing trailing white spaces. + Strings longer than 95 characters will be truncated before adding the integer. + + Args: + value: The text string to be cleaned and possibly given a unique integer. + existing_dict: A dictionary where the keys are text strings of existing items + and the values are the number of times that the item has appeared in + the model already. + """ + try: + val = ''.join(i for i in value if ord(i) < 128) # strip out non-ascii + val = re.sub(r'[,;!\n\t]', '', val) # strip out E+ special characters + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + val = val.strip() + if len(val) > 95: + val = val[:95] + if val in existing_dict: + existing_dict[val] += 1 + return val + ' ' + str(existing_dict[val]) + else: + existing_dict[val] = 1 + return val
+ + + +
+[docs] +def truncate_and_id_string(value, truncate_len=32, uuid_len=0, input_name=''): + """Truncate a string to a length with an option to add unique characters at the end. + + Note that all outputs will always be the truncate_len or less and the uuid_len + just specifies the number of characters to replace at the end with unique ones. + + The result will be valid for EnergyPlus, Radiance, and likely many more engines + with different types of character restrictions. + """ + try: + value = value.replace(' ', '_') # spaces > underscores for readability + val = re.sub(r'[^.A-Za-z0-9_-]', '', value) + except TypeError: + raise TypeError('Input {} must be a text string. Got {}: {}.'.format( + input_name, type(value), value)) + final_len = truncate_len - uuid_len + if len(val) > final_len: + val = val[:final_len] + if uuid_len > 0: + return val + str(uuid.uuid4())[:uuid_len] + return val
+ + + +
+[docs] +def fixed_string_length(value, target_len=32): + """Truncate a string or add trailing spaces to hit a target character length. + + This is useful when trying to construct human-readable tables of text. + """ + if len(value) > target_len: + return value[:target_len] + elif len(value) < target_len: + return value + ' ' * (target_len - len(value)) + else: + return value
+ + + +
+[docs] +def readable_short_name(value, max_length=24): + """Convert a string into a shorter but readable version of itself. + + This is useful when dealing with interfaces of file formats that have very + strict character limits on names or identifiers (like in DOE-2/eQuest). + + When ths input is less than or equal to the max length, the string will be + left as-is. If not, then the lower-case vowels will be removed from the name, + making the result abbreviated but still readable/recognizable. If the result + is still not shorter than the max length, then spaces will be removed. Lastly, + if all else fails to meet the max length, the middle characters will be, + removed leaving the beginning and end as they are, which should typically + help preserve the uniqueness of the name. + + Note that this method does not do any check for illegal characters and presumes + that the input is already composed of legal characters. + """ + # perform an initial check to see if it passes + if len(value) <= max_length: + return value + # strip out lowercase vowels and special characters like dashes + try: + value = re.sub(r'[aeiouy_\-]', '', value) + except TypeError: + raise TypeError('Input must be a text string. Got {}: {}.'.format( + type(value), value)) + if len(value) <= max_length: + return value + # remove spaces from the string to see if it gets short enough + value = value.replace(' ', '') + if len(value) <= max_length: + return value + # lastly, remove some characters from the middle to get it to fit + mid_ind = int(max_length * 0.5) + assert mid_ind > 3, \ + 'Max character length of {} is too restrictive.'.format(max_length) + end_length = max_length - mid_ind - 1 + value = '{}_{}'.format(value[:mid_ind], value[-end_length:]) + return value
+ + + +
+[docs] +def clean_doe2_string(value, max_length=24): + """Clean and shorten a string for DOE-2 so that it can be a U-name. + + This includes stripping out all illegal characters (including both non-ASCII + and DOE-2 specific characters), removing trailing spaces, and passing the + result through the readable_short_name function to hit the target max_length. + Note that white spaces can be in the result with the assumption that + the name will be enclosed in double quotes. + + Note that this method does not do any check to ensure the string is unique. + """ + try: + val = ''.join(i for i in value if ord(i) < 128) # strip out non-ascii + val = re.sub(r'["\(\)\[\]\,\=\n\t]', '', val) # remove DOE-2 special characters + val = val.replace('_', ' ') # put back white spaces + except TypeError: + raise TypeError('Input must be a text string. Got {}: {}.'.format( + type(value), value)) + val = val.strip() + return readable_short_name(val, max_length)
+ + + +
+[docs] +def invalid_dict_error(invalid_dict, error): + """Raise a ValueError for an invalid dictionary that failed to serialize. + + This error message will include the identifier (and display_name) if they are + present within the invalid_dict, making it easier for ens users to find the + invalid object within large objects like Models. + + Args: + invalid_dict: A dictionary of an invalid honeybee object that failed + to serialize. + error: + """ + obj_type = invalid_dict['type'].replace('Abridged', '') \ + if 'type' in invalid_dict else 'Honeybee Object' + obj_id = invalid_dict['identifier'] if 'identifier' in invalid_dict else '' + full_id = '{}[{}]'.format(invalid_dict['display_name'], obj_id) \ + if 'display_name' in invalid_dict else obj_id + raise ValueError('{} "{}" is invalid:\n{}'.format(obj_type, full_id, error))
+ + + +wrapper = '"' if os.name == 'nt' else '\'' +"""String wrapper.""" + + +
+[docs] +def normpath(value): + """Normalize path eliminating double slashes, etc and put it in quotes if needed.""" + value = os.path.normpath(value) + if ' ' in value: + value = '{0}{1}{0}'.format(wrapper, value) + return value
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/honeybee/units.html b/docs/_modules/honeybee/units.html new file mode 100644 index 00000000..585bad55 --- /dev/null +++ b/docs/_modules/honeybee/units.html @@ -0,0 +1,1222 @@ + + + + + + + honeybee.units — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +

Source code for honeybee.units

+"""Utility functions for converting and parsing units of length."""
+
+# global properties to set all supported units
+UNITS = ('Meters', 'Millimeters', 'Feet', 'Inches', 'Centimeters')
+UNITS_ABBREVIATIONS = ('m', 'mm', 'ft', 'in', 'cm')
+UNITS_TOLERANCES = {
+    'Meters': 0.01,
+    'Millimeters': 1.0,
+    'Feet': 0.01,
+    'Inches': 0.1,
+    'Centimeters': 1.0
+}
+
+
+
+[docs] +def conversion_factor_to_meters(units): + """Get the conversion factor to meters based on input units. + + Args: + units: Text for the units. Choose from the following: + + * Meters + * Millimeters + * Feet + * Inches + * Centimeters + + Returns: + A number for the conversion factor, which should be multiplied by + all distance units taken from Rhino geometry in order to convert + them to meters. + """ + if units == 'Meters': + return 1.0 + elif units == 'Millimeters': + return 0.001 + elif units == 'Feet': + return 0.3048 + elif units == 'Inches': + return 0.0254 + elif units == 'Centimeters': + return 0.01 + else: + raise ValueError( + 'You are kidding me! What units are you using? {}?\n' + 'Please use one of the following: {}'.format(units, ' '.join(UNITS)) + )
+ + + +
+[docs] +def parse_distance_string(distance_string, destination_units='Meters'): + """Parse a string of a distance value into a destination units system. + + Args: + distance_string: Text for a distance value to be parsed into the + destination units. This can have the units at the end of + it (eg. "3ft"). If no units are included, the number will be + assumed to be in the destination units system. + destination_units: The destination units system to which the distance + string will be computed. (Default: Meters). + + Returns: + A number for the distance in the destination_units. + """ + # separate the distance string into a number and a unit abbreviation + distance_string = distance_string.strip().replace(',', '.') + try: # check if the distance string is just a number + return float(distance_string) + except ValueError: # it must have some units attached to it + for i, ua in enumerate(UNITS_ABBREVIATIONS): + try: # see if replacing the units yields a float + distance = float(distance_string.replace(ua, '', 1)) + u_sys = UNITS[i] + break + except ValueError: # not the right type of units + pass + else: # we could not match the units system + raise ValueError( + 'Text string "{}" could not be decoded into a distance and a unit.\n' + 'Make sure your units are one of the following: {}'.format( + distance_string, ' '.join(UNITS_ABBREVIATIONS)) + ) + + # process the number into the destination units system + if u_sys == destination_units: + return distance + con_factor = 1 / conversion_factor_to_meters(destination_units) + if u_sys != 'Meters': + con_factor = con_factor * conversion_factor_to_meters(u_sys) + return distance * con_factor
+ +
+ +
+ +
+
+
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_modules/index.html b/docs/_modules/index.html new file mode 100644 index 00000000..6717d87a --- /dev/null +++ b/docs/_modules/index.html @@ -0,0 +1,1150 @@ + + + + + + + Overview: module code — honeybee documentation + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+ Back to top + +

+

+ © Copyright 2024, Ladybug Tools.
+ Created using Sphinx 8.0.2.
+

+
+
+ + \ No newline at end of file diff --git a/docs/_sources/cli/compare.rst.txt b/docs/_sources/cli/compare.rst.txt new file mode 100644 index 00000000..dc2967d3 --- /dev/null +++ b/docs/_sources/cli/compare.rst.txt @@ -0,0 +1,6 @@ +compare +======= + +.. click:: honeybee.cli.compare:compare + :prog: honeybee compare + :show-nested: diff --git a/docs/_sources/cli/create.rst.txt b/docs/_sources/cli/create.rst.txt new file mode 100644 index 00000000..1a6e1885 --- /dev/null +++ b/docs/_sources/cli/create.rst.txt @@ -0,0 +1,6 @@ +create +====== + +.. click:: honeybee.cli.create:create + :prog: honeybee create + :show-nested: diff --git a/docs/_sources/cli/edit.rst.txt b/docs/_sources/cli/edit.rst.txt new file mode 100644 index 00000000..96b50ad5 --- /dev/null +++ b/docs/_sources/cli/edit.rst.txt @@ -0,0 +1,6 @@ +edit +==== + +.. click:: honeybee.cli.edit:edit + :prog: honeybee edit + :show-nested: diff --git a/docs/_sources/cli/index.rst.txt b/docs/_sources/cli/index.rst.txt new file mode 100644 index 00000000..16dafb87 --- /dev/null +++ b/docs/_sources/cli/index.rst.txt @@ -0,0 +1,21 @@ +CLI Docs +======== + +Installation +------------ + +To check if the Honeybee command line interface is installed correctly try ``honeybee viz`` and you +should get a ``viiiiiiiiiiiiizzzzzzzzz!`` back in response! + +Commands +-------- +.. toctree:: + :maxdepth: 1 + + main + setconfig + create + validate + lib + compare + edit diff --git a/docs/_sources/cli/lib.rst.txt b/docs/_sources/cli/lib.rst.txt new file mode 100644 index 00000000..3e7028fc --- /dev/null +++ b/docs/_sources/cli/lib.rst.txt @@ -0,0 +1,6 @@ +lib +=== + +.. click:: honeybee.cli.lib:lib + :prog: honeybee lib + :show-nested: diff --git a/docs/_sources/cli/main.rst.txt b/docs/_sources/cli/main.rst.txt new file mode 100644 index 00000000..d9c70d8d --- /dev/null +++ b/docs/_sources/cli/main.rst.txt @@ -0,0 +1,7 @@ +main +==== + +.. click:: honeybee.cli.__init__:main + :prog: honeybee + :show-nested: + :commands: config ,viz diff --git a/docs/_sources/cli/setconfig.rst.txt b/docs/_sources/cli/setconfig.rst.txt new file mode 100644 index 00000000..b98d5236 --- /dev/null +++ b/docs/_sources/cli/setconfig.rst.txt @@ -0,0 +1,6 @@ +setconfig +========= + +.. click:: honeybee.cli.setconfig:set_config + :prog: honeybee set-config + :show-nested: diff --git a/docs/_sources/cli/validate.rst.txt b/docs/_sources/cli/validate.rst.txt new file mode 100644 index 00000000..05a5e701 --- /dev/null +++ b/docs/_sources/cli/validate.rst.txt @@ -0,0 +1,6 @@ +validate +======== + +.. click:: honeybee.cli.validate:validate + :prog: honeybee validate + :show-nested: diff --git a/docs/_sources/honeybee.altnumber.rst.txt b/docs/_sources/honeybee.altnumber.rst.txt new file mode 100644 index 00000000..6eb0819b --- /dev/null +++ b/docs/_sources/honeybee.altnumber.rst.txt @@ -0,0 +1,7 @@ +honeybee.altnumber module +========================= + +.. automodule:: honeybee.altnumber + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.aperture.rst.txt b/docs/_sources/honeybee.aperture.rst.txt new file mode 100644 index 00000000..72d88f3d --- /dev/null +++ b/docs/_sources/honeybee.aperture.rst.txt @@ -0,0 +1,7 @@ +honeybee.aperture module +======================== + +.. automodule:: honeybee.aperture + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.boundarycondition.rst.txt b/docs/_sources/honeybee.boundarycondition.rst.txt new file mode 100644 index 00000000..c2801234 --- /dev/null +++ b/docs/_sources/honeybee.boundarycondition.rst.txt @@ -0,0 +1,7 @@ +honeybee.boundarycondition module +================================= + +.. automodule:: honeybee.boundarycondition + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.checkdup.rst.txt b/docs/_sources/honeybee.checkdup.rst.txt new file mode 100644 index 00000000..a2dcbb75 --- /dev/null +++ b/docs/_sources/honeybee.checkdup.rst.txt @@ -0,0 +1,7 @@ +honeybee.checkdup module +======================== + +.. automodule:: honeybee.checkdup + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.cli.compare.rst.txt b/docs/_sources/honeybee.cli.compare.rst.txt new file mode 100644 index 00000000..98f89305 --- /dev/null +++ b/docs/_sources/honeybee.cli.compare.rst.txt @@ -0,0 +1,7 @@ +honeybee.cli.compare module +=========================== + +.. automodule:: honeybee.cli.compare + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.cli.create.rst.txt b/docs/_sources/honeybee.cli.create.rst.txt new file mode 100644 index 00000000..1a6e3df7 --- /dev/null +++ b/docs/_sources/honeybee.cli.create.rst.txt @@ -0,0 +1,7 @@ +honeybee.cli.create module +========================== + +.. automodule:: honeybee.cli.create + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.cli.edit.rst.txt b/docs/_sources/honeybee.cli.edit.rst.txt new file mode 100644 index 00000000..697b1c68 --- /dev/null +++ b/docs/_sources/honeybee.cli.edit.rst.txt @@ -0,0 +1,7 @@ +honeybee.cli.edit module +======================== + +.. automodule:: honeybee.cli.edit + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.cli.lib.rst.txt b/docs/_sources/honeybee.cli.lib.rst.txt new file mode 100644 index 00000000..c96be7f2 --- /dev/null +++ b/docs/_sources/honeybee.cli.lib.rst.txt @@ -0,0 +1,7 @@ +honeybee.cli.lib module +======================= + +.. automodule:: honeybee.cli.lib + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.cli.rst.txt b/docs/_sources/honeybee.cli.rst.txt new file mode 100644 index 00000000..e0dc2233 --- /dev/null +++ b/docs/_sources/honeybee.cli.rst.txt @@ -0,0 +1,23 @@ +honeybee.cli package +==================== + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee.cli.compare + honeybee.cli.create + honeybee.cli.edit + honeybee.cli.lib + honeybee.cli.setconfig + honeybee.cli.validate + +Module contents +--------------- + +.. automodule:: honeybee.cli + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.cli.setconfig.rst.txt b/docs/_sources/honeybee.cli.setconfig.rst.txt new file mode 100644 index 00000000..bcecb98c --- /dev/null +++ b/docs/_sources/honeybee.cli.setconfig.rst.txt @@ -0,0 +1,7 @@ +honeybee.cli.setconfig module +============================= + +.. automodule:: honeybee.cli.setconfig + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.cli.validate.rst.txt b/docs/_sources/honeybee.cli.validate.rst.txt new file mode 100644 index 00000000..4d366837 --- /dev/null +++ b/docs/_sources/honeybee.cli.validate.rst.txt @@ -0,0 +1,7 @@ +honeybee.cli.validate module +============================ + +.. automodule:: honeybee.cli.validate + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.colorobj.rst.txt b/docs/_sources/honeybee.colorobj.rst.txt new file mode 100644 index 00000000..e7bc72e1 --- /dev/null +++ b/docs/_sources/honeybee.colorobj.rst.txt @@ -0,0 +1,7 @@ +honeybee.colorobj module +======================== + +.. automodule:: honeybee.colorobj + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.config.rst.txt b/docs/_sources/honeybee.config.rst.txt new file mode 100644 index 00000000..3655f4fe --- /dev/null +++ b/docs/_sources/honeybee.config.rst.txt @@ -0,0 +1,7 @@ +honeybee.config module +====================== + +.. automodule:: honeybee.config + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.dictutil.rst.txt b/docs/_sources/honeybee.dictutil.rst.txt new file mode 100644 index 00000000..378e8f70 --- /dev/null +++ b/docs/_sources/honeybee.dictutil.rst.txt @@ -0,0 +1,7 @@ +honeybee.dictutil module +======================== + +.. automodule:: honeybee.dictutil + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.door.rst.txt b/docs/_sources/honeybee.door.rst.txt new file mode 100644 index 00000000..a40420b7 --- /dev/null +++ b/docs/_sources/honeybee.door.rst.txt @@ -0,0 +1,7 @@ +honeybee.door module +==================== + +.. automodule:: honeybee.door + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.extensionutil.rst.txt b/docs/_sources/honeybee.extensionutil.rst.txt new file mode 100644 index 00000000..5e667967 --- /dev/null +++ b/docs/_sources/honeybee.extensionutil.rst.txt @@ -0,0 +1,7 @@ +honeybee.extensionutil module +============================= + +.. automodule:: honeybee.extensionutil + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.face.rst.txt b/docs/_sources/honeybee.face.rst.txt new file mode 100644 index 00000000..60b575c1 --- /dev/null +++ b/docs/_sources/honeybee.face.rst.txt @@ -0,0 +1,7 @@ +honeybee.face module +==================== + +.. automodule:: honeybee.face + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.facetype.rst.txt b/docs/_sources/honeybee.facetype.rst.txt new file mode 100644 index 00000000..8ba4400a --- /dev/null +++ b/docs/_sources/honeybee.facetype.rst.txt @@ -0,0 +1,7 @@ +honeybee.facetype module +======================== + +.. automodule:: honeybee.facetype + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.logutil.rst.txt b/docs/_sources/honeybee.logutil.rst.txt new file mode 100644 index 00000000..da74223a --- /dev/null +++ b/docs/_sources/honeybee.logutil.rst.txt @@ -0,0 +1,7 @@ +honeybee.logutil module +======================= + +.. automodule:: honeybee.logutil + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.model.rst.txt b/docs/_sources/honeybee.model.rst.txt new file mode 100644 index 00000000..181a4721 --- /dev/null +++ b/docs/_sources/honeybee.model.rst.txt @@ -0,0 +1,7 @@ +honeybee.model module +===================== + +.. automodule:: honeybee.model + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.orientation.rst.txt b/docs/_sources/honeybee.orientation.rst.txt new file mode 100644 index 00000000..c56148c0 --- /dev/null +++ b/docs/_sources/honeybee.orientation.rst.txt @@ -0,0 +1,7 @@ +honeybee.orientation module +=========================== + +.. automodule:: honeybee.orientation + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.properties.rst.txt b/docs/_sources/honeybee.properties.rst.txt new file mode 100644 index 00000000..b5124d91 --- /dev/null +++ b/docs/_sources/honeybee.properties.rst.txt @@ -0,0 +1,7 @@ +honeybee.properties module +========================== + +.. automodule:: honeybee.properties + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.room.rst.txt b/docs/_sources/honeybee.room.rst.txt new file mode 100644 index 00000000..3ba67b21 --- /dev/null +++ b/docs/_sources/honeybee.room.rst.txt @@ -0,0 +1,7 @@ +honeybee.room module +==================== + +.. automodule:: honeybee.room + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.rst.txt b/docs/_sources/honeybee.rst.txt new file mode 100644 index 00000000..cb5ff286 --- /dev/null +++ b/docs/_sources/honeybee.rst.txt @@ -0,0 +1,47 @@ +honeybee package +================ + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + honeybee.cli + honeybee.writer + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee.altnumber + honeybee.aperture + honeybee.boundarycondition + honeybee.checkdup + honeybee.colorobj + honeybee.config + honeybee.dictutil + honeybee.door + honeybee.extensionutil + honeybee.face + honeybee.facetype + honeybee.logutil + honeybee.model + honeybee.orientation + honeybee.properties + honeybee.room + honeybee.search + honeybee.shade + honeybee.shademesh + honeybee.typing + honeybee.units + +Module contents +--------------- + +.. automodule:: honeybee + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.search.rst.txt b/docs/_sources/honeybee.search.rst.txt new file mode 100644 index 00000000..d293d647 --- /dev/null +++ b/docs/_sources/honeybee.search.rst.txt @@ -0,0 +1,7 @@ +honeybee.search module +====================== + +.. automodule:: honeybee.search + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.shade.rst.txt b/docs/_sources/honeybee.shade.rst.txt new file mode 100644 index 00000000..b973ba61 --- /dev/null +++ b/docs/_sources/honeybee.shade.rst.txt @@ -0,0 +1,7 @@ +honeybee.shade module +===================== + +.. automodule:: honeybee.shade + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.shademesh.rst.txt b/docs/_sources/honeybee.shademesh.rst.txt new file mode 100644 index 00000000..4405624b --- /dev/null +++ b/docs/_sources/honeybee.shademesh.rst.txt @@ -0,0 +1,7 @@ +honeybee.shademesh module +========================= + +.. automodule:: honeybee.shademesh + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.typing.rst.txt b/docs/_sources/honeybee.typing.rst.txt new file mode 100644 index 00000000..fdcfafd1 --- /dev/null +++ b/docs/_sources/honeybee.typing.rst.txt @@ -0,0 +1,7 @@ +honeybee.typing module +====================== + +.. automodule:: honeybee.typing + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.units.rst.txt b/docs/_sources/honeybee.units.rst.txt new file mode 100644 index 00000000..b01c11f4 --- /dev/null +++ b/docs/_sources/honeybee.units.rst.txt @@ -0,0 +1,7 @@ +honeybee.units module +===================== + +.. automodule:: honeybee.units + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.writer.aperture.rst.txt b/docs/_sources/honeybee.writer.aperture.rst.txt new file mode 100644 index 00000000..75ccaa31 --- /dev/null +++ b/docs/_sources/honeybee.writer.aperture.rst.txt @@ -0,0 +1,7 @@ +honeybee.writer.aperture module +=============================== + +.. automodule:: honeybee.writer.aperture + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.writer.door.rst.txt b/docs/_sources/honeybee.writer.door.rst.txt new file mode 100644 index 00000000..c859008f --- /dev/null +++ b/docs/_sources/honeybee.writer.door.rst.txt @@ -0,0 +1,7 @@ +honeybee.writer.door module +=========================== + +.. automodule:: honeybee.writer.door + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.writer.face.rst.txt b/docs/_sources/honeybee.writer.face.rst.txt new file mode 100644 index 00000000..8f2a572f --- /dev/null +++ b/docs/_sources/honeybee.writer.face.rst.txt @@ -0,0 +1,7 @@ +honeybee.writer.face module +=========================== + +.. automodule:: honeybee.writer.face + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.writer.model.rst.txt b/docs/_sources/honeybee.writer.model.rst.txt new file mode 100644 index 00000000..d39a00ff --- /dev/null +++ b/docs/_sources/honeybee.writer.model.rst.txt @@ -0,0 +1,7 @@ +honeybee.writer.model module +============================ + +.. automodule:: honeybee.writer.model + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.writer.room.rst.txt b/docs/_sources/honeybee.writer.room.rst.txt new file mode 100644 index 00000000..d46e1c9d --- /dev/null +++ b/docs/_sources/honeybee.writer.room.rst.txt @@ -0,0 +1,7 @@ +honeybee.writer.room module +=========================== + +.. automodule:: honeybee.writer.room + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.writer.rst.txt b/docs/_sources/honeybee.writer.rst.txt new file mode 100644 index 00000000..6bb09d43 --- /dev/null +++ b/docs/_sources/honeybee.writer.rst.txt @@ -0,0 +1,24 @@ +honeybee.writer package +======================= + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + honeybee.writer.aperture + honeybee.writer.door + honeybee.writer.face + honeybee.writer.model + honeybee.writer.room + honeybee.writer.shade + honeybee.writer.shademesh + +Module contents +--------------- + +.. automodule:: honeybee.writer + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.writer.shade.rst.txt b/docs/_sources/honeybee.writer.shade.rst.txt new file mode 100644 index 00000000..7c54f0e3 --- /dev/null +++ b/docs/_sources/honeybee.writer.shade.rst.txt @@ -0,0 +1,7 @@ +honeybee.writer.shade module +============================ + +.. automodule:: honeybee.writer.shade + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/honeybee.writer.shademesh.rst.txt b/docs/_sources/honeybee.writer.shademesh.rst.txt new file mode 100644 index 00000000..a146bd89 --- /dev/null +++ b/docs/_sources/honeybee.writer.shademesh.rst.txt @@ -0,0 +1,7 @@ +honeybee.writer.shademesh module +================================ + +.. automodule:: honeybee.writer.shademesh + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/index.rst.txt b/docs/_sources/index.rst.txt new file mode 100644 index 00000000..9d73970e --- /dev/null +++ b/docs/_sources/index.rst.txt @@ -0,0 +1,62 @@ + +Welcome to Honeybee's documentation! +========================================= + +.. image:: http://www.ladybug.tools/assets/img/honeybee.png + +Honeybee is a collection of Python libraries to create representations of buildings +following `honeybee-schema `_. + +This package is the core library that provides honeybee's common functionalities. +To extend these functionalities you should install available Honeybee extensions or write +your own. + +Installation +============ + +To install the core library try ``pip install -U honeybee-core``. + +To check if the Honeybee command line interface is installed correctly try ``honeybee viz`` and you +should get a ``viiiiiiiiiiiiizzzzzzzzz!`` back in response! + + +Documentation +============= + +This document includes `Honeybee API documentation <#honeybee>`_ and +`Honeybee Command Line Interface <#cli-docs>`_ documentation for ``honeybee core`` and does +not include the documentation for honeybee extensions. For each extension refer to +extension's documentation page. + +Here are a number of Honeybee popular extensions: + +- `honeybee-energy `_ +- `honeybee-radiance `_ + + +CLI Docs +============= + +For command line interface documentation and API documentation see the pages below. + + +.. toctree:: + :maxdepth: 2 + + cli/index + + +honeybee +============= + +.. toctree:: + :maxdepth: 4 + + modules + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/_sources/modules.rst.txt b/docs/_sources/modules.rst.txt new file mode 100644 index 00000000..b1e490b0 --- /dev/null +++ b/docs/_sources/modules.rst.txt @@ -0,0 +1,7 @@ +honeybee +======== + +.. toctree:: + :maxdepth: 4 + + honeybee diff --git a/docs/_static/basic.css b/docs/_static/basic.css new file mode 100644 index 00000000..f316efcb --- /dev/null +++ b/docs/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.css b/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.css new file mode 100644 index 00000000..09e88ce3 --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.css @@ -0,0 +1,1109 @@ +/*! + * Bootstrap Responsive v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +@-ms-viewport { + width: device-width; +} + +.hidden { + display: none; + visibility: hidden; +} + +.visible-phone { + display: none !important; +} + +.visible-tablet { + display: none !important; +} + +.hidden-desktop { + display: none !important; +} + +.visible-desktop { + display: inherit !important; +} + +@media (min-width: 768px) and (max-width: 979px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important ; + } + .visible-tablet { + display: inherit !important; + } + .hidden-tablet { + display: none !important; + } +} + +@media (max-width: 767px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important; + } + .visible-phone { + display: inherit !important; + } + .hidden-phone { + display: none !important; + } +} + +.visible-print { + display: none !important; +} + +@media print { + .visible-print { + display: inherit !important; + } + .hidden-print { + display: none !important; + } +} + +@media (min-width: 1200px) { + .row { + margin-left: -30px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 30px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 1170px; + } + .span12 { + width: 1170px; + } + .span11 { + width: 1070px; + } + .span10 { + width: 970px; + } + .span9 { + width: 870px; + } + .span8 { + width: 770px; + } + .span7 { + width: 670px; + } + .span6 { + width: 570px; + } + .span5 { + width: 470px; + } + .span4 { + width: 370px; + } + .span3 { + width: 270px; + } + .span2 { + width: 170px; + } + .span1 { + width: 70px; + } + .offset12 { + margin-left: 1230px; + } + .offset11 { + margin-left: 1130px; + } + .offset10 { + margin-left: 1030px; + } + .offset9 { + margin-left: 930px; + } + .offset8 { + margin-left: 830px; + } + .offset7 { + margin-left: 730px; + } + .offset6 { + margin-left: 630px; + } + .offset5 { + margin-left: 530px; + } + .offset4 { + margin-left: 430px; + } + .offset3 { + margin-left: 330px; + } + .offset2 { + margin-left: 230px; + } + .offset1 { + margin-left: 130px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.564102564102564%; + *margin-left: 2.5109110747408616%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.564102564102564%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.45299145299145%; + *width: 91.39979996362975%; + } + .row-fluid .span10 { + width: 82.90598290598291%; + *width: 82.8527914166212%; + } + .row-fluid .span9 { + width: 74.35897435897436%; + *width: 74.30578286961266%; + } + .row-fluid .span8 { + width: 65.81196581196582%; + *width: 65.75877432260411%; + } + .row-fluid .span7 { + width: 57.26495726495726%; + *width: 57.21176577559556%; + } + .row-fluid .span6 { + width: 48.717948717948715%; + *width: 48.664757228587014%; + } + .row-fluid .span5 { + width: 40.17094017094017%; + *width: 40.11774868157847%; + } + .row-fluid .span4 { + width: 31.623931623931625%; + *width: 31.570740134569924%; + } + .row-fluid .span3 { + width: 23.076923076923077%; + *width: 23.023731587561375%; + } + .row-fluid .span2 { + width: 14.52991452991453%; + *width: 14.476723040552828%; + } + .row-fluid .span1 { + width: 5.982905982905983%; + *width: 5.929714493544281%; + } + .row-fluid .offset12 { + margin-left: 105.12820512820512%; + *margin-left: 105.02182214948171%; + } + .row-fluid .offset12:first-child { + margin-left: 102.56410256410257%; + *margin-left: 102.45771958537915%; + } + .row-fluid .offset11 { + margin-left: 96.58119658119658%; + *margin-left: 96.47481360247316%; + } + .row-fluid .offset11:first-child { + margin-left: 94.01709401709402%; + *margin-left: 93.91071103837061%; + } + .row-fluid .offset10 { + margin-left: 88.03418803418803%; + *margin-left: 87.92780505546462%; + } + .row-fluid .offset10:first-child { + margin-left: 85.47008547008548%; + *margin-left: 85.36370249136206%; + } + .row-fluid .offset9 { + margin-left: 79.48717948717949%; + *margin-left: 79.38079650845607%; + } + .row-fluid .offset9:first-child { + margin-left: 76.92307692307693%; + *margin-left: 76.81669394435352%; + } + .row-fluid .offset8 { + margin-left: 70.94017094017094%; + *margin-left: 70.83378796144753%; + } + .row-fluid .offset8:first-child { + margin-left: 68.37606837606839%; + *margin-left: 68.26968539734497%; + } + .row-fluid .offset7 { + margin-left: 62.393162393162385%; + *margin-left: 62.28677941443899%; + } + .row-fluid .offset7:first-child { + margin-left: 59.82905982905982%; + *margin-left: 59.72267685033642%; + } + .row-fluid .offset6 { + margin-left: 53.84615384615384%; + *margin-left: 53.739770867430444%; + } + .row-fluid .offset6:first-child { + margin-left: 51.28205128205128%; + *margin-left: 51.175668303327875%; + } + .row-fluid .offset5 { + margin-left: 45.299145299145295%; + *margin-left: 45.1927623204219%; + } + .row-fluid .offset5:first-child { + margin-left: 42.73504273504273%; + *margin-left: 42.62865975631933%; + } + .row-fluid .offset4 { + margin-left: 36.75213675213675%; + *margin-left: 36.645753773413354%; + } + .row-fluid .offset4:first-child { + margin-left: 34.18803418803419%; + *margin-left: 34.081651209310785%; + } + .row-fluid .offset3 { + margin-left: 28.205128205128204%; + *margin-left: 28.0987452264048%; + } + .row-fluid .offset3:first-child { + margin-left: 25.641025641025642%; + *margin-left: 25.53464266230224%; + } + .row-fluid .offset2 { + margin-left: 19.65811965811966%; + *margin-left: 19.551736679396257%; + } + .row-fluid .offset2:first-child { + margin-left: 17.094017094017094%; + *margin-left: 16.98763411529369%; + } + .row-fluid .offset1 { + margin-left: 11.11111111111111%; + *margin-left: 11.004728132387708%; + } + .row-fluid .offset1:first-child { + margin-left: 8.547008547008547%; + *margin-left: 8.440625568285142%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 30px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 1156px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 1056px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 956px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 856px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 756px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 656px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 556px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 456px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 356px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 256px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 156px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 56px; + } + .thumbnails { + margin-left: -30px; + } + .thumbnails > li { + margin-left: 30px; + } + .row-fluid .thumbnails { + margin-left: 0; + } +} + +@media (min-width: 768px) and (max-width: 979px) { + .row { + margin-left: -20px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 724px; + } + .span12 { + width: 724px; + } + .span11 { + width: 662px; + } + .span10 { + width: 600px; + } + .span9 { + width: 538px; + } + .span8 { + width: 476px; + } + .span7 { + width: 414px; + } + .span6 { + width: 352px; + } + .span5 { + width: 290px; + } + .span4 { + width: 228px; + } + .span3 { + width: 166px; + } + .span2 { + width: 104px; + } + .span1 { + width: 42px; + } + .offset12 { + margin-left: 764px; + } + .offset11 { + margin-left: 702px; + } + .offset10 { + margin-left: 640px; + } + .offset9 { + margin-left: 578px; + } + .offset8 { + margin-left: 516px; + } + .offset7 { + margin-left: 454px; + } + .offset6 { + margin-left: 392px; + } + .offset5 { + margin-left: 330px; + } + .offset4 { + margin-left: 268px; + } + .offset3 { + margin-left: 206px; + } + .offset2 { + margin-left: 144px; + } + .offset1 { + margin-left: 82px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.7624309392265194%; + *margin-left: 2.709239449864817%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.7624309392265194%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.43646408839778%; + *width: 91.38327259903608%; + } + .row-fluid .span10 { + width: 82.87292817679558%; + *width: 82.81973668743387%; + } + .row-fluid .span9 { + width: 74.30939226519337%; + *width: 74.25620077583166%; + } + .row-fluid .span8 { + width: 65.74585635359117%; + *width: 65.69266486422946%; + } + .row-fluid .span7 { + width: 57.18232044198895%; + *width: 57.12912895262725%; + } + .row-fluid .span6 { + width: 48.61878453038674%; + *width: 48.56559304102504%; + } + .row-fluid .span5 { + width: 40.05524861878453%; + *width: 40.00205712942283%; + } + .row-fluid .span4 { + width: 31.491712707182323%; + *width: 31.43852121782062%; + } + .row-fluid .span3 { + width: 22.92817679558011%; + *width: 22.87498530621841%; + } + .row-fluid .span2 { + width: 14.3646408839779%; + *width: 14.311449394616199%; + } + .row-fluid .span1 { + width: 5.801104972375691%; + *width: 5.747913483013988%; + } + .row-fluid .offset12 { + margin-left: 105.52486187845304%; + *margin-left: 105.41847889972962%; + } + .row-fluid .offset12:first-child { + margin-left: 102.76243093922652%; + *margin-left: 102.6560479605031%; + } + .row-fluid .offset11 { + margin-left: 96.96132596685082%; + *margin-left: 96.8549429881274%; + } + .row-fluid .offset11:first-child { + margin-left: 94.1988950276243%; + *margin-left: 94.09251204890089%; + } + .row-fluid .offset10 { + margin-left: 88.39779005524862%; + *margin-left: 88.2914070765252%; + } + .row-fluid .offset10:first-child { + margin-left: 85.6353591160221%; + *margin-left: 85.52897613729868%; + } + .row-fluid .offset9 { + margin-left: 79.8342541436464%; + *margin-left: 79.72787116492299%; + } + .row-fluid .offset9:first-child { + margin-left: 77.07182320441989%; + *margin-left: 76.96544022569647%; + } + .row-fluid .offset8 { + margin-left: 71.2707182320442%; + *margin-left: 71.16433525332079%; + } + .row-fluid .offset8:first-child { + margin-left: 68.50828729281768%; + *margin-left: 68.40190431409427%; + } + .row-fluid .offset7 { + margin-left: 62.70718232044199%; + *margin-left: 62.600799341718584%; + } + .row-fluid .offset7:first-child { + margin-left: 59.94475138121547%; + *margin-left: 59.838368402492065%; + } + .row-fluid .offset6 { + margin-left: 54.14364640883978%; + *margin-left: 54.037263430116376%; + } + .row-fluid .offset6:first-child { + margin-left: 51.38121546961326%; + *margin-left: 51.27483249088986%; + } + .row-fluid .offset5 { + margin-left: 45.58011049723757%; + *margin-left: 45.47372751851417%; + } + .row-fluid .offset5:first-child { + margin-left: 42.81767955801105%; + *margin-left: 42.71129657928765%; + } + .row-fluid .offset4 { + margin-left: 37.01657458563536%; + *margin-left: 36.91019160691196%; + } + .row-fluid .offset4:first-child { + margin-left: 34.25414364640884%; + *margin-left: 34.14776066768544%; + } + .row-fluid .offset3 { + margin-left: 28.45303867403315%; + *margin-left: 28.346655695309746%; + } + .row-fluid .offset3:first-child { + margin-left: 25.69060773480663%; + *margin-left: 25.584224756083227%; + } + .row-fluid .offset2 { + margin-left: 19.88950276243094%; + *margin-left: 19.783119783707537%; + } + .row-fluid .offset2:first-child { + margin-left: 17.12707182320442%; + *margin-left: 17.02068884448102%; + } + .row-fluid .offset1 { + margin-left: 11.32596685082873%; + *margin-left: 11.219583872105325%; + } + .row-fluid .offset1:first-child { + margin-left: 8.56353591160221%; + *margin-left: 8.457152932878806%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 710px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 648px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 586px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 524px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 462px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 400px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 338px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 276px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 214px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 152px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 90px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 28px; + } +} + +@media (max-width: 767px) { + body { + padding-right: 20px; + padding-left: 20px; + } + .navbar-fixed-top, + .navbar-fixed-bottom, + .navbar-static-top { + margin-right: -20px; + margin-left: -20px; + } + .container-fluid { + padding: 0; + } + .dl-horizontal dt { + float: none; + width: auto; + clear: none; + text-align: left; + } + .dl-horizontal dd { + margin-left: 0; + } + .container { + width: auto; + } + .row-fluid { + width: 100%; + } + .row, + .thumbnails { + margin-left: 0; + } + .thumbnails > li { + float: none; + margin-left: 0; + } + [class*="span"], + .uneditable-input[class*="span"], + .row-fluid [class*="span"] { + display: block; + float: none; + width: 100%; + margin-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .span12, + .row-fluid .span12 { + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="offset"]:first-child { + margin-left: 0; + } + .input-large, + .input-xlarge, + .input-xxlarge, + input[class*="span"], + select[class*="span"], + textarea[class*="span"], + .uneditable-input { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .input-prepend input, + .input-append input, + .input-prepend input[class*="span"], + .input-append input[class*="span"] { + display: inline-block; + width: auto; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 0; + } + .modal { + position: fixed; + top: 20px; + right: 20px; + left: 20px; + width: auto; + margin: 0; + } + .modal.fade { + top: -100px; + } + .modal.fade.in { + top: 20px; + } +} + +@media (max-width: 480px) { + .nav-collapse { + -webkit-transform: translate3d(0, 0, 0); + } + .page-header h1 small { + display: block; + line-height: 20px; + } + input[type="checkbox"], + input[type="radio"] { + border: 1px solid #ccc; + } + .form-horizontal .control-label { + float: none; + width: auto; + padding-top: 0; + text-align: left; + } + .form-horizontal .controls { + margin-left: 0; + } + .form-horizontal .control-list { + padding-top: 0; + } + .form-horizontal .form-actions { + padding-right: 10px; + padding-left: 10px; + } + .media .pull-left, + .media .pull-right { + display: block; + float: none; + margin-bottom: 10px; + } + .media-object { + margin-right: 0; + margin-left: 0; + } + .modal { + top: 10px; + right: 10px; + left: 10px; + } + .modal-header .close { + padding: 10px; + margin: -10px; + } + .carousel-caption { + position: static; + } +} + +@media (max-width: 979px) { + body { + padding-top: 0; + } + .navbar-fixed-top, + .navbar-fixed-bottom { + position: static; + } + .navbar-fixed-top { + margin-bottom: 20px; + } + .navbar-fixed-bottom { + margin-top: 20px; + } + .navbar-fixed-top .navbar-inner, + .navbar-fixed-bottom .navbar-inner { + padding: 5px; + } + .navbar .container { + width: auto; + padding: 0; + } + .navbar .brand { + padding-right: 10px; + padding-left: 10px; + margin: 0 0 0 -5px; + } + .nav-collapse { + clear: both; + } + .nav-collapse .nav { + float: none; + margin: 0 0 10px; + } + .nav-collapse .nav > li { + float: none; + } + .nav-collapse .nav > li > a { + margin-bottom: 2px; + } + .nav-collapse .nav > .divider-vertical { + display: none; + } + .nav-collapse .nav .nav-header { + color: #777777; + text-shadow: none; + } + .nav-collapse .nav > li > a, + .nav-collapse .dropdown-menu a { + padding: 9px 15px; + font-weight: bold; + color: #777777; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + } + .nav-collapse .btn { + padding: 4px 10px 4px; + font-weight: normal; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + } + .nav-collapse .dropdown-menu li + li a { + margin-bottom: 2px; + } + .nav-collapse .nav > li > a:hover, + .nav-collapse .nav > li > a:focus, + .nav-collapse .dropdown-menu a:hover, + .nav-collapse .dropdown-menu a:focus { + background-color: #f2f2f2; + } + .navbar-inverse .nav-collapse .nav > li > a, + .navbar-inverse .nav-collapse .dropdown-menu a { + color: #999999; + } + .navbar-inverse .nav-collapse .nav > li > a:hover, + .navbar-inverse .nav-collapse .nav > li > a:focus, + .navbar-inverse .nav-collapse .dropdown-menu a:hover, + .navbar-inverse .nav-collapse .dropdown-menu a:focus { + background-color: #111111; + } + .nav-collapse.in .btn-group { + padding: 0; + margin-top: 5px; + } + .nav-collapse .dropdown-menu { + position: static; + top: auto; + left: auto; + display: none; + float: none; + max-width: none; + padding: 0; + margin: 0 15px; + background-color: transparent; + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + .nav-collapse .open > .dropdown-menu { + display: block; + } + .nav-collapse .dropdown-menu:before, + .nav-collapse .dropdown-menu:after { + display: none; + } + .nav-collapse .dropdown-menu .divider { + display: none; + } + .nav-collapse .nav > li > .dropdown-menu:before, + .nav-collapse .nav > li > .dropdown-menu:after { + display: none; + } + .nav-collapse .navbar-form, + .nav-collapse .navbar-search { + float: none; + padding: 10px 15px; + margin: 10px 0; + border-top: 1px solid #f2f2f2; + border-bottom: 1px solid #f2f2f2; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + } + .navbar-inverse .nav-collapse .navbar-form, + .navbar-inverse .nav-collapse .navbar-search { + border-top-color: #111111; + border-bottom-color: #111111; + } + .navbar .nav-collapse .nav.pull-right { + float: none; + margin-left: 0; + } + .nav-collapse, + .nav-collapse.collapse { + height: 0; + overflow: hidden; + } + .navbar .btn-navbar { + display: block; + } + .navbar-static .navbar-inner { + padding-right: 10px; + padding-left: 10px; + } +} + +@media (min-width: 980px) { + .nav-collapse.collapse { + height: auto !important; + overflow: visible !important; + } +} diff --git a/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.min.css b/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.min.css new file mode 100644 index 00000000..f4ede63f --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/css/bootstrap-responsive.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap Responsive v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} diff --git a/docs/_static/bootstrap-2.3.2/css/bootstrap.css b/docs/_static/bootstrap-2.3.2/css/bootstrap.css new file mode 100644 index 00000000..b725064a --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/css/bootstrap.css @@ -0,0 +1,6167 @@ +/*! + * Bootstrap v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +a:hover, +a:active { + outline: 0; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + width: auto\9; + height: auto; + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} + +#map_canvas img, +.google-maps img { + max-width: none; +} + +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} + +button, +input { + *overflow: visible; + line-height: normal; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} + +label, +select, +button, +input[type="button"], +input[type="reset"], +input[type="submit"], +input[type="radio"], +input[type="checkbox"] { + cursor: pointer; +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + @page { + margin: 0.5cm; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333333; + background-color: #ffffff; +} + +a { + color: #0088cc; + text-decoration: none; +} + +a:hover, +a:focus { + color: #005580; + text-decoration: underline; +} + +.img-rounded { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.img-polaroid { + padding: 4px; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.img-circle { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px; +} + +.row { + margin-left: -20px; + *zoom: 1; +} + +.row:before, +.row:after { + display: table; + line-height: 0; + content: ""; +} + +.row:after { + clear: both; +} + +[class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; +} + +.container, +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.span12 { + width: 940px; +} + +.span11 { + width: 860px; +} + +.span10 { + width: 780px; +} + +.span9 { + width: 700px; +} + +.span8 { + width: 620px; +} + +.span7 { + width: 540px; +} + +.span6 { + width: 460px; +} + +.span5 { + width: 380px; +} + +.span4 { + width: 300px; +} + +.span3 { + width: 220px; +} + +.span2 { + width: 140px; +} + +.span1 { + width: 60px; +} + +.offset12 { + margin-left: 980px; +} + +.offset11 { + margin-left: 900px; +} + +.offset10 { + margin-left: 820px; +} + +.offset9 { + margin-left: 740px; +} + +.offset8 { + margin-left: 660px; +} + +.offset7 { + margin-left: 580px; +} + +.offset6 { + margin-left: 500px; +} + +.offset5 { + margin-left: 420px; +} + +.offset4 { + margin-left: 340px; +} + +.offset3 { + margin-left: 260px; +} + +.offset2 { + margin-left: 180px; +} + +.offset1 { + margin-left: 100px; +} + +.row-fluid { + width: 100%; + *zoom: 1; +} + +.row-fluid:before, +.row-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.row-fluid:after { + clear: both; +} + +.row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.127659574468085%; + *margin-left: 2.074468085106383%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.row-fluid [class*="span"]:first-child { + margin-left: 0; +} + +.row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.127659574468085%; +} + +.row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; +} + +.row-fluid .span11 { + width: 91.48936170212765%; + *width: 91.43617021276594%; +} + +.row-fluid .span10 { + width: 82.97872340425532%; + *width: 82.92553191489361%; +} + +.row-fluid .span9 { + width: 74.46808510638297%; + *width: 74.41489361702126%; +} + +.row-fluid .span8 { + width: 65.95744680851064%; + *width: 65.90425531914893%; +} + +.row-fluid .span7 { + width: 57.44680851063829%; + *width: 57.39361702127659%; +} + +.row-fluid .span6 { + width: 48.93617021276595%; + *width: 48.88297872340425%; +} + +.row-fluid .span5 { + width: 40.42553191489362%; + *width: 40.37234042553192%; +} + +.row-fluid .span4 { + width: 31.914893617021278%; + *width: 31.861702127659576%; +} + +.row-fluid .span3 { + width: 23.404255319148934%; + *width: 23.351063829787233%; +} + +.row-fluid .span2 { + width: 14.893617021276595%; + *width: 14.840425531914894%; +} + +.row-fluid .span1 { + width: 6.382978723404255%; + *width: 6.329787234042553%; +} + +.row-fluid .offset12 { + margin-left: 104.25531914893617%; + *margin-left: 104.14893617021275%; +} + +.row-fluid .offset12:first-child { + margin-left: 102.12765957446808%; + *margin-left: 102.02127659574467%; +} + +.row-fluid .offset11 { + margin-left: 95.74468085106382%; + *margin-left: 95.6382978723404%; +} + +.row-fluid .offset11:first-child { + margin-left: 93.61702127659574%; + *margin-left: 93.51063829787232%; +} + +.row-fluid .offset10 { + margin-left: 87.23404255319149%; + *margin-left: 87.12765957446807%; +} + +.row-fluid .offset10:first-child { + margin-left: 85.1063829787234%; + *margin-left: 84.99999999999999%; +} + +.row-fluid .offset9 { + margin-left: 78.72340425531914%; + *margin-left: 78.61702127659572%; +} + +.row-fluid .offset9:first-child { + margin-left: 76.59574468085106%; + *margin-left: 76.48936170212764%; +} + +.row-fluid .offset8 { + margin-left: 70.2127659574468%; + *margin-left: 70.10638297872339%; +} + +.row-fluid .offset8:first-child { + margin-left: 68.08510638297872%; + *margin-left: 67.9787234042553%; +} + +.row-fluid .offset7 { + margin-left: 61.70212765957446%; + *margin-left: 61.59574468085106%; +} + +.row-fluid .offset7:first-child { + margin-left: 59.574468085106375%; + *margin-left: 59.46808510638297%; +} + +.row-fluid .offset6 { + margin-left: 53.191489361702125%; + *margin-left: 53.085106382978715%; +} + +.row-fluid .offset6:first-child { + margin-left: 51.063829787234035%; + *margin-left: 50.95744680851063%; +} + +.row-fluid .offset5 { + margin-left: 44.68085106382979%; + *margin-left: 44.57446808510638%; +} + +.row-fluid .offset5:first-child { + margin-left: 42.5531914893617%; + *margin-left: 42.4468085106383%; +} + +.row-fluid .offset4 { + margin-left: 36.170212765957444%; + *margin-left: 36.06382978723405%; +} + +.row-fluid .offset4:first-child { + margin-left: 34.04255319148936%; + *margin-left: 33.93617021276596%; +} + +.row-fluid .offset3 { + margin-left: 27.659574468085104%; + *margin-left: 27.5531914893617%; +} + +.row-fluid .offset3:first-child { + margin-left: 25.53191489361702%; + *margin-left: 25.425531914893618%; +} + +.row-fluid .offset2 { + margin-left: 19.148936170212764%; + *margin-left: 19.04255319148936%; +} + +.row-fluid .offset2:first-child { + margin-left: 17.02127659574468%; + *margin-left: 16.914893617021278%; +} + +.row-fluid .offset1 { + margin-left: 10.638297872340425%; + *margin-left: 10.53191489361702%; +} + +.row-fluid .offset1:first-child { + margin-left: 8.51063829787234%; + *margin-left: 8.404255319148938%; +} + +[class*="span"].hide, +.row-fluid [class*="span"].hide { + display: none; +} + +[class*="span"].pull-right, +.row-fluid [class*="span"].pull-right { + float: right; +} + +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} + +.container:before, +.container:after { + display: table; + line-height: 0; + content: ""; +} + +.container:after { + clear: both; +} + +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1; +} + +.container-fluid:before, +.container-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.container-fluid:after { + clear: both; +} + +p { + margin: 0 0 10px; +} + +.lead { + margin-bottom: 20px; + font-size: 21px; + font-weight: 200; + line-height: 30px; +} + +small { + font-size: 85%; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +cite { + font-style: normal; +} + +.muted { + color: #999999; +} + +a.muted:hover, +a.muted:focus { + color: #808080; +} + +.text-warning { + color: #c09853; +} + +a.text-warning:hover, +a.text-warning:focus { + color: #a47e3c; +} + +.text-error { + color: #b94a48; +} + +a.text-error:hover, +a.text-error:focus { + color: #953b39; +} + +.text-info { + color: #3a87ad; +} + +a.text-info:hover, +a.text-info:focus { + color: #2d6987; +} + +.text-success { + color: #468847; +} + +a.text-success:hover, +a.text-success:focus { + color: #356635; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-center { + text-align: center; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + line-height: 1; + color: #999999; +} + +h1, +h2, +h3 { + line-height: 40px; +} + +h1 { + font-size: 38.5px; +} + +h2 { + font-size: 31.5px; +} + +h3 { + font-size: 24.5px; +} + +h4 { + font-size: 17.5px; +} + +h5 { + font-size: 14px; +} + +h6 { + font-size: 11.9px; +} + +h1 small { + font-size: 24.5px; +} + +h2 small { + font-size: 17.5px; +} + +h3 small { + font-size: 14px; +} + +h4 small { + font-size: 14px; +} + +.page-header { + padding-bottom: 9px; + margin: 20px 0 30px; + border-bottom: 1px solid #eeeeee; +} + +ul, +ol { + padding: 0; + margin: 0 0 10px 25px; +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} + +li { + line-height: 20px; +} + +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none; +} + +ul.inline, +ol.inline { + margin-left: 0; + list-style: none; +} + +ul.inline > li, +ol.inline > li { + display: inline-block; + *display: inline; + padding-right: 5px; + padding-left: 5px; + *zoom: 1; +} + +dl { + margin-bottom: 20px; +} + +dt, +dd { + line-height: 20px; +} + +dt { + font-weight: bold; +} + +dd { + margin-left: 10px; +} + +.dl-horizontal { + *zoom: 1; +} + +.dl-horizontal:before, +.dl-horizontal:after { + display: table; + line-height: 0; + content: ""; +} + +.dl-horizontal:after { + clear: both; +} + +.dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; +} + +.dl-horizontal dd { + margin-left: 180px; +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px solid #eeeeee; + border-bottom: 1px solid #ffffff; +} + +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} + +blockquote p { + margin-bottom: 0; + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} + +blockquote small { + display: block; + line-height: 20px; + color: #999999; +} + +blockquote small:before { + content: '\2014 \00A0'; +} + +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} + +blockquote.pull-right small:before { + content: ''; +} + +blockquote.pull-right small:after { + content: '\00A0 \2014'; +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 20px; +} + +code, +pre { + padding: 0 3px 2px; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +code { + padding: 2px 4px; + color: #d14; + white-space: nowrap; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 20px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +pre.prettyprint { + margin-bottom: 20px; +} + +pre code { + padding: 0; + color: inherit; + white-space: pre; + white-space: pre-wrap; + background-color: transparent; + border: 0; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +form { + margin: 0 0 20px; +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +legend small { + font-size: 15px; + color: #999999; +} + +label, +input, +button, +select, +textarea { + font-size: 14px; + font-weight: normal; + line-height: 20px; +} + +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +label { + display: block; + margin-bottom: 5px; +} + +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 20px; + padding: 4px 6px; + margin-bottom: 10px; + font-size: 14px; + line-height: 20px; + color: #555555; + vertical-align: middle; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +input, +textarea, +.uneditable-input { + width: 206px; +} + +textarea { + height: auto; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + /* IE6-9 */ + + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); +} + +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + *margin-top: 0; + line-height: normal; +} + +input[type="file"], +input[type="image"], +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto; +} + +select, +input[type="file"] { + height: 30px; + /* In IE7, the height of the select element cannot be changed by height, only font-size */ + + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + + line-height: 30px; +} + +select { + width: 220px; + background-color: #ffffff; + border: 1px solid #cccccc; +} + +select[multiple], +select[size] { + height: auto; +} + +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.uneditable-input, +.uneditable-textarea { + color: #999999; + cursor: not-allowed; + background-color: #fcfcfc; + border-color: #cccccc; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap; +} + +.uneditable-textarea { + width: auto; + height: auto; +} + +input:-moz-placeholder, +textarea:-moz-placeholder { + color: #999999; +} + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #999999; +} + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #999999; +} + +.radio, +.checkbox { + min-height: 20px; + padding-left: 20px; +} + +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -20px; +} + +.controls > .radio:first-child, +.controls > .checkbox:first-child { + padding-top: 5px; +} + +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle; +} + +.radio.inline + .radio.inline, +.checkbox.inline + .checkbox.inline { + margin-left: 10px; +} + +.input-mini { + width: 60px; +} + +.input-small { + width: 90px; +} + +.input-medium { + width: 150px; +} + +.input-large { + width: 210px; +} + +.input-xlarge { + width: 270px; +} + +.input-xxlarge { + width: 530px; +} + +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0; +} + +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block; +} + +input, +textarea, +.uneditable-input { + margin-left: 0; +} + +.controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; +} + +input.span12, +textarea.span12, +.uneditable-input.span12 { + width: 926px; +} + +input.span11, +textarea.span11, +.uneditable-input.span11 { + width: 846px; +} + +input.span10, +textarea.span10, +.uneditable-input.span10 { + width: 766px; +} + +input.span9, +textarea.span9, +.uneditable-input.span9 { + width: 686px; +} + +input.span8, +textarea.span8, +.uneditable-input.span8 { + width: 606px; +} + +input.span7, +textarea.span7, +.uneditable-input.span7 { + width: 526px; +} + +input.span6, +textarea.span6, +.uneditable-input.span6 { + width: 446px; +} + +input.span5, +textarea.span5, +.uneditable-input.span5 { + width: 366px; +} + +input.span4, +textarea.span4, +.uneditable-input.span4 { + width: 286px; +} + +input.span3, +textarea.span3, +.uneditable-input.span3 { + width: 206px; +} + +input.span2, +textarea.span2, +.uneditable-input.span2 { + width: 126px; +} + +input.span1, +textarea.span1, +.uneditable-input.span1 { + width: 46px; +} + +.controls-row { + *zoom: 1; +} + +.controls-row:before, +.controls-row:after { + display: table; + line-height: 0; + content: ""; +} + +.controls-row:after { + clear: both; +} + +.controls-row [class*="span"], +.row-fluid .controls-row [class*="span"] { + float: left; +} + +.controls-row .checkbox[class*="span"], +.controls-row .radio[class*="span"] { + padding-top: 5px; +} + +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #eeeeee; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; +} + +.control-group.warning .control-label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #c09853; +} + +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #c09853; +} + +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; +} + +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} + +.control-group.error .control-label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #b94a48; +} + +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #b94a48; +} + +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} + +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} + +.control-group.success .control-label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #468847; +} + +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #468847; +} + +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; +} + +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} + +.control-group.info .control-label, +.control-group.info .help-block, +.control-group.info .help-inline { + color: #3a87ad; +} + +.control-group.info .checkbox, +.control-group.info .radio, +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + color: #3a87ad; +} + +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + border-color: #3a87ad; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.info input:focus, +.control-group.info select:focus, +.control-group.info textarea:focus { + border-color: #2d6987; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; +} + +.control-group.info .input-prepend .add-on, +.control-group.info .input-append .add-on { + color: #3a87ad; + background-color: #d9edf7; + border-color: #3a87ad; +} + +input:focus:invalid, +textarea:focus:invalid, +select:focus:invalid { + color: #b94a48; + border-color: #ee5f5b; +} + +input:focus:invalid:focus, +textarea:focus:invalid:focus, +select:focus:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} + +.form-actions { + padding: 19px 20px 20px; + margin-top: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1; +} + +.form-actions:before, +.form-actions:after { + display: table; + line-height: 0; + content: ""; +} + +.form-actions:after { + clear: both; +} + +.help-block, +.help-inline { + color: #595959; +} + +.help-block { + display: block; + margin-bottom: 10px; +} + +.help-inline { + display: inline-block; + *display: inline; + padding-left: 5px; + vertical-align: middle; + *zoom: 1; +} + +.input-append, +.input-prepend { + display: inline-block; + margin-bottom: 10px; + font-size: 0; + white-space: nowrap; + vertical-align: middle; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input, +.input-append .dropdown-menu, +.input-prepend .dropdown-menu, +.input-append .popover, +.input-prepend .popover { + font-size: 14px; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: top; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append input:focus, +.input-prepend input:focus, +.input-append select:focus, +.input-prepend select:focus, +.input-append .uneditable-input:focus, +.input-prepend .uneditable-input:focus { + z-index: 2; +} + +.input-append .add-on, +.input-prepend .add-on { + display: inline-block; + width: auto; + height: 20px; + min-width: 16px; + padding: 4px 5px; + font-size: 14px; + font-weight: normal; + line-height: 20px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + background-color: #eeeeee; + border: 1px solid #ccc; +} + +.input-append .add-on, +.input-prepend .add-on, +.input-append .btn, +.input-prepend .btn, +.input-append .btn-group > .dropdown-toggle, +.input-prepend .btn-group > .dropdown-toggle { + vertical-align: top; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-append .active, +.input-prepend .active { + background-color: #a9dba9; + border-color: #46a546; +} + +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px; +} + +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input + .btn-group .btn:last-child, +.input-append select + .btn-group .btn:last-child, +.input-append .uneditable-input + .btn-group .btn:last-child { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append .add-on, +.input-append .btn, +.input-append .btn-group { + margin-left: -1px; +} + +.input-append .add-on:last-child, +.input-append .btn:last-child, +.input-append .btn-group:last-child > .dropdown-toggle { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-prepend.input-append input + .btn-group .btn, +.input-prepend.input-append select + .btn-group .btn, +.input-prepend.input-append .uneditable-input + .btn-group .btn { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .btn-group:first-child { + margin-left: 0; +} + +input.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + /* IE7-8 doesn't have border-radius, so don't indent the padding */ + + margin-bottom: 0; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +/* Allow for input prepend/append in search forms */ + +.form-search .input-append .search-query, +.form-search .input-prepend .search-query { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.form-search .input-append .search-query { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search .input-append .btn { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .search-query { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .btn { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + margin-bottom: 0; + vertical-align: middle; + *zoom: 1; +} + +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none; +} + +.form-search label, +.form-inline label, +.form-search .btn-group, +.form-inline .btn-group { + display: inline-block; +} + +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0; +} + +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle; +} + +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0; +} + +.control-group { + margin-bottom: 10px; +} + +legend + .control-group { + margin-top: 20px; + -webkit-margin-top-collapse: separate; +} + +.form-horizontal .control-group { + margin-bottom: 20px; + *zoom: 1; +} + +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + line-height: 0; + content: ""; +} + +.form-horizontal .control-group:after { + clear: both; +} + +.form-horizontal .control-label { + float: left; + width: 160px; + padding-top: 5px; + text-align: right; +} + +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 180px; + *margin-left: 0; +} + +.form-horizontal .controls:first-child { + *padding-left: 180px; +} + +.form-horizontal .help-block { + margin-bottom: 0; +} + +.form-horizontal input + .help-block, +.form-horizontal select + .help-block, +.form-horizontal textarea + .help-block, +.form-horizontal .uneditable-input + .help-block, +.form-horizontal .input-prepend + .help-block, +.form-horizontal .input-append + .help-block { + margin-top: 10px; +} + +.form-horizontal .form-actions { + padding-left: 180px; +} + +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; +} + +.table { + width: 100%; + margin-bottom: 20px; +} + +.table th, +.table td { + padding: 8px; + line-height: 20px; + text-align: left; + vertical-align: top; + border-top: 1px solid #dddddd; +} + +.table th { + font-weight: bold; +} + +.table thead th { + vertical-align: bottom; +} + +.table caption + thead tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child th, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0; +} + +.table tbody + tbody { + border-top: 2px solid #dddddd; +} + +.table .table { + background-color: #ffffff; +} + +.table-condensed th, +.table-condensed td { + padding: 4px 5px; +} + +.table-bordered { + border: 1px solid #dddddd; + border-collapse: separate; + *border-collapse: collapse; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.table-bordered th, +.table-bordered td { + border-left: 1px solid #dddddd; +} + +.table-bordered caption + thead tr:first-child th, +.table-bordered caption + tbody tr:first-child th, +.table-bordered caption + tbody tr:first-child td, +.table-bordered colgroup + thead tr:first-child th, +.table-bordered colgroup + tbody tr:first-child th, +.table-bordered colgroup + tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0; +} + +.table-bordered thead:first-child tr:first-child > th:first-child, +.table-bordered tbody:first-child tr:first-child > td:first-child, +.table-bordered tbody:first-child tr:first-child > th:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered thead:first-child tr:first-child > th:last-child, +.table-bordered tbody:first-child tr:first-child > td:last-child, +.table-bordered tbody:first-child tr:first-child > th:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:first-child, +.table-bordered tbody:last-child tr:last-child > td:first-child, +.table-bordered tbody:last-child tr:last-child > th:first-child, +.table-bordered tfoot:last-child tr:last-child > td:first-child, +.table-bordered tfoot:last-child tr:last-child > th:first-child { + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:last-child, +.table-bordered tbody:last-child tr:last-child > td:last-child, +.table-bordered tbody:last-child tr:last-child > th:last-child, +.table-bordered tfoot:last-child tr:last-child > td:last-child, +.table-bordered tfoot:last-child tr:last-child > th:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomleft: 0; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomright: 0; +} + +.table-bordered caption + thead tr:first-child th:first-child, +.table-bordered caption + tbody tr:first-child td:first-child, +.table-bordered colgroup + thead tr:first-child th:first-child, +.table-bordered colgroup + tbody tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered caption + thead tr:first-child th:last-child, +.table-bordered caption + tbody tr:first-child td:last-child, +.table-bordered colgroup + thead tr:first-child th:last-child, +.table-bordered colgroup + tbody tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-striped tbody > tr:nth-child(odd) > td, +.table-striped tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} + +.table-hover tbody tr:hover > td, +.table-hover tbody tr:hover > th { + background-color: #f5f5f5; +} + +table td[class*="span"], +table th[class*="span"], +.row-fluid table td[class*="span"], +.row-fluid table th[class*="span"] { + display: table-cell; + float: none; + margin-left: 0; +} + +.table td.span1, +.table th.span1 { + float: none; + width: 44px; + margin-left: 0; +} + +.table td.span2, +.table th.span2 { + float: none; + width: 124px; + margin-left: 0; +} + +.table td.span3, +.table th.span3 { + float: none; + width: 204px; + margin-left: 0; +} + +.table td.span4, +.table th.span4 { + float: none; + width: 284px; + margin-left: 0; +} + +.table td.span5, +.table th.span5 { + float: none; + width: 364px; + margin-left: 0; +} + +.table td.span6, +.table th.span6 { + float: none; + width: 444px; + margin-left: 0; +} + +.table td.span7, +.table th.span7 { + float: none; + width: 524px; + margin-left: 0; +} + +.table td.span8, +.table th.span8 { + float: none; + width: 604px; + margin-left: 0; +} + +.table td.span9, +.table th.span9 { + float: none; + width: 684px; + margin-left: 0; +} + +.table td.span10, +.table th.span10 { + float: none; + width: 764px; + margin-left: 0; +} + +.table td.span11, +.table th.span11 { + float: none; + width: 844px; + margin-left: 0; +} + +.table td.span12, +.table th.span12 { + float: none; + width: 924px; + margin-left: 0; +} + +.table tbody tr.success > td { + background-color: #dff0d8; +} + +.table tbody tr.error > td { + background-color: #f2dede; +} + +.table tbody tr.warning > td { + background-color: #fcf8e3; +} + +.table tbody tr.info > td { + background-color: #d9edf7; +} + +.table-hover tbody tr.success:hover > td { + background-color: #d0e9c6; +} + +.table-hover tbody tr.error:hover > td { + background-color: #ebcccc; +} + +.table-hover tbody tr.warning:hover > td { + background-color: #faf2cc; +} + +.table-hover tbody tr.info:hover > td { + background-color: #c4e3f3; +} + +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + margin-top: 1px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; +} + +/* White icons with optional class, or on hover/focus/active states of certain elements */ + +.icon-white, +.nav-pills > .active > a > [class^="icon-"], +.nav-pills > .active > a > [class*=" icon-"], +.nav-list > .active > a > [class^="icon-"], +.nav-list > .active > a > [class*=" icon-"], +.navbar-inverse .nav > .active > a > [class^="icon-"], +.navbar-inverse .nav > .active > a > [class*=" icon-"], +.dropdown-menu > li > a:hover > [class^="icon-"], +.dropdown-menu > li > a:focus > [class^="icon-"], +.dropdown-menu > li > a:hover > [class*=" icon-"], +.dropdown-menu > li > a:focus > [class*=" icon-"], +.dropdown-menu > .active > a > [class^="icon-"], +.dropdown-menu > .active > a > [class*=" icon-"], +.dropdown-submenu:hover > a > [class^="icon-"], +.dropdown-submenu:focus > a > [class^="icon-"], +.dropdown-submenu:hover > a > [class*=" icon-"], +.dropdown-submenu:focus > a > [class*=" icon-"] { + background-image: url("../img/glyphicons-halflings-white.png"); +} + +.icon-glass { + background-position: 0 0; +} + +.icon-music { + background-position: -24px 0; +} + +.icon-search { + background-position: -48px 0; +} + +.icon-envelope { + background-position: -72px 0; +} + +.icon-heart { + background-position: -96px 0; +} + +.icon-star { + background-position: -120px 0; +} + +.icon-star-empty { + background-position: -144px 0; +} + +.icon-user { + background-position: -168px 0; +} + +.icon-film { + background-position: -192px 0; +} + +.icon-th-large { + background-position: -216px 0; +} + +.icon-th { + background-position: -240px 0; +} + +.icon-th-list { + background-position: -264px 0; +} + +.icon-ok { + background-position: -288px 0; +} + +.icon-remove { + background-position: -312px 0; +} + +.icon-zoom-in { + background-position: -336px 0; +} + +.icon-zoom-out { + background-position: -360px 0; +} + +.icon-off { + background-position: -384px 0; +} + +.icon-signal { + background-position: -408px 0; +} + +.icon-cog { + background-position: -432px 0; +} + +.icon-trash { + background-position: -456px 0; +} + +.icon-home { + background-position: 0 -24px; +} + +.icon-file { + background-position: -24px -24px; +} + +.icon-time { + background-position: -48px -24px; +} + +.icon-road { + background-position: -72px -24px; +} + +.icon-download-alt { + background-position: -96px -24px; +} + +.icon-download { + background-position: -120px -24px; +} + +.icon-upload { + background-position: -144px -24px; +} + +.icon-inbox { + background-position: -168px -24px; +} + +.icon-play-circle { + background-position: -192px -24px; +} + +.icon-repeat { + background-position: -216px -24px; +} + +.icon-refresh { + background-position: -240px -24px; +} + +.icon-list-alt { + background-position: -264px -24px; +} + +.icon-lock { + background-position: -287px -24px; +} + +.icon-flag { + background-position: -312px -24px; +} + +.icon-headphones { + background-position: -336px -24px; +} + +.icon-volume-off { + background-position: -360px -24px; +} + +.icon-volume-down { + background-position: -384px -24px; +} + +.icon-volume-up { + background-position: -408px -24px; +} + +.icon-qrcode { + background-position: -432px -24px; +} + +.icon-barcode { + background-position: -456px -24px; +} + +.icon-tag { + background-position: 0 -48px; +} + +.icon-tags { + background-position: -25px -48px; +} + +.icon-book { + background-position: -48px -48px; +} + +.icon-bookmark { + background-position: -72px -48px; +} + +.icon-print { + background-position: -96px -48px; +} + +.icon-camera { + background-position: -120px -48px; +} + +.icon-font { + background-position: -144px -48px; +} + +.icon-bold { + background-position: -167px -48px; +} + +.icon-italic { + background-position: -192px -48px; +} + +.icon-text-height { + background-position: -216px -48px; +} + +.icon-text-width { + background-position: -240px -48px; +} + +.icon-align-left { + background-position: -264px -48px; +} + +.icon-align-center { + background-position: -288px -48px; +} + +.icon-align-right { + background-position: -312px -48px; +} + +.icon-align-justify { + background-position: -336px -48px; +} + +.icon-list { + background-position: -360px -48px; +} + +.icon-indent-left { + background-position: -384px -48px; +} + +.icon-indent-right { + background-position: -408px -48px; +} + +.icon-facetime-video { + background-position: -432px -48px; +} + +.icon-picture { + background-position: -456px -48px; +} + +.icon-pencil { + background-position: 0 -72px; +} + +.icon-map-marker { + background-position: -24px -72px; +} + +.icon-adjust { + background-position: -48px -72px; +} + +.icon-tint { + background-position: -72px -72px; +} + +.icon-edit { + background-position: -96px -72px; +} + +.icon-share { + background-position: -120px -72px; +} + +.icon-check { + background-position: -144px -72px; +} + +.icon-move { + background-position: -168px -72px; +} + +.icon-step-backward { + background-position: -192px -72px; +} + +.icon-fast-backward { + background-position: -216px -72px; +} + +.icon-backward { + background-position: -240px -72px; +} + +.icon-play { + background-position: -264px -72px; +} + +.icon-pause { + background-position: -288px -72px; +} + +.icon-stop { + background-position: -312px -72px; +} + +.icon-forward { + background-position: -336px -72px; +} + +.icon-fast-forward { + background-position: -360px -72px; +} + +.icon-step-forward { + background-position: -384px -72px; +} + +.icon-eject { + background-position: -408px -72px; +} + +.icon-chevron-left { + background-position: -432px -72px; +} + +.icon-chevron-right { + background-position: -456px -72px; +} + +.icon-plus-sign { + background-position: 0 -96px; +} + +.icon-minus-sign { + background-position: -24px -96px; +} + +.icon-remove-sign { + background-position: -48px -96px; +} + +.icon-ok-sign { + background-position: -72px -96px; +} + +.icon-question-sign { + background-position: -96px -96px; +} + +.icon-info-sign { + background-position: -120px -96px; +} + +.icon-screenshot { + background-position: -144px -96px; +} + +.icon-remove-circle { + background-position: -168px -96px; +} + +.icon-ok-circle { + background-position: -192px -96px; +} + +.icon-ban-circle { + background-position: -216px -96px; +} + +.icon-arrow-left { + background-position: -240px -96px; +} + +.icon-arrow-right { + background-position: -264px -96px; +} + +.icon-arrow-up { + background-position: -289px -96px; +} + +.icon-arrow-down { + background-position: -312px -96px; +} + +.icon-share-alt { + background-position: -336px -96px; +} + +.icon-resize-full { + background-position: -360px -96px; +} + +.icon-resize-small { + background-position: -384px -96px; +} + +.icon-plus { + background-position: -408px -96px; +} + +.icon-minus { + background-position: -433px -96px; +} + +.icon-asterisk { + background-position: -456px -96px; +} + +.icon-exclamation-sign { + background-position: 0 -120px; +} + +.icon-gift { + background-position: -24px -120px; +} + +.icon-leaf { + background-position: -48px -120px; +} + +.icon-fire { + background-position: -72px -120px; +} + +.icon-eye-open { + background-position: -96px -120px; +} + +.icon-eye-close { + background-position: -120px -120px; +} + +.icon-warning-sign { + background-position: -144px -120px; +} + +.icon-plane { + background-position: -168px -120px; +} + +.icon-calendar { + background-position: -192px -120px; +} + +.icon-random { + width: 16px; + background-position: -216px -120px; +} + +.icon-comment { + background-position: -240px -120px; +} + +.icon-magnet { + background-position: -264px -120px; +} + +.icon-chevron-up { + background-position: -288px -120px; +} + +.icon-chevron-down { + background-position: -313px -119px; +} + +.icon-retweet { + background-position: -336px -120px; +} + +.icon-shopping-cart { + background-position: -360px -120px; +} + +.icon-folder-close { + width: 16px; + background-position: -384px -120px; +} + +.icon-folder-open { + width: 16px; + background-position: -408px -120px; +} + +.icon-resize-vertical { + background-position: -432px -119px; +} + +.icon-resize-horizontal { + background-position: -456px -118px; +} + +.icon-hdd { + background-position: 0 -144px; +} + +.icon-bullhorn { + background-position: -24px -144px; +} + +.icon-bell { + background-position: -48px -144px; +} + +.icon-certificate { + background-position: -72px -144px; +} + +.icon-thumbs-up { + background-position: -96px -144px; +} + +.icon-thumbs-down { + background-position: -120px -144px; +} + +.icon-hand-right { + background-position: -144px -144px; +} + +.icon-hand-left { + background-position: -168px -144px; +} + +.icon-hand-up { + background-position: -192px -144px; +} + +.icon-hand-down { + background-position: -216px -144px; +} + +.icon-circle-arrow-right { + background-position: -240px -144px; +} + +.icon-circle-arrow-left { + background-position: -264px -144px; +} + +.icon-circle-arrow-up { + background-position: -288px -144px; +} + +.icon-circle-arrow-down { + background-position: -312px -144px; +} + +.icon-globe { + background-position: -336px -144px; +} + +.icon-wrench { + background-position: -360px -144px; +} + +.icon-tasks { + background-position: -384px -144px; +} + +.icon-filter { + background-position: -408px -144px; +} + +.icon-briefcase { + background-position: -432px -144px; +} + +.icon-fullscreen { + background-position: -456px -144px; +} + +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle { + *margin-bottom: -3px; +} + +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: ""; +} + +.dropdown .caret { + margin-top: 8px; + margin-left: 2px; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 20px; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-submenu:hover > a, +.dropdown-submenu:focus > a { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + outline: 0; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} + +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.open { + *z-index: 1000; +} + +.open > .dropdown-menu { + display: block; +} + +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000000; + content: ""; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu > .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} + +.dropdown-submenu:hover > .dropdown-menu { + display: block; +} + +.dropup .dropdown-submenu > .dropdown-menu { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -2px; + -webkit-border-radius: 5px 5px 5px 0; + -moz-border-radius: 5px 5px 5px 0; + border-radius: 5px 5px 5px 0; +} + +.dropdown-submenu > a:after { + display: block; + float: right; + width: 0; + height: 0; + margin-top: 5px; + margin-right: -10px; + border-color: transparent; + border-left-color: #cccccc; + border-style: solid; + border-width: 5px 0 5px 5px; + content: " "; +} + +.dropdown-submenu:hover > a:after { + border-left-color: #ffffff; +} + +.dropdown-submenu.pull-left { + float: none; +} + +.dropdown-submenu.pull-left > .dropdown-menu { + left: -100%; + margin-left: 10px; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.dropdown .dropdown-menu .nav-header { + padding-right: 20px; + padding-left: 20px; +} + +.typeahead { + z-index: 1051; + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +.fade.in { + opacity: 1; +} + +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +.collapse.in { + height: auto; +} + +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 20px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.btn { + display: inline-block; + *display: inline; + padding: 4px 12px; + margin-bottom: 0; + *margin-left: .3em; + font-size: 14px; + line-height: 20px; + color: #333333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + *background-color: #e6e6e6; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + border: 1px solid #cccccc; + *border: 0; + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn:hover, +.btn:focus, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + color: #333333; + background-color: #e6e6e6; + *background-color: #d9d9d9; +} + +.btn:active, +.btn.active { + background-color: #cccccc \9; +} + +.btn:first-child { + *margin-left: 0; +} + +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.btn.active, +.btn:active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn.disabled, +.btn[disabled] { + cursor: default; + background-image: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-large { + padding: 11px 19px; + font-size: 17.5px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.btn-large [class^="icon-"], +.btn-large [class*=" icon-"] { + margin-top: 4px; +} + +.btn-small { + padding: 2px 10px; + font-size: 11.9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-small [class^="icon-"], +.btn-small [class*=" icon-"] { + margin-top: 0; +} + +.btn-mini [class^="icon-"], +.btn-mini [class*=" icon-"] { + margin-top: -1px; +} + +.btn-mini { + padding: 0 6px; + font-size: 10.5px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.btn-block + .btn-block { + margin-top: 5px; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75); +} + +.btn-primary { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #006dcc; + *background-color: #0044cc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + color: #ffffff; + background-color: #0044cc; + *background-color: #003bb3; +} + +.btn-primary:active, +.btn-primary.active { + background-color: #003399 \9; +} + +.btn-warning { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #faa732; + *background-color: #f89406; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + color: #ffffff; + background-color: #f89406; + *background-color: #df8505; +} + +.btn-warning:active, +.btn-warning.active { + background-color: #c67605 \9; +} + +.btn-danger { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #da4f49; + *background-color: #bd362f; + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); + background-repeat: repeat-x; + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + color: #ffffff; + background-color: #bd362f; + *background-color: #a9302a; +} + +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9; +} + +.btn-success { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #5bb75b; + *background-color: #51a351; + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(to bottom, #62c462, #51a351); + background-repeat: repeat-x; + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + color: #ffffff; + background-color: #51a351; + *background-color: #499249; +} + +.btn-success:active, +.btn-success.active { + background-color: #408140 \9; +} + +.btn-info { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #49afcd; + *background-color: #2f96b4; + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); + background-repeat: repeat-x; + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + color: #ffffff; + background-color: #2f96b4; + *background-color: #2a85a0; +} + +.btn-info:active, +.btn-info.active { + background-color: #24748c \9; +} + +.btn-inverse { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #363636; + *background-color: #222222; + background-image: -moz-linear-gradient(top, #444444, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); + background-image: -webkit-linear-gradient(top, #444444, #222222); + background-image: -o-linear-gradient(top, #444444, #222222); + background-image: linear-gradient(to bottom, #444444, #222222); + background-repeat: repeat-x; + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-inverse:hover, +.btn-inverse:focus, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + color: #ffffff; + background-color: #222222; + *background-color: #151515; +} + +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9; +} + +button.btn, +input[type="submit"].btn { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0; +} + +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px; +} + +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px; +} + +.btn-link, +.btn-link:active, +.btn-link[disabled] { + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-link { + color: #0088cc; + cursor: pointer; + border-color: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-link:hover, +.btn-link:focus { + color: #005580; + text-decoration: underline; + background-color: transparent; +} + +.btn-link[disabled]:hover, +.btn-link[disabled]:focus { + color: #333333; + text-decoration: none; +} + +.btn-group { + position: relative; + display: inline-block; + *display: inline; + *margin-left: .3em; + font-size: 0; + white-space: nowrap; + vertical-align: middle; + *zoom: 1; +} + +.btn-group:first-child { + *margin-left: 0; +} + +.btn-group + .btn-group { + margin-left: 5px; +} + +.btn-toolbar { + margin-top: 10px; + margin-bottom: 10px; + font-size: 0; +} + +.btn-toolbar > .btn + .btn, +.btn-toolbar > .btn-group + .btn, +.btn-toolbar > .btn + .btn-group { + margin-left: 5px; +} + +.btn-group > .btn { + position: relative; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group > .btn + .btn { + margin-left: -1px; +} + +.btn-group > .btn, +.btn-group > .dropdown-menu, +.btn-group > .popover { + font-size: 14px; +} + +.btn-group > .btn-mini { + font-size: 10.5px; +} + +.btn-group > .btn-small { + font-size: 11.9px; +} + +.btn-group > .btn-large { + font-size: 17.5px; +} + +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.btn-group > .btn:last-child, +.btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.btn-group > .btn.large:last-child, +.btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active { + z-index: 2; +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group > .btn + .dropdown-toggle { + *padding-top: 5px; + padding-right: 8px; + *padding-bottom: 5px; + padding-left: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group > .btn-mini + .dropdown-toggle { + *padding-top: 2px; + padding-right: 5px; + *padding-bottom: 2px; + padding-left: 5px; +} + +.btn-group > .btn-small + .dropdown-toggle { + *padding-top: 5px; + *padding-bottom: 4px; +} + +.btn-group > .btn-large + .dropdown-toggle { + *padding-top: 7px; + padding-right: 12px; + *padding-bottom: 7px; + padding-left: 12px; +} + +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6; +} + +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #0044cc; +} + +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406; +} + +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f; +} + +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351; +} + +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4; +} + +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222222; +} + +.btn .caret { + margin-top: 8px; + margin-left: 0; +} + +.btn-large .caret { + margin-top: 6px; +} + +.btn-large .caret { + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px; +} + +.btn-mini .caret, +.btn-small .caret { + margin-top: 8px; +} + +.dropup .btn-large .caret { + border-bottom-width: 5px; +} + +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.btn-group-vertical { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; +} + +.btn-group-vertical > .btn { + display: block; + float: none; + max-width: 100%; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group-vertical > .btn + .btn { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical > .btn:first-child { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.btn-group-vertical > .btn:last-child { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.btn-group-vertical > .btn-large:first-child { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +.btn-group-vertical > .btn-large:last-child { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 20px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.alert, +.alert h4 { + color: #c09853; +} + +.alert h4 { + margin: 0; +} + +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 20px; +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.alert-success h4 { + color: #468847; +} + +.alert-danger, +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.alert-danger h4, +.alert-error h4 { + color: #b94a48; +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.alert-info h4 { + color: #3a87ad; +} + +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} + +.alert-block > p, +.alert-block > ul { + margin-bottom: 0; +} + +.alert-block p + p { + margin-top: 5px; +} + +.nav { + margin-bottom: 20px; + margin-left: 0; + list-style: none; +} + +.nav > li > a { + display: block; +} + +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} + +.nav > li > a > img { + max-width: none; +} + +.nav > .pull-right { + float: right; +} + +.nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 20px; + color: #999999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} + +.nav li + .nav-header { + margin-top: 9px; +} + +.nav-list { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 0; +} + +.nav-list > li > a, +.nav-list .nav-header { + margin-right: -15px; + margin-left: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} + +.nav-list > li > a { + padding: 3px 15px; +} + +.nav-list > .active > a, +.nav-list > .active > a:hover, +.nav-list > .active > a:focus { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #0088cc; +} + +.nav-list [class^="icon-"], +.nav-list [class*=" icon-"] { + margin-right: 2px; +} + +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.nav-tabs, +.nav-pills { + *zoom: 1; +} + +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + line-height: 0; + content: ""; +} + +.nav-tabs:after, +.nav-pills:after { + clear: both; +} + +.nav-tabs > li, +.nav-pills > li { + float: left; +} + +.nav-tabs > li > a, +.nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px; +} + +.nav-tabs { + border-bottom: 1px solid #ddd; +} + +.nav-tabs > li { + margin-bottom: -1px; +} + +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 20px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.nav-tabs > li > a:hover, +.nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover, +.nav-tabs > .active > a:focus { + color: #555555; + cursor: default; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} + +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.nav-pills > .active > a, +.nav-pills > .active > a:hover, +.nav-pills > .active > a:focus { + color: #ffffff; + background-color: #0088cc; +} + +.nav-stacked > li { + float: none; +} + +.nav-stacked > li > a { + margin-right: 0; +} + +.nav-tabs.nav-stacked { + border-bottom: 0; +} + +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; +} + +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.nav-tabs.nav-stacked > li > a:hover, +.nav-tabs.nav-stacked > li > a:focus { + z-index: 2; + border-color: #ddd; +} + +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px; +} + +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px; +} + +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.nav-pills .dropdown-menu { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.nav .dropdown-toggle .caret { + margin-top: 6px; + border-top-color: #0088cc; + border-bottom-color: #0088cc; +} + +.nav .dropdown-toggle:hover .caret, +.nav .dropdown-toggle:focus .caret { + border-top-color: #005580; + border-bottom-color: #005580; +} + +/* move down carets for tabs */ + +.nav-tabs .dropdown-toggle .caret { + margin-top: 8px; +} + +.nav .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff; +} + +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.nav > .dropdown.active > a:hover, +.nav > .dropdown.active > a:focus { + cursor: pointer; +} + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover, +.nav > li.dropdown.open.active > a:focus { + color: #ffffff; + background-color: #999999; + border-color: #999999; +} + +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret, +.nav li.dropdown.open a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity=100); +} + +.tabs-stacked .open > a:hover, +.tabs-stacked .open > a:focus { + border-color: #999999; +} + +.tabbable { + *zoom: 1; +} + +.tabbable:before, +.tabbable:after { + display: table; + line-height: 0; + content: ""; +} + +.tabbable:after { + clear: both; +} + +.tab-content { + overflow: auto; +} + +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} + +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0; +} + +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.tabs-below > .nav-tabs > li > a:hover, +.tabs-below > .nav-tabs > li > a:focus { + border-top-color: #ddd; + border-bottom-color: transparent; +} + +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover, +.tabs-below > .nav-tabs > .active > a:focus { + border-color: transparent #ddd #ddd #ddd; +} + +.tabs-left > .nav-tabs > li, +.tabs-right > .nav-tabs > li { + float: none; +} + +.tabs-left > .nav-tabs > li > a, +.tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} + +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} + +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.tabs-left > .nav-tabs > li > a:hover, +.tabs-left > .nav-tabs > li > a:focus { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} + +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover, +.tabs-left > .nav-tabs .active > a:focus { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} + +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} + +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.tabs-right > .nav-tabs > li > a:hover, +.tabs-right > .nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} + +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover, +.tabs-right > .nav-tabs .active > a:focus { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} + +.nav > .disabled > a { + color: #999999; +} + +.nav > .disabled > a:hover, +.nav > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; +} + +.navbar { + *position: relative; + *z-index: 2; + margin-bottom: 20px; + overflow: visible; +} + +.navbar-inner { + min-height: 40px; + padding-right: 20px; + padding-left: 20px; + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); + background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); + background-repeat: repeat-x; + border: 1px solid #d4d4d4; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + *zoom: 1; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); +} + +.navbar-inner:before, +.navbar-inner:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-inner:after { + clear: both; +} + +.navbar .container { + width: auto; +} + +.nav-collapse.collapse { + height: auto; + overflow: visible; +} + +.navbar .brand { + display: block; + float: left; + padding: 10px 20px 10px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + color: #777777; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .brand:hover, +.navbar .brand:focus { + text-decoration: none; +} + +.navbar-text { + margin-bottom: 0; + line-height: 40px; + color: #777777; +} + +.navbar-link { + color: #777777; +} + +.navbar-link:hover, +.navbar-link:focus { + color: #333333; +} + +.navbar .divider-vertical { + height: 40px; + margin: 0 9px; + border-right: 1px solid #ffffff; + border-left: 1px solid #f2f2f2; +} + +.navbar .btn, +.navbar .btn-group { + margin-top: 5px; +} + +.navbar .btn-group .btn, +.navbar .input-prepend .btn, +.navbar .input-append .btn, +.navbar .input-prepend .btn-group, +.navbar .input-append .btn-group { + margin-top: 0; +} + +.navbar-form { + margin-bottom: 0; + *zoom: 1; +} + +.navbar-form:before, +.navbar-form:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-form:after { + clear: both; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .btn { + display: inline-block; + margin-bottom: 0; +} + +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px; +} + +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 5px; + white-space: nowrap; +} + +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0; +} + +.navbar-search { + position: relative; + float: left; + margin-top: 5px; + margin-bottom: 0; +} + +.navbar-search .search-query { + padding: 4px 14px; + margin-bottom: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.navbar-static-top { + position: static; + margin-bottom: 0; +} + +.navbar-static-top .navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + border-width: 0 0 1px; +} + +.navbar-fixed-bottom .navbar-inner { + border-width: 1px 0 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-right: 0; + padding-left: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.navbar-fixed-top { + top: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar-fixed-bottom { + bottom: 0; +} + +.navbar-fixed-bottom .navbar-inner { + -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0; +} + +.navbar .nav.pull-right { + float: right; + margin-right: 0; +} + +.navbar .nav > li { + float: left; +} + +.navbar .nav > li > a { + float: none; + padding: 10px 15px 10px; + color: #777777; + text-decoration: none; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .nav .dropdown-toggle .caret { + margin-top: 8px; +} + +.navbar .nav > li > a:focus, +.navbar .nav > li > a:hover { + color: #333333; + text-decoration: none; + background-color: transparent; +} + +.navbar .nav > .active > a, +.navbar .nav > .active > a:hover, +.navbar .nav > .active > a:focus { + color: #555555; + text-decoration: none; + background-color: #e5e5e5; + -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); +} + +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-right: 5px; + margin-left: 5px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #ededed; + *background-color: #e5e5e5; + background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); + background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); + background-repeat: repeat-x; + border-color: #e5e5e5 #e5e5e5 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); +} + +.navbar .btn-navbar:hover, +.navbar .btn-navbar:focus, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + color: #ffffff; + background-color: #e5e5e5; + *background-color: #d9d9d9; +} + +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #cccccc \9; +} + +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); +} + +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px; +} + +.navbar .nav > li > .dropdown-menu:before { + position: absolute; + top: -7px; + left: 9px; + display: inline-block; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-left: 7px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; +} + +.navbar .nav > li > .dropdown-menu:after { + position: absolute; + top: -6px; + left: 10px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + border-left: 6px solid transparent; + content: ''; +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:before { + top: auto; + bottom: -7px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2); +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:after { + top: auto; + bottom: -6px; + border-top: 6px solid #ffffff; + border-bottom: 0; +} + +.navbar .nav li.dropdown > a:hover .caret, +.navbar .nav li.dropdown > a:focus .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + color: #555555; + background-color: #e5e5e5; +} + +.navbar .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #777777; + border-bottom-color: #777777; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.navbar .pull-right > li > .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:before, +.navbar .nav > li > .dropdown-menu.pull-right:before { + right: 12px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:after, +.navbar .nav > li > .dropdown-menu.pull-right:after { + right: 13px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { + right: 100%; + left: auto; + margin-right: -1px; + margin-left: 0; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.navbar-inverse .navbar-inner { + background-color: #1b1b1b; + background-image: -moz-linear-gradient(top, #222222, #111111); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); + background-image: -webkit-linear-gradient(top, #222222, #111111); + background-image: -o-linear-gradient(top, #222222, #111111); + background-image: linear-gradient(to bottom, #222222, #111111); + background-repeat: repeat-x; + border-color: #252525; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); +} + +.navbar-inverse .brand, +.navbar-inverse .nav > li > a { + color: #999999; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-inverse .brand:hover, +.navbar-inverse .nav > li > a:hover, +.navbar-inverse .brand:focus, +.navbar-inverse .nav > li > a:focus { + color: #ffffff; +} + +.navbar-inverse .brand { + color: #999999; +} + +.navbar-inverse .navbar-text { + color: #999999; +} + +.navbar-inverse .nav > li > a:focus, +.navbar-inverse .nav > li > a:hover { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .nav .active > a, +.navbar-inverse .nav .active > a:hover, +.navbar-inverse .nav .active > a:focus { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .navbar-link { + color: #999999; +} + +.navbar-inverse .navbar-link:hover, +.navbar-inverse .navbar-link:focus { + color: #ffffff; +} + +.navbar-inverse .divider-vertical { + border-right-color: #222222; + border-left-color: #111111; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .nav li.dropdown > a:hover .caret, +.navbar-inverse .nav li.dropdown > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .navbar-search .search-query { + color: #ffffff; + background-color: #515151; + border-color: #111111; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; +} + +.navbar-inverse .navbar-search .search-query:-moz-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:focus, +.navbar-inverse .navbar-search .search-query.focused { + padding: 5px 15px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} + +.navbar-inverse .btn-navbar { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e0e0e; + *background-color: #040404; + background-image: -moz-linear-gradient(top, #151515, #040404); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); + background-image: -webkit-linear-gradient(top, #151515, #040404); + background-image: -o-linear-gradient(top, #151515, #040404); + background-image: linear-gradient(to bottom, #151515, #040404); + background-repeat: repeat-x; + border-color: #040404 #040404 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.navbar-inverse .btn-navbar:hover, +.navbar-inverse .btn-navbar:focus, +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active, +.navbar-inverse .btn-navbar.disabled, +.navbar-inverse .btn-navbar[disabled] { + color: #ffffff; + background-color: #040404; + *background-color: #000000; +} + +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active { + background-color: #000000 \9; +} + +.breadcrumb { + padding: 8px 15px; + margin: 0 0 20px; + list-style: none; + background-color: #f5f5f5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.breadcrumb > li { + display: inline-block; + *display: inline; + text-shadow: 0 1px 0 #ffffff; + *zoom: 1; +} + +.breadcrumb > li > .divider { + padding: 0 5px; + color: #ccc; +} + +.breadcrumb > .active { + color: #999999; +} + +.pagination { + margin: 20px 0; +} + +.pagination ul { + display: inline-block; + *display: inline; + margin-bottom: 0; + margin-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + *zoom: 1; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.pagination ul > li { + display: inline; +} + +.pagination ul > li > a, +.pagination ul > li > span { + float: left; + padding: 4px 12px; + line-height: 20px; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; + border-left-width: 0; +} + +.pagination ul > li > a:hover, +.pagination ul > li > a:focus, +.pagination ul > .active > a, +.pagination ul > .active > span { + background-color: #f5f5f5; +} + +.pagination ul > .active > a, +.pagination ul > .active > span { + color: #999999; + cursor: default; +} + +.pagination ul > .disabled > span, +.pagination ul > .disabled > a, +.pagination ul > .disabled > a:hover, +.pagination ul > .disabled > a:focus { + color: #999999; + cursor: default; + background-color: transparent; +} + +.pagination ul > li:first-child > a, +.pagination ul > li:first-child > span { + border-left-width: 1px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.pagination ul > li:last-child > a, +.pagination ul > li:last-child > span { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.pagination-centered { + text-align: center; +} + +.pagination-right { + text-align: right; +} + +.pagination-large ul > li > a, +.pagination-large ul > li > span { + padding: 11px 19px; + font-size: 17.5px; +} + +.pagination-large ul > li:first-child > a, +.pagination-large ul > li:first-child > span { + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.pagination-large ul > li:last-child > a, +.pagination-large ul > li:last-child > span { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.pagination-mini ul > li:first-child > a, +.pagination-small ul > li:first-child > a, +.pagination-mini ul > li:first-child > span, +.pagination-small ul > li:first-child > span { + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-topleft: 3px; +} + +.pagination-mini ul > li:last-child > a, +.pagination-small ul > li:last-child > a, +.pagination-mini ul > li:last-child > span, +.pagination-small ul > li:last-child > span { + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-bottomright: 3px; +} + +.pagination-small ul > li > a, +.pagination-small ul > li > span { + padding: 2px 10px; + font-size: 11.9px; +} + +.pagination-mini ul > li > a, +.pagination-mini ul > li > span { + padding: 0 6px; + font-size: 10.5px; +} + +.pager { + margin: 20px 0; + text-align: center; + list-style: none; + *zoom: 1; +} + +.pager:before, +.pager:after { + display: table; + line-height: 0; + content: ""; +} + +.pager:after { + clear: both; +} + +.pager li { + display: inline; +} + +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #f5f5f5; +} + +.pager .next > a, +.pager .next > span { + float: right; +} + +.pager .previous > a, +.pager .previous > span { + float: left; +} + +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + cursor: default; + background-color: #fff; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +.modal.fade { + top: -25%; + -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; + -moz-transition: opacity 0.3s linear, top 0.3s ease-out; + -o-transition: opacity 0.3s linear, top 0.3s ease-out; + transition: opacity 0.3s linear, top 0.3s ease-out; +} + +.modal.fade.in { + top: 10%; +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} + +.modal-header .close { + margin-top: 2px; +} + +.modal-header h3 { + margin: 0; + line-height: 30px; +} + +.modal-body { + position: relative; + max-height: 400px; + padding: 15px; + overflow-y: auto; +} + +.modal-form { + margin-bottom: 0; +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + line-height: 0; + content: ""; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 11px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} + +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} + +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} + +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} + +.tooltip-inner { + max-width: 200px; + padding: 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000000; + border-width: 5px 5px 5px 0; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000000; + border-width: 5px 0 5px 5px; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.popover.top { + margin-top: -10px; +} + +.popover.right { + margin-left: 10px; +} + +.popover.bottom { + margin-top: 10px; +} + +.popover.left { + margin-left: -10px; +} + +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + +.popover-title:empty { + display: none; +} + +.popover-content { + padding: 9px 14px; +} + +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover .arrow { + border-width: 11px; +} + +.popover .arrow:after { + border-width: 10px; + content: ""; +} + +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, 0.25); + border-bottom-width: 0; +} + +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-top-color: #ffffff; + border-bottom-width: 0; +} + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, 0.25); + border-left-width: 0; +} + +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + border-right-color: #ffffff; + border-left-width: 0; +} + +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-top-width: 0; +} + +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-bottom-color: #ffffff; + border-top-width: 0; +} + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, 0.25); + border-right-width: 0; +} + +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + border-left-color: #ffffff; + border-right-width: 0; +} + +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1; +} + +.thumbnails:before, +.thumbnails:after { + display: table; + line-height: 0; + content: ""; +} + +.thumbnails:after { + clear: both; +} + +.row-fluid .thumbnails { + margin-left: 0; +} + +.thumbnails > li { + float: left; + margin-bottom: 20px; + margin-left: 20px; +} + +.thumbnail { + display: block; + padding: 4px; + line-height: 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +a.thumbnail:hover, +a.thumbnail:focus { + border-color: #0088cc; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} + +.thumbnail > img { + display: block; + max-width: 100%; + margin-right: auto; + margin-left: auto; +} + +.thumbnail .caption { + padding: 9px; + color: #555555; +} + +.media, +.media-body { + overflow: hidden; + *overflow: visible; + zoom: 1; +} + +.media, +.media .media { + margin-top: 15px; +} + +.media:first-child { + margin-top: 0; +} + +.media-object { + display: block; +} + +.media-heading { + margin: 0 0 5px; +} + +.media > .pull-left { + margin-right: 10px; +} + +.media > .pull-right { + margin-left: 10px; +} + +.media-list { + margin-left: 0; + list-style: none; +} + +.label, +.badge { + display: inline-block; + padding: 2px 4px; + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; +} + +.label { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.badge { + padding-right: 9px; + padding-left: 9px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} + +.label:empty, +.badge:empty { + display: none; +} + +a.label:hover, +a.label:focus, +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label-important, +.badge-important { + background-color: #b94a48; +} + +.label-important[href], +.badge-important[href] { + background-color: #953b39; +} + +.label-warning, +.badge-warning { + background-color: #f89406; +} + +.label-warning[href], +.badge-warning[href] { + background-color: #c67605; +} + +.label-success, +.badge-success { + background-color: #468847; +} + +.label-success[href], +.badge-success[href] { + background-color: #356635; +} + +.label-info, +.badge-info { + background-color: #3a87ad; +} + +.label-info[href], +.badge-info[href] { + background-color: #2d6987; +} + +.label-inverse, +.badge-inverse { + background-color: #333333; +} + +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a; +} + +.btn .label, +.btn .badge { + position: relative; + top: -1px; +} + +.btn-mini .label, +.btn-mini .badge { + top: 0; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress .bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + color: #ffffff; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(to bottom, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width 0.6s ease; + -moz-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress .bar + .bar { + -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); +} + +.progress-striped .bar { + background-color: #149bdf; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px; +} + +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-danger .bar, +.progress .bar-danger { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); +} + +.progress-danger.progress-striped .bar, +.progress-striped .bar-danger { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-success .bar, +.progress .bar-success { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(to bottom, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); +} + +.progress-success.progress-striped .bar, +.progress-striped .bar-success { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-info .bar, +.progress .bar-info { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(to bottom, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); +} + +.progress-info.progress-striped .bar, +.progress-striped .bar-info { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-warning .bar, +.progress .bar-warning { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); +} + +.progress-warning.progress-striped .bar, +.progress-striped .bar-warning { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.accordion { + margin-bottom: 20px; +} + +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.accordion-heading { + border-bottom: 0; +} + +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px; +} + +.accordion-toggle { + cursor: pointer; +} + +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5; +} + +.carousel { + position: relative; + margin-bottom: 20px; + line-height: 1; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + -moz-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} + +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + line-height: 1; +} + +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} + +.carousel-inner > .active { + left: 0; +} + +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel-inner > .next { + left: 100%; +} + +.carousel-inner > .prev { + left: -100%; +} + +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} + +.carousel-inner > .active.left { + left: -100%; +} + +.carousel-inner > .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #ffffff; + text-align: center; + background: #222222; + border: 3px solid #ffffff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: 0.5; + filter: alpha(opacity=50); +} + +.carousel-control.right { + right: 15px; + left: auto; +} + +.carousel-control:hover, +.carousel-control:focus { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} + +.carousel-indicators { + position: absolute; + top: 15px; + right: 15px; + z-index: 5; + margin: 0; + list-style: none; +} + +.carousel-indicators li { + display: block; + float: left; + width: 10px; + height: 10px; + margin-left: 5px; + text-indent: -999px; + background-color: #ccc; + background-color: rgba(255, 255, 255, 0.25); + border-radius: 5px; +} + +.carousel-indicators .active { + background-color: #fff; +} + +.carousel-caption { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 15px; + background: #333333; + background: rgba(0, 0, 0, 0.75); +} + +.carousel-caption h4, +.carousel-caption p { + line-height: 20px; + color: #ffffff; +} + +.carousel-caption h4 { + margin: 0 0 5px; +} + +.carousel-caption p { + margin-bottom: 0; +} + +.hero-unit { + padding: 60px; + margin-bottom: 30px; + font-size: 18px; + font-weight: 200; + line-height: 30px; + color: inherit; + background-color: #eeeeee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + color: inherit; +} + +.hero-unit li { + line-height: 30px; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.hide { + display: none; +} + +.show { + display: block; +} + +.invisible { + visibility: hidden; +} + +.affix { + position: fixed; +} diff --git a/docs/_static/bootstrap-2.3.2/css/bootstrap.min.css b/docs/_static/bootstrap-2.3.2/css/bootstrap.min.css new file mode 100644 index 00000000..b6428e69 --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/css/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} diff --git a/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings-white.png b/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings-white.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf6484a29d8da269f9bc874b25493a45fae3bae GIT binary patch literal 8777 zcmZvC1yGz#v+m*$LXcp=A$ZWB0fL7wNbp_U*$~{_gL`my3oP#L!5tQYy99Ta`+g_q zKlj|KJ2f@c)ARJx{q*bbkhN_!|Wn*Vos8{TEhUT@5e;_WJsIMMcG5%>DiS&dv_N`4@J0cnAQ-#>RjZ z00W5t&tJ^l-QC*ST1-p~00u^9XJ=AUl7oW-;2a+x2k__T=grN{+1c4XK0ZL~^z^i$ zp&>vEhr@4fZWb380S18T&!0cQ3IKpHF)?v=b_NIm0Q>vwY7D0baZ)n z31Fa5sELUQARIVaU0nqf0XzT+fB_63aA;@<$l~wse|mcA;^G1TmX?-)e)jkGPfkuA z92@|!<>h5S_4f8QP-JRq>d&7)^Yin8l7K8gED$&_FaV?gY+wLjpoW%~7NDe=nHfMG z5DO3j{R9kv5GbssrUpO)OyvVrlx>u0UKD0i;Dpm5S5dY16(DL5l{ixz|mhJU@&-OWCTb7_%}8-fE(P~+XIRO zJU|wp1|S>|J3KrLcz^+v1f&BDpd>&MAaibR4#5A_4(MucZwG9E1h4@u0P@C8;oo+g zIVj7kfJi{oV~E(NZ*h(@^-(Q(C`Psb3KZ{N;^GB(a8NE*Vwc715!9 zr-H4Ao|T_c6+VT_JH9H+P3>iXSt!a$F`>s`jn`w9GZ_~B!{0soaiV|O_c^R2aWa%}O3jUE)WO=pa zs~_Wz08z|ieY5A%$@FcBF9^!1a}m5ks@7gjn;67N>}S~Hrm`4sM5Hh`q7&5-N{|31 z6x1{ol7BnskoViZ0GqbLa#kW`Z)VCjt1MysKg|rT zi!?s##Ck>8c zpi|>$lGlw#@yMNi&V4`6OBGJ(H&7lqLlcTQ&1zWriG_fL>BnFcr~?;E93{M-xIozQ zO=EHQ#+?<}%@wbWWv23#!V70h9MOuUVaU>3kpTvYfc|LBw?&b*89~Gc9i&8tlT#kF ztpbZoAzkdB+UTy=tx%L3Z4)I{zY(Kb)eg{InobSJmNwPZt$14aS-uc4eKuY8h$dtfyxu^a%zA)>fYI&)@ZXky?^{5>xSC?;w4r&td6vBdi%vHm4=XJH!3yL3?Ep+T5aU_>i;yr_XGq zxZfCzUU@GvnoIk+_Nd`aky>S&H!b*{A%L>?*XPAgWL(Vf(k7qUS}>Zn=U(ZfcOc{B z3*tOHH@t5Ub5D~#N7!Fxx}P2)sy{vE_l(R7$aW&CX>c|&HY+7};vUIietK%}!phrCuh+;C@1usp;XLU<8Gq8P!rEI3ieg#W$!= zQcZr{hp>8sF?k&Yl0?B84OneiQxef-4TEFrq3O~JAZR}yEJHA|Xkqd49tR&8oq{zP zY@>J^HBV*(gJvJZc_0VFN7Sx?H7#75E3#?N8Z!C+_f53YU}pyggxx1?wQi5Yb-_`I`_V*SMx5+*P^b=ec5RON-k1cIlsBLk}(HiaJyab0`CI zo0{=1_LO$~oE2%Tl_}KURuX<`+mQN_sTdM&* zkFf!Xtl^e^gTy6ON=&gTn6)$JHQq2)33R@_!#9?BLNq-Wi{U|rVX7Vny$l6#+SZ@KvQt@VYb%<9JfapI^b9j=wa+Tqb4ei;8c5 z&1>Uz@lVFv6T4Z*YU$r4G`g=91lSeA<=GRZ!*KTWKDPR}NPUW%peCUj`Ix_LDq!8| zMH-V`Pv!a~QkTL||L@cqiTz)*G-0=ytr1KqTuFPan9y4gYD5>PleK`NZB$ev@W%t= zkp)_=lBUTLZJpAtZg;pjI;7r2y|26-N7&a(hX|`1YNM9N8{>8JAuv}hp1v`3JHT-=5lbXpbMq7X~2J5Kl zh7tyU`_AusMFZ{ej9D;Uyy;SQ!4nwgSnngsYBwdS&EO3NS*o04)*juAYl;57c2Ly0(DEZ8IY?zSph-kyxu+D`tt@oU{32J#I{vmy=#0ySPK zA+i(A3yl)qmTz*$dZi#y9FS;$;h%bY+;StNx{_R56Otq+?pGe^T^{5d7Gs&?`_r`8 zD&dzOA|j8@3A&FR5U3*eQNBf<4^4W_iS_()*8b4aaUzfk2 zzIcMWSEjm;EPZPk{j{1>oXd}pXAj!NaRm8{Sjz!D=~q3WJ@vmt6ND_?HI~|wUS1j5 z9!S1MKr7%nxoJ3k`GB^7yV~*{n~O~n6($~x5Bu{7s|JyXbAyKI4+tO(zZYMslK;Zc zzeHGVl{`iP@jfSKq>R;{+djJ9n%$%EL()Uw+sykjNQdflkJZSjqV_QDWivbZS~S{K zkE@T^Jcv)Dfm93!mf$XYnCT--_A$zo9MOkPB6&diM8MwOfV?+ApNv`moV@nqn>&lv zYbN1-M|jc~sG|yLN^1R2=`+1ih3jCshg`iP&mY$GMTcY^W^T`WOCX!{-KHmZ#GiRH zYl{|+KLn5!PCLtBy~9i}`#d^gCDDx$+GQb~uc;V#K3OgbbOG0j5{BRG-si%Bo{@lB zGIt+Ain8^C`!*S0d0OSWVO+Z89}}O8aFTZ>p&k}2gGCV zh#<$gswePFxWGT$4DC^8@84_e*^KT74?7n8!$8cg=sL$OlKr&HMh@Rr5%*Wr!xoOl zo7jItnj-xYgVTX)H1=A2bD(tleEH57#V{xAeW_ezISg5OC zg=k>hOLA^urTH_e6*vSYRqCm$J{xo}-x3@HH;bsHD1Z`Pzvsn}%cvfw%Q(}h`Dgtb z0_J^niUmoCM5$*f)6}}qi(u;cPgxfyeVaaVmOsG<)5`6tzU4wyhF;k|~|x>7-2hXpVBpc5k{L4M`Wbe6Q?tr^*B z`Y*>6*&R#~%JlBIitlZ^qGe3s21~h3U|&k%%jeMM;6!~UH|+0+<5V-_zDqZQN79?n?!Aj!Nj`YMO9?j>uqI9-Tex+nJD z%e0#Yca6(zqGUR|KITa?9x-#C0!JKJHO(+fy@1!B$%ZwJwncQW7vGYv?~!^`#L~Um zOL++>4qmqW`0Chc0T23G8|vO)tK=Z2`gvS4*qpqhIJCEv9i&&$09VO8YOz|oZ+ubd zNXVdLc&p=KsSgtmIPLN69P7xYkYQ1vJ?u1g)T!6Ru`k2wkdj*wDC)VryGu2=yb0?F z>q~~e>KZ0d_#7f3UgV%9MY1}vMgF{B8yfE{HL*pMyhYF)WDZ^^3vS8F zGlOhs%g_~pS3=WQ#494@jAXwOtr^Y|TnQ5zki>qRG)(oPY*f}U_=ip_{qB0!%w7~G zWE!P4p3khyW-JJnE>eECuYfI?^d366Shq!Wm#x&jAo>=HdCllE$>DPO0N;y#4G)D2y#B@5=N=+F%Xo2n{gKcPcK2!hP*^WSXl+ut; zyLvVoY>VL{H%Kd9^i~lsb8j4>$EllrparEOJNT?Ym>vJa$(P^tOG)5aVb_5w^*&M0 zYOJ`I`}9}UoSnYg#E(&yyK(tqr^@n}qU2H2DhkK-`2He% zgXr_4kpXoQHxAO9S`wEdmqGU4j=1JdG!OixdqB4PPP6RXA}>GM zumruUUH|ZG2$bBj)Qluj&uB=dRb)?^qomw?Z$X%#D+Q*O97eHrgVB2*mR$bFBU`*} zIem?dM)i}raTFDn@5^caxE^XFXVhBePmH9fqcTi`TLaXiueH=@06sl}>F%}h9H_e9 z>^O?LxM1EjX}NVppaO@NNQr=AtHcH-BU{yBT_vejJ#J)l^cl69Z7$sk`82Zyw7Wxt z=~J?hZm{f@W}|96FUJfy65Gk8?^{^yjhOahUMCNNpt5DJw}ZKH7b!bGiFY9y6OY&T z_N)?Jj(MuLTN36ZCJ6I5Xy7uVlrb$o*Z%=-)kPo9s?<^Yqz~!Z* z_mP8(unFq65XSi!$@YtieSQ!<7IEOaA9VkKI?lA`*(nURvfKL8cX}-+~uw9|_5)uC2`ZHcaeX7L8aG6Ghleg@F9aG%X$#g6^yP5apnB>YTz&EfS{q z9UVfSyEIczebC)qlVu5cOoMzS_jrC|)rQlAzK7sfiW0`M8mVIohazPE9Jzn*qPt%6 zZL8RELY@L09B83@Be;x5V-IHnn$}{RAT#<2JA%ttlk#^(%u}CGze|1JY5MPhbfnYG zIw%$XfBmA-<_pKLpGKwbRF$#P;@_)ech#>vj25sv25VM$ouo)?BXdRcO{)*OwTw)G zv43W~T6ekBMtUD%5Bm>`^Ltv!w4~65N!Ut5twl!Agrzyq4O2Fi3pUMtCU~>9gt_=h-f% z;1&OuSu?A_sJvIvQ+dZNo3?m1%b1+s&UAx?8sUHEe_sB7zkm4R%6)<@oYB_i5>3Ip zIA+?jVdX|zL{)?TGpx+=Ta>G80}0}Ax+722$XFNJsC1gcH56{8B)*)eU#r~HrC&}` z|EWW92&;6y;3}!L5zXa385@?-D%>dSvyK;?jqU2t_R3wvBW;$!j45uQ7tyEIQva;Db}r&bR3kqNSh)Q_$MJ#Uj3Gj1F;)sO|%6z#@<+ zi{pbYsYS#u`X$Nf($OS+lhw>xgjos1OnF^$-I$u;qhJswhH~p|ab*nO>zBrtb0ndn zxV0uh!LN`&xckTP+JW}gznSpU492)u+`f{9Yr)js`NmfYH#Wdtradc0TnKNz@Su!e zu$9}G_=ku;%4xk}eXl>)KgpuT>_<`Ud(A^a++K&pm3LbN;gI}ku@YVrA%FJBZ5$;m zobR8}OLtW4-i+qPPLS-(7<>M{)rhiPoi@?&vDeVq5%fmZk=mDdRV>Pb-l7pP1y6|J z8I>sF+TypKV=_^NwBU^>4JJq<*14GLfM2*XQzYdlqqjnE)gZsPW^E@mp&ww* zW9i>XL=uwLVZ9pO*8K>t>vdL~Ek_NUL$?LQi5sc#1Q-f6-ywKcIT8Kw?C(_3pbR`e|)%9S-({if|E+hR2W!&qfQ&UiF^I!|M#xhdWsenv^wpKCBiuxXbnp85`{i|;BM?Ba`lqTA zyRm=UWJl&E{8JzYDHFu>*Z10-?#A8D|5jW9Ho0*CAs0fAy~MqbwYuOq9jjt9*nuHI zbDwKvh)5Ir$r!fS5|;?Dt>V+@F*v8=TJJF)TdnC#Mk>+tGDGCw;A~^PC`gUt*<(|i zB{{g{`uFehu`$fm4)&k7`u{xIV)yvA(%5SxX9MS80p2EKnLtCZ>tlX>*Z6nd&6-Mv$5rHD*db;&IBK3KH&M<+ArlGXDRdX1VVO4)&R$f4NxXI>GBh zSv|h>5GDAI(4E`@F?EnW zS>#c&Gw6~_XL`qQG4bK`W*>hek4LX*efn6|_MY+rXkNyAuu?NxS%L7~9tD3cn7&p( zCtfqe6sjB&Q-Vs7BP5+%;#Gk};4xtwU!KY0XXbmkUy$kR9)!~?*v)qw00!+Yg^#H> zc#8*z6zZo>+(bud?K<*!QO4ehiTCK&PD4G&n)Tr9X_3r-we z?fI+}-G~Yn93gI6F{}Dw_SC*FLZ)5(85zp4%uubtD)J)UELLkvGk4#tw&Tussa)mTD$R2&O~{ zCI3>fr-!-b@EGRI%g0L8UU%%u_<;e9439JNV;4KSxd|78v+I+8^rmMf3f40Jb}wEszROD?xBZu>Ll3;sUIoNxDK3|j3*sam2tC@@e$ z^!;+AK>efeBJB%ALsQ{uFui)oDoq()2USi?n=6C3#eetz?wPswc={I<8x=(8lE4EIsUfyGNZ{|KYn1IR|=E==f z(;!A5(-2y^2xRFCSPqzHAZn5RCN_bp22T(KEtjA(rFZ%>a4@STrHZflxKoqe9Z4@^ zM*scx_y73?Q{vt6?~WEl?2q*;@8 z3M*&@%l)SQmXkcUm)d@GT2#JdzhfSAP9|n#C;$E8X|pwD!r#X?0P>0ZisQ~TNqupW z*lUY~+ikD`vQb?@SAWX#r*Y+;=_|oacL$2CL$^(mV}aKO77pg}O+-=T1oLBT5sL2i z42Qth2+0@C`c+*D0*5!qy26sis<9a7>LN2{z%Qj49t z=L@x`4$ALHb*3COHoT?5S_c(Hs}g!V>W^=6Q0}zaubkDn)(lTax0+!+%B}9Vqw6{H zvL|BRM`O<@;eVi1DzM!tXtBrA20Ce@^Jz|>%X-t`vi-%WweXCh_LhI#bUg2*pcP~R z*RuTUzBKLXO~~uMd&o$v3@d0shHfUjC6c539PE6rF&;Ufa(Rw@K1*m7?f5)t`MjH0 z)_V(cajV5Am>f!kWcI@5rE8t6$S>5M=k=aRZROH6fA^jJp~2NlR4;Q2>L$7F#RT#9 z>4@1RhWG`Khy>P2j1Yx^BBL{S`niMaxlSWV-JBU0-T9zZ%>7mR3l$~QV$({o0;jTI ze5=cN^!Bc2bT|BcojXp~K#2cM>OTe*cM{Kg-j*CkiW)EGQot^}s;cy8_1_@JA0Whq zlrNr+R;Efa+`6N)s5rH*|E)nYZ3uqkk2C(E7@A|3YI`ozP~9Lexx#*1(r8luq+YPk z{J}c$s` zPM35Fx(YWB3Z5IYnN+L_4|jaR(5iWJi2~l&xy}aU7kW?o-V*6Av2wyZTG!E2KSW2* zGRLQkQU;Oz##ie-Z4fI)WSRxn$(ZcD;TL+;^r=a4(G~H3ZhK$lSXZj?cvyY8%d9JM zzc3#pD^W_QnWy#rx#;c&N@sqHhrnHRmj#i;s%zLm6SE(n&BWpd&f7>XnjV}OlZntI70fq%8~9<7 zMYaw`E-rp49-oC1N_uZTo)Cu%RR2QWdHpzQIcNsoDp`3xfP+`gI?tVQZ4X={qU?(n zV>0ASES^Xuc;9JBji{)RnFL(Lez;8XbB1uWaMp@p?7xhXk6V#!6B@aP4Rz7-K%a>i z?fvf}va_DGUXlI#4--`A3qK7J?-HwnG7O~H2;zR~RLW)_^#La!=}+>KW#anZ{|^D3 B7G?kd literal 0 HcmV?d00001 diff --git a/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings.png b/docs/_static/bootstrap-2.3.2/img/glyphicons-halflings.png new file mode 100644 index 0000000000000000000000000000000000000000..a9969993201f9cee63cf9f49217646347297b643 GIT binary patch literal 12799 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 literal 0 HcmV?d00001 diff --git a/docs/_static/bootstrap-2.3.2/js/bootstrap.js b/docs/_static/bootstrap-2.3.2/js/bootstrap.js new file mode 100644 index 00000000..638bb187 --- /dev/null +++ b/docs/_static/bootstrap-2.3.2/js/bootstrap.js @@ -0,0 +1,2287 @@ +/* =================================================== + * bootstrap-transition.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#transitions + * =================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) + * ======================================================= */ + + $(function () { + + $.support.transition = (function () { + + var transitionEnd = (function () { + + var el = document.createElement('bootstrap') + , transEndEventNames = { + 'WebkitTransition' : 'webkitTransitionEnd' + , 'MozTransition' : 'transitionend' + , 'OTransition' : 'oTransitionEnd otransitionend' + , 'transition' : 'transitionend' + } + , name + + for (name in transEndEventNames){ + if (el.style[name] !== undefined) { + return transEndEventNames[name] + } + } + + }()) + + return transitionEnd && { + end: transitionEnd + } + + })() + + }) + +}(window.$jqTheme || window.jQuery); +/* ========================================================== + * bootstrap-alert.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#alerts + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* ALERT CLASS DEFINITION + * ====================== */ + + var dismiss = '[data-dismiss="alert"]' + , Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype.close = function (e) { + var $this = $(this) + , selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = $(selector) + + e && e.preventDefault() + + $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) + + $parent.trigger(e = $.Event('close')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + $parent + .trigger('closed') + .remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent.on($.support.transition.end, removeElement) : + removeElement() + } + + + /* ALERT PLUGIN DEFINITION + * ======================= */ + + var old = $.fn.alert + + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('alert') + if (!data) $this.data('alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + /* ALERT NO CONFLICT + * ================= */ + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + /* ALERT DATA-API + * ============== */ + + $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) + +}(window.$jqTheme || window.jQuery); +/* ============================================================ + * bootstrap-button.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#buttons + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* BUTTON PUBLIC CLASS DEFINITION + * ============================== */ + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.button.defaults, options) + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + , $el = this.$element + , data = $el.data() + , val = $el.is('input') ? 'val' : 'html' + + state = state + 'Text' + data.resetText || $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout(function () { + state == 'loadingText' ? + $el.addClass(d).attr(d, d) : + $el.removeClass(d).removeAttr(d) + }, 0) + } + + Button.prototype.toggle = function () { + var $parent = this.$element.closest('[data-toggle="buttons-radio"]') + + $parent && $parent + .find('.active') + .removeClass('active') + + this.$element.toggleClass('active') + } + + + /* BUTTON PLUGIN DEFINITION + * ======================== */ + + var old = $.fn.button + + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('button') + , options = typeof option == 'object' && option + if (!data) $this.data('button', (data = new Button(this, options))) + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.defaults = { + loadingText: 'loading...' + } + + $.fn.button.Constructor = Button + + + /* BUTTON NO CONFLICT + * ================== */ + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + /* BUTTON DATA-API + * =============== */ + + $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + }) + +}(window.$jqTheme || window.jQuery); +/* ========================================================== + * bootstrap-carousel.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#carousel + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CAROUSEL CLASS DEFINITION + * ========================= */ + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } + + Carousel.prototype = { + + cycle: function (e) { + if (!e) this.paused = false + if (this.interval) clearInterval(this.interval); + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + return this + } + + , getActiveIndex: function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() + return this.$items.index(this.$active) + } + + , to: function (pos) { + var activeIndex = this.getActiveIndex() + , that = this + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) { + return this.$element.one('slid', function () { + that.to(pos) + }) + } + + if (activeIndex == pos) { + return this.pause().cycle() + } + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } + + , pause: function (e) { + if (!e) this.paused = true + if (this.$element.find('.next, .prev').length && $.support.transition.end) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + clearInterval(this.interval) + this.interval = null + return this + } + + , next: function () { + if (this.sliding) return + return this.slide('next') + } + + , prev: function () { + if (this.sliding) return + return this.slide('prev') + } + + , slide: function (type, next) { + var $active = this.$element.find('.item.active') + , $next = next || $active[type]() + , isCycling = this.interval + , direction = type == 'next' ? 'left' : 'right' + , fallback = type == 'next' ? 'first' : 'last' + , that = this + , e + + this.sliding = true + + isCycling && this.pause() + + $next = $next.length ? $next : this.$element.find('.item')[fallback]() + + e = $.Event('slide', { + relatedTarget: $next[0] + , direction: direction + }) + + if ($next.hasClass('active')) return + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + + if ($.support.transition && this.$element.hasClass('slide')) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + this.$element.one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { that.$element.trigger('slid') }, 0) + }) + } else { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid') + } + + isCycling && this.cycle() + + return this + } + + } + + + /* CAROUSEL PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('carousel') + , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) + , action = typeof option == 'string' ? option : options.slide + if (!data) $this.data('carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + $.fn.carousel.defaults = { + interval: 5000 + , pause: 'hover' + } + + $.fn.carousel.Constructor = Carousel + + + /* CAROUSEL NO CONFLICT + * ==================== */ + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + /* CAROUSEL DATA-API + * ================= */ + + $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + , options = $.extend({}, $target.data(), $this.data()) + , slideIndex + + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('carousel').pause().to(slideIndex).cycle() + } + + e.preventDefault() + }) + +}(window.$jqTheme || window.jQuery); +/* ============================================================= + * bootstrap-collapse.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#collapse + * ============================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* COLLAPSE PUBLIC CLASS DEFINITION + * ================================ */ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.collapse.defaults, options) + + if (this.options.parent) { + this.$parent = $(this.options.parent) + } + + this.options.toggle && this.toggle() + } + + Collapse.prototype = { + + constructor: Collapse + + , dimension: function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + , show: function () { + var dimension + , scroll + , actives + , hasData + + if (this.transitioning || this.$element.hasClass('in')) return + + dimension = this.dimension() + scroll = $.camelCase(['scroll', dimension].join('-')) + actives = this.$parent && this.$parent.find('> .accordion-group > .in') + + if (actives && actives.length) { + hasData = actives.data('collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('collapse', null) + } + + this.$element[dimension](0) + this.transition('addClass', $.Event('show'), 'shown') + $.support.transition && this.$element[dimension](this.$element[0][scroll]) + } + + , hide: function () { + var dimension + if (this.transitioning || !this.$element.hasClass('in')) return + dimension = this.dimension() + this.reset(this.$element[dimension]()) + this.transition('removeClass', $.Event('hide'), 'hidden') + this.$element[dimension](0) + } + + , reset: function (size) { + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + [dimension](size || 'auto') + [0].offsetWidth + + this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') + + return this + } + + , transition: function (method, startEvent, completeEvent) { + var that = this + , complete = function () { + if (startEvent.type == 'show') that.reset() + that.transitioning = 0 + that.$element.trigger(completeEvent) + } + + this.$element.trigger(startEvent) + + if (startEvent.isDefaultPrevented()) return + + this.transitioning = 1 + + this.$element[method]('in') + + $.support.transition && this.$element.hasClass('collapse') ? + this.$element.one($.support.transition.end, complete) : + complete() + } + + , toggle: function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + } + + + /* COLLAPSE PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('collapse') + , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.defaults = { + toggle: true + } + + $.fn.collapse.Constructor = Collapse + + + /* COLLAPSE NO CONFLICT + * ==================== */ + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + /* COLLAPSE DATA-API + * ================= */ + + $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + , target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + , option = $(target).data('collapse') ? 'toggle' : $this.data() + $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + $(target).collapse(option) + }) + +}(window.$jqTheme || window.jQuery); +/* ============================================================ + * bootstrap-dropdown.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#dropdowns + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle=dropdown]' + , Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown + + , toggle: function (e) { + var $this = $(this) + , $parent + , isActive + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement) { + // if mobile we we use a backdrop because click events don't delegate + $('