honeybee-core 1.63.0__tar.gz → 1.64.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {honeybee_core-1.63.0/honeybee_core.egg-info → honeybee_core-1.64.0}/PKG-INFO +1 -1
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/model.py +155 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/room.py +192 -84
- {honeybee_core-1.63.0 → honeybee_core-1.64.0/honeybee_core.egg-info}/PKG-INFO +1 -1
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/.github/workflows/ci.yaml +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/.github/workflows/dependency-release.yaml +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/.gitignore +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/.releaserc.json +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/CODE_OF_CONDUCT.md +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/CONTRIBUTING.md +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/LICENSE +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/MANIFEST.in +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/README.md +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/deploy.sh +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/dev-requirements.txt +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/docs/_build/.nojekyll +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/docs/_build/README.md +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/docs/_build/docs/README.md +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/docs/_static/custom.css +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/docs/_templates/layout.html +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/docs/cli/index.rst +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/docs/conf.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/docs/index.rst +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/__init__.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/__main__.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/_base.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/_basewithshade.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/_lockable.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/altnumber.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/aperture.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/boundarycondition.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/checkdup.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/cli/__init__.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/cli/compare.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/cli/create.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/cli/edit.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/cli/lib.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/cli/setconfig.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/cli/validate.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/colorobj.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/config.json +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/config.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/dictutil.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/door.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/extensionutil.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/face.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/facetype.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/logutil.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/orientation.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/properties.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/search.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/shade.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/shademesh.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/typing.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/units.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/writer/__init__.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/writer/aperture.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/writer/door.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/writer/face.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/writer/model.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/writer/room.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/writer/shade.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee/writer/shademesh.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee_core.egg-info/SOURCES.txt +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee_core.egg-info/dependency_links.txt +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee_core.egg-info/entry_points.txt +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee_core.egg-info/requires.txt +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/honeybee_core.egg-info/top_level.txt +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/requirements.txt +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/setup.cfg +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/setup.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/__init__.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/aperture_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/boundary_condition_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/cli_compare_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/cli_create_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/cli_edit_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/cli_validate_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/colorobj_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/config_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/dictutil_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/door_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/face_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/facetype_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/ShoeBox.json +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/bad_geometry_model.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/colliding_room_volumes.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/compare_model_1.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/compare_model_2.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/complex_polyfaces.json +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/minor_geometry/existing_model.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/minor_geometry/updated_model.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/mismatched_area_adj.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/model_with_adiabatic.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/model_with_holes.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/model_without_adjacency.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/nonascii_face.json +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/polygons_for_gap_boundary.json +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/room_for_window_offset.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/single_family_home.hbjson +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/lockable_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/model_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/orientation_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/room_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/search_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/shade_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/shademesh_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/stl/cube_ascii.stl +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/stl/cube_binary.stl +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/typing_test.py +0 -0
- {honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/units_test.py +0 -0
|
@@ -107,6 +107,18 @@ class Model(_Base):
|
|
|
107
107
|
* exterior_skylight_aperture_area
|
|
108
108
|
* min
|
|
109
109
|
* max
|
|
110
|
+
* roof_to_exterior_edges
|
|
111
|
+
* slab_to_exterior_edges
|
|
112
|
+
* exposed_floor_to_exterior_wall_edges
|
|
113
|
+
* exterior_wall_to_wall_edges
|
|
114
|
+
* roof_ridge_edges
|
|
115
|
+
* exposed_floor_to_floor_edges
|
|
116
|
+
* underground_edges
|
|
117
|
+
* interior_edges
|
|
118
|
+
* exterior_aperture_edges
|
|
119
|
+
* exterior_door_edges
|
|
120
|
+
* exterior_aperture_edges
|
|
121
|
+
* exterior_door_edges
|
|
110
122
|
* top_level_dict
|
|
111
123
|
* user_data
|
|
112
124
|
"""
|
|
@@ -1014,6 +1026,92 @@ class Model(_Base):
|
|
|
1014
1026
|
"""Get a Point3D for the max bounding box vertex in the XY plane."""
|
|
1015
1027
|
return self._calculate_max(self._all_objects())
|
|
1016
1028
|
|
|
1029
|
+
@property
|
|
1030
|
+
def roof_to_exterior_edges(self):
|
|
1031
|
+
"""Get LineSegment3Ds where roofs meet exterior walls (or floors).
|
|
1032
|
+
|
|
1033
|
+
Note that both the roof Face and the wall/floor Face must be next to one
|
|
1034
|
+
another in the model's outer envelope and have outdoor boundary conditions for
|
|
1035
|
+
the edge to show up in this list.
|
|
1036
|
+
"""
|
|
1037
|
+
return self.classified_envelope_edges()[0]
|
|
1038
|
+
|
|
1039
|
+
@property
|
|
1040
|
+
def slab_to_exterior_edges(self):
|
|
1041
|
+
"""Get LineSegment3Ds where ground floor slabs meet exterior walls or roofs.
|
|
1042
|
+
|
|
1043
|
+
Note that the floor Face must have a ground boundary condition and the wall or
|
|
1044
|
+
roof Face must have an outdoor boundary condition for the edge between the
|
|
1045
|
+
two Faces to show up in this list.
|
|
1046
|
+
"""
|
|
1047
|
+
return self.classified_envelope_edges()[1]
|
|
1048
|
+
|
|
1049
|
+
@property
|
|
1050
|
+
def exposed_floor_to_exterior_wall_edges(self):
|
|
1051
|
+
"""Get LineSegment3Ds where exposed floors meet exterior walls.
|
|
1052
|
+
|
|
1053
|
+
Note that both the wall Face and the floor Face must be next to one
|
|
1054
|
+
another in the model's outer envelope and have outdoor boundary conditions for
|
|
1055
|
+
the edge to show up in this list.
|
|
1056
|
+
"""
|
|
1057
|
+
return self.classified_envelope_edges()[2]
|
|
1058
|
+
|
|
1059
|
+
@property
|
|
1060
|
+
def exterior_wall_to_wall_edges(self):
|
|
1061
|
+
"""Get LineSegment3Ds where exterior walls meet one another.
|
|
1062
|
+
|
|
1063
|
+
Note that both wall Faces must be next to one another in the model's
|
|
1064
|
+
outer envelope and have outdoor boundary conditions for the edge to
|
|
1065
|
+
show up in this list.
|
|
1066
|
+
"""
|
|
1067
|
+
return self.classified_envelope_edges()[3]
|
|
1068
|
+
|
|
1069
|
+
@property
|
|
1070
|
+
def roof_ridge_edges(self):
|
|
1071
|
+
"""Get a list of LineSegment3D where exterior roofs meet one another.
|
|
1072
|
+
|
|
1073
|
+
Note that both roof Faces must be next to one another in the model's
|
|
1074
|
+
outer envelope and have outdoor boundary conditions for the edge to
|
|
1075
|
+
show up in this list.
|
|
1076
|
+
"""
|
|
1077
|
+
return self.classified_envelope_edges()[4]
|
|
1078
|
+
|
|
1079
|
+
@property
|
|
1080
|
+
def exposed_floor_to_floor_edges(self):
|
|
1081
|
+
"""Get LineSegment3Ds where exposed floors meet one another.
|
|
1082
|
+
|
|
1083
|
+
Note that both floor Faces must be next to one another in the model's
|
|
1084
|
+
outer envelope and have outdoor boundary conditions for the edge to
|
|
1085
|
+
show up in this list.
|
|
1086
|
+
"""
|
|
1087
|
+
return self.classified_envelope_edges()[5]
|
|
1088
|
+
|
|
1089
|
+
@property
|
|
1090
|
+
def underground_edges(self):
|
|
1091
|
+
"""Get a list of LineSegment3D where underground Faces meet one another.
|
|
1092
|
+
|
|
1093
|
+
Note that both Faces must be next to one another in the model's outer envelope
|
|
1094
|
+
and have ground boundary conditions for the edge to show up in this list.
|
|
1095
|
+
"""
|
|
1096
|
+
return self.classified_envelope_edges()[6]
|
|
1097
|
+
|
|
1098
|
+
@property
|
|
1099
|
+
def exterior_aperture_edges(self):
|
|
1100
|
+
"""Get a list of LineSegment3D for the borders around room exterior apertures.
|
|
1101
|
+
"""
|
|
1102
|
+
edges = []
|
|
1103
|
+
for room in self.rooms:
|
|
1104
|
+
edges.extend(room.exterior_aperture_edges)
|
|
1105
|
+
return edges
|
|
1106
|
+
|
|
1107
|
+
@property
|
|
1108
|
+
def exterior_door_edges(self):
|
|
1109
|
+
"""Get a list of LineSegment3D for the borders around room exterior doors."""
|
|
1110
|
+
edges = []
|
|
1111
|
+
for room in self.rooms:
|
|
1112
|
+
edges.extend(room.exterior_door_edges)
|
|
1113
|
+
return edges
|
|
1114
|
+
|
|
1017
1115
|
@property
|
|
1018
1116
|
def top_level_dict(self):
|
|
1019
1117
|
"""Get dictionary of top-level model objects with identifiers as the keys.
|
|
@@ -1378,6 +1476,63 @@ class Model(_Base):
|
|
|
1378
1476
|
)
|
|
1379
1477
|
return shades
|
|
1380
1478
|
|
|
1479
|
+
def classified_envelope_edges(self, tolerance=None, exclude_coplanar=False):
|
|
1480
|
+
"""Get classified edges of this Model's envelope based on Faces they adjoin.
|
|
1481
|
+
|
|
1482
|
+
The edges returned by this method will only exist along the exterior
|
|
1483
|
+
envelope of the Model's Rooms as defined by the contiguous volume across
|
|
1484
|
+
all Room interior adjacencies.
|
|
1485
|
+
|
|
1486
|
+
Args:
|
|
1487
|
+
tolerance: The maximum difference between point values for them to be
|
|
1488
|
+
considered equivalent. If None, the Model's tolerance will be used.
|
|
1489
|
+
exclude_coplanar: Boolean to note whether edges falling between two
|
|
1490
|
+
coplanar Faces in the building envelope should be included
|
|
1491
|
+
in the result (False) or excluded from it (True). (Default: False).
|
|
1492
|
+
|
|
1493
|
+
Returns:
|
|
1494
|
+
A tuple with eight items where each item is a list containing
|
|
1495
|
+
LineSegment3D adjoining different types of Faces.
|
|
1496
|
+
|
|
1497
|
+
- roof_to_exterior - Roofs meet exterior walls or floors.
|
|
1498
|
+
|
|
1499
|
+
- slab_to_exterior - Ground floor slabs meet exterior walls or roofs.
|
|
1500
|
+
|
|
1501
|
+
- exposed_floor_to_exterior_wall - Exposed floors meet exterior walls.
|
|
1502
|
+
|
|
1503
|
+
- exterior_wall_to_wall - Exterior walls meet.
|
|
1504
|
+
|
|
1505
|
+
- roof_ridge - Exterior roofs meet.
|
|
1506
|
+
|
|
1507
|
+
- exposed_floor_to_floor - Exposed floors meet.
|
|
1508
|
+
|
|
1509
|
+
- underground - Underground faces meet.
|
|
1510
|
+
"""
|
|
1511
|
+
# set up lists to be populated
|
|
1512
|
+
roof_to_exterior, slab_to_exterior, exposed_floor_to_exterior_wall = [], [], []
|
|
1513
|
+
exterior_wall_to_wall, roof_ridge, exposed_floor_to_floor = [], [], []
|
|
1514
|
+
underground, interior = [], []
|
|
1515
|
+
tol = tolerance if tolerance else self.tolerance
|
|
1516
|
+
ang_tol = self.angle_tolerance if exclude_coplanar else None
|
|
1517
|
+
|
|
1518
|
+
# join all of the rooms in the model across their adjacencies
|
|
1519
|
+
merged_rooms = Room.join_adjacent_rooms(self.rooms, tol)
|
|
1520
|
+
for room in merged_rooms:
|
|
1521
|
+
rf_to_ext, slb_to_ext, ex_flr_to_ext, ext_wl_to_wl, rf_ridge, \
|
|
1522
|
+
ex_flr_to_flr, under_gnd, inter = room.classified_edges(tol, ang_tol)
|
|
1523
|
+
roof_to_exterior.extend(rf_to_ext)
|
|
1524
|
+
slab_to_exterior.extend(slb_to_ext)
|
|
1525
|
+
exposed_floor_to_exterior_wall.extend(ex_flr_to_ext)
|
|
1526
|
+
exterior_wall_to_wall.extend(ext_wl_to_wl)
|
|
1527
|
+
roof_ridge.extend(rf_ridge)
|
|
1528
|
+
exposed_floor_to_floor.extend(ex_flr_to_flr)
|
|
1529
|
+
underground.extend(under_gnd)
|
|
1530
|
+
interior.extend(inter)
|
|
1531
|
+
|
|
1532
|
+
# return the classified edges
|
|
1533
|
+
return roof_to_exterior, slab_to_exterior, exposed_floor_to_exterior_wall, \
|
|
1534
|
+
exterior_wall_to_wall, roof_ridge, exposed_floor_to_floor, underground
|
|
1535
|
+
|
|
1381
1536
|
def add_prefix(self, prefix):
|
|
1382
1537
|
"""Change the identifier of this object and child objects by inserting a prefix.
|
|
1383
1538
|
|
|
@@ -8,6 +8,7 @@ import uuid
|
|
|
8
8
|
from ladybug_geometry.geometry2d import Point2D, Vector2D, Polygon2D
|
|
9
9
|
from ladybug_geometry.geometry3d import Point3D, Vector3D, Ray3D, Plane, Face3D, \
|
|
10
10
|
Mesh3D, Polyface3D
|
|
11
|
+
from ladybug_geometry.bounding import overlapping_bounding_boxes
|
|
11
12
|
from ladybug_geometry_polyskel.polysplit import perimeter_core_subpolygons
|
|
12
13
|
|
|
13
14
|
import honeybee.writer.room as writer
|
|
@@ -71,6 +72,8 @@ class Room(_BaseWithShade):
|
|
|
71
72
|
* center
|
|
72
73
|
* min
|
|
73
74
|
* max
|
|
75
|
+
* exterior_aperture_edges
|
|
76
|
+
* exterior_door_edges
|
|
74
77
|
* volume
|
|
75
78
|
* floor_area
|
|
76
79
|
* exposed_area
|
|
@@ -430,6 +433,24 @@ class Room(_BaseWithShade):
|
|
|
430
433
|
all_geo.extend(self._faces)
|
|
431
434
|
return self._calculate_max(all_geo)
|
|
432
435
|
|
|
436
|
+
@property
|
|
437
|
+
def exterior_aperture_edges(self):
|
|
438
|
+
"""Get a list of LineSegment3D for the borders around exterior apertures."""
|
|
439
|
+
edges = []
|
|
440
|
+
for ap in self.apertures:
|
|
441
|
+
if isinstance(ap.boundary_condition, Outdoors):
|
|
442
|
+
edges.extend(ap.geometry.segments)
|
|
443
|
+
return edges
|
|
444
|
+
|
|
445
|
+
@property
|
|
446
|
+
def exterior_door_edges(self):
|
|
447
|
+
"""Get a list of LineSegment3D for the borders around exterior doors."""
|
|
448
|
+
edges = []
|
|
449
|
+
for dr in self.doors:
|
|
450
|
+
if isinstance(dr.boundary_condition, Outdoors):
|
|
451
|
+
edges.extend(dr.geometry.segments)
|
|
452
|
+
return edges
|
|
453
|
+
|
|
433
454
|
@property
|
|
434
455
|
def volume(self):
|
|
435
456
|
"""Get the volume of the room.
|
|
@@ -584,101 +605,92 @@ class Room(_BaseWithShade):
|
|
|
584
605
|
areas += face.area
|
|
585
606
|
return orientations / areas if areas != 0 else None
|
|
586
607
|
|
|
587
|
-
def
|
|
588
|
-
"""
|
|
589
|
-
|
|
590
|
-
This is particularly useful in workflows where you duplicate and edit
|
|
591
|
-
a starting object and then want to combine it with the original object
|
|
592
|
-
into one Model (like making a model of repeated rooms) since all objects
|
|
593
|
-
within a Model must have unique identifiers.
|
|
608
|
+
def classified_edges(self, tolerance=0.01, angle_tolerance=None):
|
|
609
|
+
"""Get classified edges of this Room's Polyface3D based on Faces they adjoin.
|
|
594
610
|
|
|
595
611
|
Args:
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
self._identifier = clean_string('{}_{}'.format(prefix, self.identifier))
|
|
602
|
-
self.display_name = '{}_{}'.format(prefix, self.display_name)
|
|
603
|
-
self.properties.add_prefix(prefix)
|
|
604
|
-
for face in self._faces:
|
|
605
|
-
face.add_prefix(prefix)
|
|
606
|
-
self._add_prefix_shades(prefix)
|
|
612
|
+
tolerance: The maximum difference between point values for them to be
|
|
613
|
+
considered equivalent. (Default: 0.01, suitable for objects in meters).
|
|
614
|
+
angle_tolerance: An optional value in degrees, which can be used to
|
|
615
|
+
exclude edges falling between coplanar Faces. If None, edges falling
|
|
616
|
+
between coplanar Faces will be included. (Default: None).
|
|
607
617
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
"""Set the display name of this Room using a format string with Room attributes.
|
|
618
|
+
Returns:
|
|
619
|
+
A tuple with eight items where each item is a list containing
|
|
620
|
+
LineSegment3D adjoining different types of Faces.
|
|
612
621
|
|
|
613
|
-
|
|
614
|
-
format_str: Text string for the pattern with which the Room will be
|
|
615
|
-
renamed. Any property on this class may be used (eg. story)
|
|
616
|
-
and each property should be put in curly brackets. Nested
|
|
617
|
-
properties can be specified by using "." to denote nesting levels
|
|
618
|
-
(eg. properties.energy.program_type.display_name). Functions that
|
|
619
|
-
return string outputs can also be passed here as long as these
|
|
620
|
-
functions defaults specified for all arguments.
|
|
621
|
-
"""
|
|
622
|
-
matches = re.findall(r'{([^}]*)}', format_str)
|
|
623
|
-
attributes = [get_attr_nested(self, m) for m in matches]
|
|
624
|
-
for attr_name, attr_val in zip(matches, attributes):
|
|
625
|
-
format_str = format_str.replace('{{{}}}'.format(attr_name), attr_val)
|
|
626
|
-
self.display_name = format_str
|
|
627
|
-
return format_str
|
|
622
|
+
- roof_to_exterior - Roofs meet exterior walls or floors.
|
|
628
623
|
|
|
629
|
-
|
|
630
|
-
self,
|
|
631
|
-
format_str='{parent.display_name} - {gbxml_type} - {cardinal_direction}'
|
|
632
|
-
):
|
|
633
|
-
"""Set the display name for all of this Room's faces using a format string.
|
|
624
|
+
- slab_to_exterior - Ground floor slabs meet exterior walls or roofs.
|
|
634
625
|
|
|
635
|
-
|
|
636
|
-
format_str: Text string for the pattern with which the faces will be
|
|
637
|
-
renamed. Any property of the Face class may be used (eg. gbxml_str)
|
|
638
|
-
and each property should be put in curly brackets. Nested
|
|
639
|
-
properties can be specified by using "." to denote nesting levels
|
|
640
|
-
(eg. properties.energy.construction.display_name). Functions that
|
|
641
|
-
return string outputs can also be passed here as long as these
|
|
642
|
-
functions defaults specified for all arguments.
|
|
643
|
-
"""
|
|
644
|
-
for face in self.faces:
|
|
645
|
-
face.rename_by_attribute(format_str)
|
|
626
|
+
- exposed_floor_to_exterior_wall - Exposed floors meet exterior walls.
|
|
646
627
|
|
|
647
|
-
|
|
648
|
-
self,
|
|
649
|
-
format_str='{parent.parent.display_name} - {gbxml_type} - {cardinal_direction}'
|
|
650
|
-
):
|
|
651
|
-
"""Set the display name for all of this Room's apertures using a format string.
|
|
628
|
+
- exterior_wall_to_wall - Exterior walls meet.
|
|
652
629
|
|
|
653
|
-
|
|
654
|
-
format_str: Text string for the pattern with which the apertures will be
|
|
655
|
-
renamed. Any property on the Aperture class may be used (eg. gbxml_str)
|
|
656
|
-
and each property should be put in curly brackets. Nested
|
|
657
|
-
properties can be specified by using "." to denote nesting levels
|
|
658
|
-
(eg. properties.energy.construction.display_name). Functions that
|
|
659
|
-
return string outputs can also be passed here as long as these
|
|
660
|
-
functions defaults specified for all arguments.
|
|
661
|
-
"""
|
|
662
|
-
for ap in self.apertures:
|
|
663
|
-
ap.rename_by_attribute(format_str)
|
|
630
|
+
- roof_ridge - Exterior roofs meet.
|
|
664
631
|
|
|
665
|
-
|
|
666
|
-
self,
|
|
667
|
-
format_str='{parent.parent.display_name} - {energyplus_type} - {cardinal_direction}'
|
|
668
|
-
):
|
|
669
|
-
"""Set the display name for all of this Room's doors using a format string.
|
|
632
|
+
- exposed_floor_to_floor - Exposed floors meet.
|
|
670
633
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
and each property should be put in curly brackets. Nested
|
|
675
|
-
properties can be specified by using "." to denote nesting levels
|
|
676
|
-
(eg. properties.energy.construction.display_name). Functions that
|
|
677
|
-
return string outputs can also be passed here as long as these
|
|
678
|
-
functions defaults specified for all arguments.
|
|
634
|
+
- underground - Underground faces meet.
|
|
635
|
+
|
|
636
|
+
- interior - Interior faces meet.
|
|
679
637
|
"""
|
|
680
|
-
|
|
681
|
-
|
|
638
|
+
# set up lists to be populated
|
|
639
|
+
roof_to_exterior, slab_to_exterior, exposed_floor_to_exterior_wall = [], [], []
|
|
640
|
+
exterior_wall_to_wall, roof_ridge, exposed_floor_to_floor = [], [], []
|
|
641
|
+
underground, interior = [], []
|
|
642
|
+
|
|
643
|
+
# get all of the edges and map them to room faces
|
|
644
|
+
edges = self.geometry.internal_edges
|
|
645
|
+
edge_faces = [[] for _ in edges]
|
|
646
|
+
for i, edge in enumerate(edges):
|
|
647
|
+
for face in self.faces:
|
|
648
|
+
if overlapping_bounding_boxes(face.geometry, edge, tolerance):
|
|
649
|
+
for f_edge in face.geometry.segments:
|
|
650
|
+
if edge.distance_to_point(f_edge.p1) < tolerance and \
|
|
651
|
+
edge.distance_to_point(f_edge.p2) < tolerance:
|
|
652
|
+
edge_faces[i].append(face)
|
|
653
|
+
break
|
|
654
|
+
|
|
655
|
+
# classify the edges by analyzing the faces they adjoin
|
|
656
|
+
for edge, faces in zip(edges, edge_faces):
|
|
657
|
+
# first check for cases where the edge should be excluded
|
|
658
|
+
if len(edge_faces) <= 1: # not an edge between two faces
|
|
659
|
+
continue
|
|
660
|
+
if angle_tolerance is not None:
|
|
661
|
+
ang_tol = math.radians(angle_tolerance)
|
|
662
|
+
base_normal = faces[0].normal
|
|
663
|
+
if all(f.normal.angle(base_normal) < ang_tol for f in faces[1:]):
|
|
664
|
+
continue
|
|
665
|
+
|
|
666
|
+
# then check for which category the edge should go into
|
|
667
|
+
ext_faces = [f for f in faces if isinstance(f.boundary_condition, Outdoors)
|
|
668
|
+
and not isinstance(f.type, AirBoundary)]
|
|
669
|
+
if len(ext_faces) >= 2: # some type of exterior edge
|
|
670
|
+
if all(isinstance(f.type, Wall) for f in ext_faces):
|
|
671
|
+
exterior_wall_to_wall.append(edge)
|
|
672
|
+
elif all(isinstance(f.type, RoofCeiling) for f in ext_faces):
|
|
673
|
+
roof_ridge.append(edge)
|
|
674
|
+
elif all(isinstance(f.type, Floor) for f in ext_faces):
|
|
675
|
+
exposed_floor_to_floor.append(edge)
|
|
676
|
+
elif any(isinstance(f.type, RoofCeiling) for f in ext_faces):
|
|
677
|
+
roof_to_exterior.append(edge)
|
|
678
|
+
elif any(isinstance(f.type, Floor) for f in ext_faces):
|
|
679
|
+
exposed_floor_to_exterior_wall.append(edge)
|
|
680
|
+
else:
|
|
681
|
+
gnd_faces = [f for f in faces if isinstance(f.boundary_condition, Ground)
|
|
682
|
+
and not isinstance(f.type, AirBoundary)]
|
|
683
|
+
if len(ext_faces) >= 1 and len(gnd_faces) >= 1:
|
|
684
|
+
slab_to_exterior.append(edge)
|
|
685
|
+
elif len(gnd_faces) >= 2: # some type of underground edge
|
|
686
|
+
underground.append(edge)
|
|
687
|
+
else: # some type of interior edge
|
|
688
|
+
interior.append(edge)
|
|
689
|
+
|
|
690
|
+
# return the classified edges
|
|
691
|
+
return roof_to_exterior, slab_to_exterior, exposed_floor_to_exterior_wall, \
|
|
692
|
+
exterior_wall_to_wall, roof_ridge, exposed_floor_to_floor, \
|
|
693
|
+
underground, interior
|
|
682
694
|
|
|
683
695
|
def horizontal_boundary(self, match_walls=False, tolerance=0.01):
|
|
684
696
|
"""Get a Face3D representing the horizontal boundary around the Room.
|
|
@@ -774,6 +786,102 @@ class Room(_BaseWithShade):
|
|
|
774
786
|
return self._match_walls_to_horizontal_faces(horiz_bound, tolerance)
|
|
775
787
|
return horiz_bound
|
|
776
788
|
|
|
789
|
+
def add_prefix(self, prefix):
|
|
790
|
+
"""Change the identifier of this object and child objects by inserting a prefix.
|
|
791
|
+
|
|
792
|
+
This is particularly useful in workflows where you duplicate and edit
|
|
793
|
+
a starting object and then want to combine it with the original object
|
|
794
|
+
into one Model (like making a model of repeated rooms) since all objects
|
|
795
|
+
within a Model must have unique identifiers.
|
|
796
|
+
|
|
797
|
+
Args:
|
|
798
|
+
prefix: Text that will be inserted at the start of this object's
|
|
799
|
+
(and child objects') identifier and display_name. It is recommended
|
|
800
|
+
that this prefix be short to avoid maxing out the 100 allowable
|
|
801
|
+
characters for honeybee identifiers.
|
|
802
|
+
"""
|
|
803
|
+
self._identifier = clean_string('{}_{}'.format(prefix, self.identifier))
|
|
804
|
+
self.display_name = '{}_{}'.format(prefix, self.display_name)
|
|
805
|
+
self.properties.add_prefix(prefix)
|
|
806
|
+
for face in self._faces:
|
|
807
|
+
face.add_prefix(prefix)
|
|
808
|
+
self._add_prefix_shades(prefix)
|
|
809
|
+
|
|
810
|
+
def rename_by_attribute(
|
|
811
|
+
self, format_str='{story} - {display_name}'
|
|
812
|
+
):
|
|
813
|
+
"""Set the display name of this Room using a format string with Room attributes.
|
|
814
|
+
|
|
815
|
+
Args:
|
|
816
|
+
format_str: Text string for the pattern with which the Room will be
|
|
817
|
+
renamed. Any property on this class may be used (eg. story)
|
|
818
|
+
and each property should be put in curly brackets. Nested
|
|
819
|
+
properties can be specified by using "." to denote nesting levels
|
|
820
|
+
(eg. properties.energy.program_type.display_name). Functions that
|
|
821
|
+
return string outputs can also be passed here as long as these
|
|
822
|
+
functions defaults specified for all arguments.
|
|
823
|
+
"""
|
|
824
|
+
matches = re.findall(r'{([^}]*)}', format_str)
|
|
825
|
+
attributes = [get_attr_nested(self, m) for m in matches]
|
|
826
|
+
for attr_name, attr_val in zip(matches, attributes):
|
|
827
|
+
format_str = format_str.replace('{{{}}}'.format(attr_name), attr_val)
|
|
828
|
+
self.display_name = format_str
|
|
829
|
+
return format_str
|
|
830
|
+
|
|
831
|
+
def rename_faces_by_attribute(
|
|
832
|
+
self,
|
|
833
|
+
format_str='{parent.display_name} - {gbxml_type} - {cardinal_direction}'
|
|
834
|
+
):
|
|
835
|
+
"""Set the display name for all of this Room's faces using a format string.
|
|
836
|
+
|
|
837
|
+
Args:
|
|
838
|
+
format_str: Text string for the pattern with which the faces will be
|
|
839
|
+
renamed. Any property of the Face class may be used (eg. gbxml_str)
|
|
840
|
+
and each property should be put in curly brackets. Nested
|
|
841
|
+
properties can be specified by using "." to denote nesting levels
|
|
842
|
+
(eg. properties.energy.construction.display_name). Functions that
|
|
843
|
+
return string outputs can also be passed here as long as these
|
|
844
|
+
functions defaults specified for all arguments.
|
|
845
|
+
"""
|
|
846
|
+
for face in self.faces:
|
|
847
|
+
face.rename_by_attribute(format_str)
|
|
848
|
+
|
|
849
|
+
def rename_apertures_by_attribute(
|
|
850
|
+
self,
|
|
851
|
+
format_str='{parent.parent.display_name} - {gbxml_type} - {cardinal_direction}'
|
|
852
|
+
):
|
|
853
|
+
"""Set the display name for all of this Room's apertures using a format string.
|
|
854
|
+
|
|
855
|
+
Args:
|
|
856
|
+
format_str: Text string for the pattern with which the apertures will be
|
|
857
|
+
renamed. Any property on the Aperture class may be used (eg. gbxml_str)
|
|
858
|
+
and each property should be put in curly brackets. Nested
|
|
859
|
+
properties can be specified by using "." to denote nesting levels
|
|
860
|
+
(eg. properties.energy.construction.display_name). Functions that
|
|
861
|
+
return string outputs can also be passed here as long as these
|
|
862
|
+
functions defaults specified for all arguments.
|
|
863
|
+
"""
|
|
864
|
+
for ap in self.apertures:
|
|
865
|
+
ap.rename_by_attribute(format_str)
|
|
866
|
+
|
|
867
|
+
def rename_doors_by_attribute(
|
|
868
|
+
self,
|
|
869
|
+
format_str='{parent.parent.display_name} - {energyplus_type} - {cardinal_direction}'
|
|
870
|
+
):
|
|
871
|
+
"""Set the display name for all of this Room's doors using a format string.
|
|
872
|
+
|
|
873
|
+
Args:
|
|
874
|
+
format_str: Text string for the pattern with which the doors will be
|
|
875
|
+
renamed. Any property on the Door class may be used (eg. gbxml_str)
|
|
876
|
+
and each property should be put in curly brackets. Nested
|
|
877
|
+
properties can be specified by using "." to denote nesting levels
|
|
878
|
+
(eg. properties.energy.construction.display_name). Functions that
|
|
879
|
+
return string outputs can also be passed here as long as these
|
|
880
|
+
functions defaults specified for all arguments.
|
|
881
|
+
"""
|
|
882
|
+
for dr in self.doors:
|
|
883
|
+
dr.rename_by_attribute(format_str)
|
|
884
|
+
|
|
777
885
|
def remove_indoor_furniture(self):
|
|
778
886
|
"""Remove all indoor furniture assigned to this Room.
|
|
779
887
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/minor_geometry/existing_model.hbjson
RENAMED
|
File without changes
|
{honeybee_core-1.63.0 → honeybee_core-1.64.0}/tests/json/minor_geometry/updated_model.hbjson
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|