honeybee-core 1.64.0__tar.gz → 1.64.2__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.64.0/honeybee_core.egg-info → honeybee_core-1.64.2}/PKG-INFO +1 -1
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/model.py +179 -47
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/shademesh.py +17 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2/honeybee_core.egg-info}/PKG-INFO +1 -1
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/model_test.py +18 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/.github/workflows/ci.yaml +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/.github/workflows/dependency-release.yaml +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/.gitignore +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/.releaserc.json +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/CODE_OF_CONDUCT.md +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/CONTRIBUTING.md +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/LICENSE +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/MANIFEST.in +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/README.md +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/deploy.sh +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/dev-requirements.txt +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/docs/_build/.nojekyll +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/docs/_build/README.md +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/docs/_build/docs/README.md +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/docs/_static/custom.css +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/docs/_templates/layout.html +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/docs/cli/index.rst +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/docs/conf.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/docs/index.rst +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/__init__.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/__main__.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/_base.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/_basewithshade.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/_lockable.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/altnumber.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/aperture.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/boundarycondition.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/checkdup.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/cli/__init__.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/cli/compare.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/cli/create.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/cli/edit.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/cli/lib.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/cli/setconfig.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/cli/validate.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/colorobj.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/config.json +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/config.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/dictutil.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/door.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/extensionutil.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/face.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/facetype.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/logutil.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/orientation.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/properties.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/room.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/search.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/shade.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/typing.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/units.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/writer/__init__.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/writer/aperture.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/writer/door.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/writer/face.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/writer/model.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/writer/room.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/writer/shade.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee/writer/shademesh.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee_core.egg-info/SOURCES.txt +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee_core.egg-info/dependency_links.txt +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee_core.egg-info/entry_points.txt +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee_core.egg-info/requires.txt +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/honeybee_core.egg-info/top_level.txt +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/requirements.txt +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/setup.cfg +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/setup.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/__init__.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/aperture_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/boundary_condition_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/cli_compare_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/cli_create_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/cli_edit_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/cli_validate_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/colorobj_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/config_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/dictutil_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/door_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/face_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/facetype_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/ShoeBox.json +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/bad_geometry_model.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/colliding_room_volumes.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/compare_model_1.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/compare_model_2.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/complex_polyfaces.json +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/minor_geometry/existing_model.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/minor_geometry/updated_model.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/mismatched_area_adj.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/model_with_adiabatic.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/model_with_holes.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/model_without_adjacency.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/nonascii_face.json +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/polygons_for_gap_boundary.json +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/room_for_window_offset.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/json/single_family_home.hbjson +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/lockable_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/orientation_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/room_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/search_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/shade_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/shademesh_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/stl/cube_ascii.stl +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/stl/cube_binary.stl +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/typing_test.py +0 -0
- {honeybee_core-1.64.0 → honeybee_core-1.64.2}/tests/units_test.py +0 -0
|
@@ -13,7 +13,9 @@ try: # check if we are in IronPython
|
|
|
13
13
|
except ImportError: # wea are in cPython
|
|
14
14
|
import pickle
|
|
15
15
|
|
|
16
|
-
from ladybug_geometry.
|
|
16
|
+
from ladybug_geometry.geometry2d import Polygon2D
|
|
17
|
+
from ladybug_geometry.geometry3d import Vector3D, Point3D, Plane, Face3D, \
|
|
18
|
+
Mesh3D, Polyface3D
|
|
17
19
|
from ladybug_geometry.interop.stl import STL
|
|
18
20
|
|
|
19
21
|
from ._base import _Base
|
|
@@ -1533,6 +1535,71 @@ class Model(_Base):
|
|
|
1533
1535
|
return roof_to_exterior, slab_to_exterior, exposed_floor_to_exterior_wall, \
|
|
1534
1536
|
exterior_wall_to_wall, roof_ridge, exposed_floor_to_floor, underground
|
|
1535
1537
|
|
|
1538
|
+
def classified_sub_face_edges(
|
|
1539
|
+
self, mullion_thickness=None, tolerance=None, angle_tolerance=None
|
|
1540
|
+
):
|
|
1541
|
+
"""Get classified edges around this Model's Apertures and Doors.
|
|
1542
|
+
|
|
1543
|
+
The edges returned by this method will only exist along the exterior
|
|
1544
|
+
sub-faces.
|
|
1545
|
+
|
|
1546
|
+
Args:
|
|
1547
|
+
mullion_thickness: The maximum difference that apertures can be from
|
|
1548
|
+
one another for the edges to be considered a mullion rather than
|
|
1549
|
+
a frame. If None, the Model's tolerance will be used.
|
|
1550
|
+
tolerance: The maximum difference between point values for them to be
|
|
1551
|
+
considered equivalent. If None, the Model's tolerance will be used.
|
|
1552
|
+
angle_tolerance: The max angle difference in degrees where sub-face
|
|
1553
|
+
normals are no longer considered coplanar. If None, the Model
|
|
1554
|
+
angle_tolerance will be used. (Default: None).
|
|
1555
|
+
|
|
1556
|
+
Returns:
|
|
1557
|
+
A tuple with three items where each item is a list containing
|
|
1558
|
+
LineSegment3D surrounding different sub-face conditions.
|
|
1559
|
+
|
|
1560
|
+
- window_frames - Apertures meet their parent exterior wall or roof.
|
|
1561
|
+
|
|
1562
|
+
- window_mullions - Apertures meet one another.
|
|
1563
|
+
|
|
1564
|
+
- door_frames - Doors meet their parent exterior wall or roof.
|
|
1565
|
+
"""
|
|
1566
|
+
# set up lists to be populated
|
|
1567
|
+
window_frames, window_mullions = [], []
|
|
1568
|
+
tol = tolerance if tolerance is not None else self.tolerance
|
|
1569
|
+
a_tol = math.radians(angle_tolerance) if angle_tolerance is not None else \
|
|
1570
|
+
math.radians(self.angle_tolerance)
|
|
1571
|
+
mul_thick = tol if mullion_thickness is None else mullion_thickness
|
|
1572
|
+
|
|
1573
|
+
# group the apertures by the plane in which they exist
|
|
1574
|
+
apertures = self.apertures
|
|
1575
|
+
coplanar_dict = {apertures[0].geometry.plane: [apertures[0]]}
|
|
1576
|
+
for ap in apertures[1:]:
|
|
1577
|
+
if isinstance(ap.boundary_condition, Outdoors):
|
|
1578
|
+
for pln, f_list in coplanar_dict.items():
|
|
1579
|
+
if ap.geometry.plane.is_coplanar_tolerance(pln, tol, a_tol):
|
|
1580
|
+
f_list.append(ap)
|
|
1581
|
+
break
|
|
1582
|
+
else: # the first face with this type of plane
|
|
1583
|
+
coplanar_dict[ap.geometry.plane] = [ap]
|
|
1584
|
+
|
|
1585
|
+
# for each group, intersect their edges and extract edges from a Polyface3D
|
|
1586
|
+
for plane, aps in coplanar_dict.items():
|
|
1587
|
+
# intersect edges that are close enough to one another within thickness
|
|
1588
|
+
polygons = []
|
|
1589
|
+
for ap in aps:
|
|
1590
|
+
pts_2d = [plane.xyz_to_xy(pt) for pt in ap.geometry.boundary]
|
|
1591
|
+
polygons.append(Polygon2D(pts_2d))
|
|
1592
|
+
polygons = Polygon2D.intersect_polygon_segments(polygons, mul_thick)
|
|
1593
|
+
faces = []
|
|
1594
|
+
for poly in polygons:
|
|
1595
|
+
faces.append(Face3D([plane.xy_to_xyz(pt) for pt in poly]))
|
|
1596
|
+
# create a joined Polyface3D and classify the edges
|
|
1597
|
+
ap_polyface = Polyface3D.from_faces(faces, mul_thick)
|
|
1598
|
+
window_frames.extend(ap_polyface.naked_edges)
|
|
1599
|
+
window_mullions.extend(ap_polyface.internal_edges)
|
|
1600
|
+
|
|
1601
|
+
return window_frames, window_mullions, self.exterior_door_edges
|
|
1602
|
+
|
|
1536
1603
|
def add_prefix(self, prefix):
|
|
1537
1604
|
"""Change the identifier of this object and child objects by inserting a prefix.
|
|
1538
1605
|
|
|
@@ -1559,6 +1626,25 @@ class Model(_Base):
|
|
|
1559
1626
|
for shade_mesh in self._shade_meshes:
|
|
1560
1627
|
shade_mesh.add_prefix(prefix)
|
|
1561
1628
|
|
|
1629
|
+
def reset_room_ids(self):
|
|
1630
|
+
"""Reset the identifiers of the Model Rooms to be derived from display_names.
|
|
1631
|
+
|
|
1632
|
+
In the event that duplicate Room identifiers are found, an integer will
|
|
1633
|
+
be automatically appended to the new Room ID to make it unique.
|
|
1634
|
+
|
|
1635
|
+
Returns:
|
|
1636
|
+
A dictionary that relates the old identifiers (keys) to the new
|
|
1637
|
+
identifiers (values). This can be used to map between old and new
|
|
1638
|
+
objects and update things like Surface boundary conditions.
|
|
1639
|
+
"""
|
|
1640
|
+
room_dict, room_map = {}, {}
|
|
1641
|
+
for room in self.rooms:
|
|
1642
|
+
new_id = clean_and_number_string(
|
|
1643
|
+
room.display_name, room_dict, 'Room identifier')
|
|
1644
|
+
room_map[room.identifier] = new_id
|
|
1645
|
+
room.identifier = new_id
|
|
1646
|
+
return room_map
|
|
1647
|
+
|
|
1562
1648
|
def reset_ids(self, repair_surface_bcs=True):
|
|
1563
1649
|
"""Reset the identifiers of all Model objects to be derived from display_names.
|
|
1564
1650
|
|
|
@@ -1613,39 +1699,7 @@ class Model(_Base):
|
|
|
1613
1699
|
shade_mesh.display_name, sm_dict, 'ShadeMesh identifier')
|
|
1614
1700
|
# reset all of the Surface boundary conditions if requested
|
|
1615
1701
|
if repair_surface_bcs:
|
|
1616
|
-
|
|
1617
|
-
for face in room.faces:
|
|
1618
|
-
if isinstance(face.boundary_condition, Surface):
|
|
1619
|
-
old_objs = face.boundary_condition.boundary_condition_objects
|
|
1620
|
-
try:
|
|
1621
|
-
new_objs = (face_map[old_objs[0]], room_map[old_objs[1]])
|
|
1622
|
-
except KeyError: # missing adjacency
|
|
1623
|
-
try: # see if maybe the room reference is still there
|
|
1624
|
-
new_objs = (old_objs[0], room_map[old_objs[1]])
|
|
1625
|
-
except KeyError: # just let the invalid adjacency pass
|
|
1626
|
-
continue
|
|
1627
|
-
new_bc = Surface(new_objs)
|
|
1628
|
-
face.boundary_condition = new_bc
|
|
1629
|
-
for ap in face.apertures:
|
|
1630
|
-
old_objs = ap.boundary_condition.boundary_condition_objects
|
|
1631
|
-
try:
|
|
1632
|
-
new_objs = (ap_map[old_objs[0]], face_map[old_objs[1]],
|
|
1633
|
-
room_map[old_objs[2]])
|
|
1634
|
-
except KeyError: # missing adjacency
|
|
1635
|
-
new_objs = (old_objs[0], old_objs[1],
|
|
1636
|
-
room_map[old_objs[2]])
|
|
1637
|
-
new_bc = Surface(new_objs, True)
|
|
1638
|
-
ap.boundary_condition = new_bc
|
|
1639
|
-
for dr in face.doors:
|
|
1640
|
-
old_objs = dr.boundary_condition.boundary_condition_objects
|
|
1641
|
-
try:
|
|
1642
|
-
new_objs = (dr_map[old_objs[0]], face_map[old_objs[1]],
|
|
1643
|
-
room_map[old_objs[2]])
|
|
1644
|
-
except KeyError: # missing adjacency
|
|
1645
|
-
new_objs = (old_objs[0], old_objs[1],
|
|
1646
|
-
room_map[old_objs[2]])
|
|
1647
|
-
new_bc = Surface(new_objs, True)
|
|
1648
|
-
dr.boundary_condition = new_bc
|
|
1702
|
+
self._repair_surface_bcs(room_map, face_map, ap_map, dr_map)
|
|
1649
1703
|
# return a dictionary that maps between old and new IDs
|
|
1650
1704
|
return {
|
|
1651
1705
|
'rooms': room_map,
|
|
@@ -1654,24 +1708,90 @@ class Model(_Base):
|
|
|
1654
1708
|
'doors': dr_map
|
|
1655
1709
|
}
|
|
1656
1710
|
|
|
1657
|
-
def
|
|
1658
|
-
"""Reset the identifiers of
|
|
1711
|
+
def reset_ids_to_integers(self, start_integer=0, repair_surface_bcs=True):
|
|
1712
|
+
"""Reset the identifiers of all Model geometry objects to be a unique integer.
|
|
1659
1713
|
|
|
1660
|
-
|
|
1661
|
-
|
|
1714
|
+
Integers are simply incremented from the start_integer, assigning integers
|
|
1715
|
+
first to Rooms, then to Faces, then to Apertures/Doors and lastly to
|
|
1716
|
+
Shades/ShadeMeshes.
|
|
1717
|
+
|
|
1718
|
+
Args:
|
|
1719
|
+
start_integer: The starting integer that will be used to set a lower
|
|
1720
|
+
limit on the integers assigned to the geometry elements.
|
|
1721
|
+
repair_surface_bcs: A Boolean to note whether all Surface boundary
|
|
1722
|
+
conditions across the model should be updated with the new
|
|
1723
|
+
identifiers that were generated from the display names. (Default: True).
|
|
1662
1724
|
|
|
1663
1725
|
Returns:
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1726
|
+
An integer for the last value assigned to the model geometry objects.
|
|
1727
|
+
This can be used to ensure that any future IDs assigned after running
|
|
1728
|
+
this method do not have IDs that collide with the model objects.
|
|
1667
1729
|
"""
|
|
1668
|
-
|
|
1730
|
+
# set up dictionaries to hold various pieces of information
|
|
1731
|
+
room_map, face_map, ap_map, dr_map = {}, {}, {}, {}
|
|
1732
|
+
# loop through the objects and change their identifiers
|
|
1669
1733
|
for room in self.rooms:
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1734
|
+
room_map[room.identifier] = str(start_integer)
|
|
1735
|
+
room.identifier = str(start_integer)
|
|
1736
|
+
start_integer += 1
|
|
1737
|
+
for face in self.faces:
|
|
1738
|
+
face_map[face.identifier] = str(start_integer)
|
|
1739
|
+
face.identifier = str(start_integer)
|
|
1740
|
+
start_integer += 1
|
|
1741
|
+
for ap in self.apertures:
|
|
1742
|
+
ap_map[ap.identifier] = str(start_integer)
|
|
1743
|
+
ap.identifier = str(start_integer)
|
|
1744
|
+
start_integer += 1
|
|
1745
|
+
for dr in self.doors:
|
|
1746
|
+
dr_map[dr.identifier] = str(start_integer)
|
|
1747
|
+
dr.identifier = str(start_integer)
|
|
1748
|
+
start_integer += 1
|
|
1749
|
+
for shade in self.shades:
|
|
1750
|
+
shade.identifier = str(start_integer)
|
|
1751
|
+
start_integer += 1
|
|
1752
|
+
for shade_mesh in self.shade_meshes:
|
|
1753
|
+
shade_mesh.identifier = str(start_integer)
|
|
1754
|
+
start_integer += 1
|
|
1755
|
+
# reset all of the Surface boundary conditions if requested
|
|
1756
|
+
if repair_surface_bcs:
|
|
1757
|
+
self._repair_surface_bcs(room_map, face_map, ap_map, dr_map)
|
|
1758
|
+
return start_integer
|
|
1759
|
+
|
|
1760
|
+
def _repair_surface_bcs(self, room_map, face_map, ap_map, dr_map):
|
|
1761
|
+
"""Repair Surface boundary conditions across the model using dict maps."""
|
|
1762
|
+
for room in self.rooms:
|
|
1763
|
+
for face in room.faces:
|
|
1764
|
+
if isinstance(face.boundary_condition, Surface):
|
|
1765
|
+
old_objs = face.boundary_condition.boundary_condition_objects
|
|
1766
|
+
try:
|
|
1767
|
+
new_objs = (face_map[old_objs[0]], room_map[old_objs[1]])
|
|
1768
|
+
except KeyError: # missing adjacency
|
|
1769
|
+
try: # see if maybe the room reference is still there
|
|
1770
|
+
new_objs = (old_objs[0], room_map[old_objs[1]])
|
|
1771
|
+
except KeyError: # just let the invalid adjacency pass
|
|
1772
|
+
continue
|
|
1773
|
+
new_bc = Surface(new_objs)
|
|
1774
|
+
face.boundary_condition = new_bc
|
|
1775
|
+
for ap in face.apertures:
|
|
1776
|
+
old_objs = ap.boundary_condition.boundary_condition_objects
|
|
1777
|
+
try:
|
|
1778
|
+
new_objs = (ap_map[old_objs[0]], face_map[old_objs[1]],
|
|
1779
|
+
room_map[old_objs[2]])
|
|
1780
|
+
except KeyError: # missing adjacency
|
|
1781
|
+
new_objs = (old_objs[0], old_objs[1],
|
|
1782
|
+
room_map[old_objs[2]])
|
|
1783
|
+
new_bc = Surface(new_objs, True)
|
|
1784
|
+
ap.boundary_condition = new_bc
|
|
1785
|
+
for dr in face.doors:
|
|
1786
|
+
old_objs = dr.boundary_condition.boundary_condition_objects
|
|
1787
|
+
try:
|
|
1788
|
+
new_objs = (dr_map[old_objs[0]], face_map[old_objs[1]],
|
|
1789
|
+
room_map[old_objs[2]])
|
|
1790
|
+
except KeyError: # missing adjacency
|
|
1791
|
+
new_objs = (old_objs[0], old_objs[1],
|
|
1792
|
+
room_map[old_objs[2]])
|
|
1793
|
+
new_bc = Surface(new_objs, True)
|
|
1794
|
+
dr.boundary_condition = new_bc
|
|
1675
1795
|
|
|
1676
1796
|
def solve_adjacency(
|
|
1677
1797
|
self, merge_coplanar=False, intersect=False, overwrite=False,
|
|
@@ -2181,6 +2301,18 @@ class Model(_Base):
|
|
|
2181
2301
|
extrusion_rooms.append(room.to_extrusion(tol, a_tol))
|
|
2182
2302
|
self._rooms = extrusion_rooms
|
|
2183
2303
|
|
|
2304
|
+
def shade_meshes_to_shades(self):
|
|
2305
|
+
"""Convert all ShadeMesh objects on the Model to planar Shades."""
|
|
2306
|
+
new_shades = []
|
|
2307
|
+
for shade_mesh in self.shade_meshes:
|
|
2308
|
+
try:
|
|
2309
|
+
shade_mesh.triangulate_and_remove_degenerate_faces(self.tolerance)
|
|
2310
|
+
new_shades.extend(shade_mesh.to_shades())
|
|
2311
|
+
except AssertionError:
|
|
2312
|
+
pass # completely degenerate ShadeMesh to ignore
|
|
2313
|
+
self._orphaned_shades.extend(new_shades)
|
|
2314
|
+
self._shade_meshes = []
|
|
2315
|
+
|
|
2184
2316
|
def convert_to_units(self, units='Meters'):
|
|
2185
2317
|
"""Convert all of the geometry in this model to certain units.
|
|
2186
2318
|
|
|
@@ -324,6 +324,23 @@ class ShadeMesh(_Base):
|
|
|
324
324
|
base['user_data'] = self.user_data
|
|
325
325
|
return base
|
|
326
326
|
|
|
327
|
+
def to_shades(self):
|
|
328
|
+
"""Return a list of Honeybee Shade objects derived from this ShadeMesh.
|
|
329
|
+
|
|
330
|
+
Note that the resulting Shades may be degenerate or non-planar so it
|
|
331
|
+
may be useful to call triangulate_and_remove_degenerate_faces on this
|
|
332
|
+
object before converting to Shades.
|
|
333
|
+
"""
|
|
334
|
+
from honeybee.shade import Shade # imported here to avoid circular import
|
|
335
|
+
shades = []
|
|
336
|
+
for i, shade_geo in enumerate(self.geometry.face_vertices):
|
|
337
|
+
shade_id = '{}_{}'.format(self.identifier, i)
|
|
338
|
+
shade = Shade(shade_id, Face3D(shade_geo), self.is_detached)
|
|
339
|
+
if self._display_name is not None:
|
|
340
|
+
shade.display_name = '{} {}'.format(self.display_name, i)
|
|
341
|
+
shades.append(shade)
|
|
342
|
+
return shades
|
|
343
|
+
|
|
327
344
|
@staticmethod
|
|
328
345
|
def _display_mesh(mesh3d, color):
|
|
329
346
|
"""Create a DisplayMesh3D dictionary from a Mesh3D and color."""
|
|
@@ -399,6 +399,18 @@ def test_reset_ids():
|
|
|
399
399
|
assert new_model.check_missing_adjacencies() == ''
|
|
400
400
|
|
|
401
401
|
|
|
402
|
+
def test_reset_ids_to_integers():
|
|
403
|
+
"""Test the reset_ids_to_integers method."""
|
|
404
|
+
model_json = './tests/json/model_with_adiabatic.hbjson'
|
|
405
|
+
parsed_model = Model.from_hbjson(model_json, cleanup_irrational=True)
|
|
406
|
+
|
|
407
|
+
new_model = parsed_model.duplicate()
|
|
408
|
+
new_model.reset_ids_to_integers(True)
|
|
409
|
+
|
|
410
|
+
assert new_model.rooms[0].identifier != parsed_model.rooms[0].identifier
|
|
411
|
+
assert new_model.check_missing_adjacencies() == ''
|
|
412
|
+
|
|
413
|
+
|
|
402
414
|
def test_offset_aperture_edges():
|
|
403
415
|
"""Test the Face offset_aperture_edges method."""
|
|
404
416
|
model_json = './tests/json/room_for_window_offset.hbjson'
|
|
@@ -588,6 +600,12 @@ def test_remove_degenerate_geometry():
|
|
|
588
600
|
model.remove_degenerate_geometry()
|
|
589
601
|
assert len(model.shade_meshes) == 1
|
|
590
602
|
|
|
603
|
+
model = Model('MultiZoneSingleFamilyHouse',
|
|
604
|
+
[first_floor, second_floor], shade_meshes=[shade1, shade2])
|
|
605
|
+
model.shade_meshes_to_shades()
|
|
606
|
+
assert len(model.shade_meshes) == 0
|
|
607
|
+
assert len(model.orphaned_shades) == 2
|
|
608
|
+
|
|
591
609
|
|
|
592
610
|
def test_assign_stories_by_floor_height():
|
|
593
611
|
"""Test the Model assign_stories_by_floor_height method."""
|
|
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.64.0 → honeybee_core-1.64.2}/tests/json/minor_geometry/existing_model.hbjson
RENAMED
|
File without changes
|
{honeybee_core-1.64.0 → honeybee_core-1.64.2}/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
|