honeybee-core 1.61.17__py2.py3-none-any.whl → 1.61.19__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
honeybee/aperture.py CHANGED
@@ -818,6 +818,39 @@ class Aperture(_BaseWithShade):
818
818
  return full_msg
819
819
  return [] if detailed else ''
820
820
 
821
+ def check_degenerate(self, tolerance=0.01, raise_exception=True, detailed=False):
822
+ """Check whether the Aperture is degenerate with effectively zero area.
823
+
824
+ Note that, while the Aperture may have an area larger than the tolerance,
825
+ removing colinear vertices within the tolerance would create a geometry
826
+ smaller than the tolerance.
827
+
828
+ Args:
829
+ tolerance: The minimum difference between the coordinate values of two
830
+ vertices at which they can be considered equivalent. Default: 0.01,
831
+ suitable for objects in meters.
832
+ raise_exception: If True, a ValueError will be raised if the object
833
+ intersects with itself. Default: True.
834
+ detailed: Boolean for whether the returned object is a detailed list of
835
+ dicts with error info or a string with a message. (Default: False).
836
+
837
+ Returns:
838
+ A string with the message or a list with a dictionary if detailed is True.
839
+ """
840
+ msg = 'Aperture "{}" is degenerate and should be deleted.'.format(
841
+ self.full_id)
842
+ try: # see if it is self-intersecting because of a duplicate vertex
843
+ new_geo = self.geometry.remove_colinear_vertices(tolerance)
844
+ if new_geo.area > tolerance:
845
+ return [] if detailed else '' # valid
846
+ except AssertionError:
847
+ pass # degenerate subface; treat it as degenerate
848
+ full_msg = self._validation_message(
849
+ msg, raise_exception, detailed, '000103',
850
+ error_type='Zero-Area Geometry')
851
+ return full_msg
852
+ return [] if detailed else ''
853
+
821
854
  def display_dict(self):
822
855
  """Get a list of DisplayFace3D dictionaries for visualizing the object."""
823
856
  base = [self._display_face(self.geometry, self.type_color)]
honeybee/door.py CHANGED
@@ -575,6 +575,39 @@ class Door(_BaseWithShade):
575
575
  return full_msg
576
576
  return [] if detailed else ''
577
577
 
578
+ def check_degenerate(self, tolerance=0.01, raise_exception=True, detailed=False):
579
+ """Check whether the Door is degenerate with effectively zero area.
580
+
581
+ Note that, while the Door may have an area larger than the tolerance,
582
+ removing colinear vertices within the tolerance would create a geometry
583
+ smaller than the tolerance.
584
+
585
+ Args:
586
+ tolerance: The minimum difference between the coordinate values of two
587
+ vertices at which they can be considered equivalent. Default: 0.01,
588
+ suitable for objects in meters.
589
+ raise_exception: If True, a ValueError will be raised if the object
590
+ intersects with itself. Default: True.
591
+ detailed: Boolean for whether the returned object is a detailed list of
592
+ dicts with error info or a string with a message. (Default: False).
593
+
594
+ Returns:
595
+ A string with the message or a list with a dictionary if detailed is True.
596
+ """
597
+ msg = 'Door "{}" is degenerate and should be deleted.'.format(
598
+ self.full_id)
599
+ try: # see if it is self-intersecting because of a duplicate vertex
600
+ new_geo = self.geometry.remove_colinear_vertices(tolerance)
601
+ if new_geo.area > tolerance:
602
+ return [] if detailed else '' # valid
603
+ except AssertionError:
604
+ pass # degenerate subface; treat it as degenerate
605
+ full_msg = self._validation_message(
606
+ msg, raise_exception, detailed, '000103',
607
+ error_type='Zero-Area Geometry')
608
+ return full_msg
609
+ return [] if detailed else ''
610
+
578
611
  def display_dict(self):
579
612
  """Get a list of DisplayFace3D dictionaries for visualizing the object."""
580
613
  base = [self._display_face(self.geometry, self.type_color)]
honeybee/face.py CHANGED
@@ -130,6 +130,13 @@ class Face(_BaseWithShade):
130
130
  assert data['type'] == 'Face', 'Expected Face dictionary. ' \
131
131
  'Got {}.'.format(data['type'])
132
132
 
133
+ # remove any invalid holes from the geometry
134
+ geo_dict = data['geometry']
135
+ if 'holes' in geo_dict and geo_dict['holes'] is not None:
136
+ for i, hole_list in enumerate(geo_dict['holes']):
137
+ if len(hole_list) < 3:
138
+ geo_dict['holes'].pop(i)
139
+
133
140
  # first serialize it with an outdoor boundary condition
134
141
  face_type = face_types.by_name(data['face_type'])
135
142
  face = cls(data['identifier'], Face3D.from_dict(data['geometry']),
@@ -2039,6 +2046,38 @@ class Face(_BaseWithShade):
2039
2046
  return full_msg
2040
2047
  return [] if detailed else ''
2041
2048
 
2049
+ def check_degenerate(self, tolerance=0.01, raise_exception=True, detailed=False):
2050
+ """Check whether the Face is degenerate with effectively zero area.
2051
+
2052
+ Note that, while the Face may have an area larger than the tolerance,
2053
+ removing colinear vertices within the tolerance would create a geometry
2054
+ smaller than the tolerance.
2055
+
2056
+ Args:
2057
+ tolerance: The minimum difference between the coordinate values of two
2058
+ vertices at which they can be considered equivalent. Default: 0.01,
2059
+ suitable for objects in meters.
2060
+ raise_exception: If True, a ValueError will be raised if the object
2061
+ intersects with itself. Default: True.
2062
+ detailed: Boolean for whether the returned object is a detailed list of
2063
+ dicts with error info or a string with a message. (Default: False).
2064
+
2065
+ Returns:
2066
+ A string with the message or a list with a dictionary if detailed is True.
2067
+ """
2068
+ msg = 'Face "{}" is degenerate and should be deleted.'.format(self.full_id)
2069
+ try: # see if it is self-intersecting because of a duplicate vertex
2070
+ new_geo = self.geometry.remove_colinear_vertices(tolerance)
2071
+ if new_geo.area > tolerance:
2072
+ return [] if detailed else '' # valid
2073
+ except AssertionError:
2074
+ pass # degenerate face; treat it as degenerate
2075
+ full_msg = self._validation_message(
2076
+ msg, raise_exception, detailed, '000103',
2077
+ error_type='Zero-Area Geometry')
2078
+ return full_msg
2079
+ return [] if detailed else ''
2080
+
2042
2081
  def display_dict(self):
2043
2082
  """Get a list of DisplayFace3D dictionaries for visualizing the object."""
2044
2083
  base = [self._display_face(self.punched_geometry, self.type_color)]
honeybee/model.py CHANGED
@@ -17,7 +17,8 @@ from ladybug_geometry.geometry3d import Plane, Face3D, Mesh3D
17
17
  from ladybug_geometry.interop.stl import STL
18
18
 
19
19
  from ._base import _Base
20
- from .units import conversion_factor_to_meters, UNITS, UNITS_TOLERANCES
20
+ from .units import conversion_factor_to_meters, parse_distance_string, \
21
+ UNITS, UNITS_TOLERANCES
21
22
  from .checkdup import check_duplicate_identifiers, check_duplicate_identifiers_parent
22
23
  from .properties import ModelProperties
23
24
  from .room import Room
@@ -2200,6 +2201,7 @@ class Model(_Base):
2200
2201
  'Model must have a non-zero angle_tolerance to perform geometry checks.'
2201
2202
  tol = self.tolerance
2202
2203
  ang_tol = self.angle_tolerance
2204
+ e_tol = parse_distance_string('1cm', self.units)
2203
2205
 
2204
2206
  # perform checks for duplicate identifiers, which might mess with other checks
2205
2207
  msgs.append(self.check_all_duplicate_identifiers(False, detailed))
@@ -2207,7 +2209,7 @@ class Model(_Base):
2207
2209
  # perform several checks for the Honeybee schema geometry rules
2208
2210
  msgs.append(self.check_planar(tol, False, detailed))
2209
2211
  msgs.append(self.check_self_intersecting(tol, False, detailed))
2210
- msgs.append(self.check_degenerate_rooms(tol, False, detailed))
2212
+ msgs.append(self.check_degenerate_rooms(e_tol, False, detailed))
2211
2213
 
2212
2214
  # perform geometry checks related to parent-child relationships
2213
2215
  msgs.append(self.check_sub_faces_valid(tol, ang_tol, False, detailed))
honeybee/room.py CHANGED
@@ -1155,7 +1155,7 @@ class Room(_BaseWithShade):
1155
1155
  """Remove colinear and duplicate vertices from this object's Faces and Sub-faces.
1156
1156
 
1157
1157
  If degenerate geometry is found in the process of removing colinear vertices,
1158
- an exception will be raised. Note that this does not affect the assigned Shades.
1158
+ an exception will be raised unless delete_degenerate is True.
1159
1159
 
1160
1160
  Args:
1161
1161
  tolerance: The minimum distance between a vertex and the boundary segments
@@ -1628,13 +1628,19 @@ class Room(_BaseWithShade):
1628
1628
  """
1629
1629
  # if the room has the correct number of faces, test the envelope geometry
1630
1630
  if len(self._faces) >= 4 and self.volume > tolerance:
1631
- try:
1632
- test_room = self.duplicate() # duplicate to avoid editing the original
1633
- test_room.remove_colinear_vertices_envelope(tolerance)
1634
- except ValueError as e:
1635
- deg_msg = str(e)
1636
- if raise_exception:
1637
- raise ValueError(e)
1631
+ msgs, final_faces = [], []
1632
+ for face in self._faces:
1633
+ face_msg = face.check_degenerate(tolerance, False, detailed)
1634
+ if not face_msg:
1635
+ final_faces.append(face)
1636
+ msgs.append(face_msg)
1637
+ for ap in face._apertures:
1638
+ msgs.append(ap.check_degenerate(tolerance, False, detailed))
1639
+ for dr in face._doors:
1640
+ msgs.append(dr.check_degenerate(tolerance, False, detailed))
1641
+ if len(final_faces) < 4:
1642
+ deg_msg = 'Room "{}" is degenerate with zero volume. ' \
1643
+ 'It should be deleted'.format(self.full_id)
1638
1644
  if detailed:
1639
1645
  deg_msg = [{
1640
1646
  'type': 'ValidationError',
@@ -1646,9 +1652,19 @@ class Room(_BaseWithShade):
1646
1652
  'element_name': [self.display_name],
1647
1653
  'message': deg_msg
1648
1654
  }]
1649
- return deg_msg
1650
- return [] if detailed else ''
1651
- # otherwise, report the room as invalid
1655
+ msgs.append(deg_msg)
1656
+ full_msgs = [msg for msg in msgs if msg]
1657
+ if len(full_msgs) == 0:
1658
+ return [] if detailed else ''
1659
+ elif detailed:
1660
+ return [m for megs in full_msgs for m in megs]
1661
+ full_msg = 'Room "{}" contains degenerate geometry.' \
1662
+ '\n {}'.format(self.full_id, '\n '.join(full_msgs))
1663
+ if raise_exception and len(full_msgs) != 0:
1664
+ raise ValueError(full_msg)
1665
+ return full_msg
1666
+
1667
+ # otherwise, report the room as invalid
1652
1668
  msg = 'Room "{}" is degenerate with zero volume. It should be deleted'.format(
1653
1669
  self.full_id)
1654
1670
  return self._validation_message(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: honeybee-core
3
- Version: 1.61.17
3
+ Version: 1.61.19
4
4
  Summary: A library to create 3D building geometry for various types of environmental simulation.
5
5
  Home-page: https://github.com/ladybug-tools/honeybee-core
6
6
  Author: Ladybug Tools
@@ -4,22 +4,22 @@ honeybee/_base.py,sha256=11TweR_0YJFv5ma1ttN2bs6FW_RlC3hNTjhhjvqXDB0,13181
4
4
  honeybee/_basewithshade.py,sha256=SXCWZ-4do6_Z-bZpVFidUINbylVyjwpkY2TIJE28Vuw,12943
5
5
  honeybee/_lockable.py,sha256=jmTVsXEWmYyEHpL3WsQZ_ItGOVVlJht1z3NFn07DIp0,3707
6
6
  honeybee/altnumber.py,sha256=nVXIvji9YDpy_I37oG41-rkPDx5QLplW9B2RYRCNeoA,1002
7
- honeybee/aperture.py,sha256=yVzhl2zqDVzIB0d1zgP2dtA8egfzzEw9bcR2ZqteMok,40763
7
+ honeybee/aperture.py,sha256=IHWU_-y1S2CEnIJnvBWU3WzwUqM3isn2JU_-3cXYPQQ,42425
8
8
  honeybee/boundarycondition.py,sha256=ys3kgMqgeJDBMLpXwSgwNBwvKMRz-LbCtLiL9tiOXS0,13777
9
9
  honeybee/checkdup.py,sha256=8q5p4tD3S4dl69jcURQhppeajJ_pYXRBlA48zTOoAGI,8221
10
10
  honeybee/colorobj.py,sha256=jhJmTBcLayFKSniW5ASo2-XMKFsW-RBUJilc9v-33ik,13349
11
11
  honeybee/config.json,sha256=GAFduJOXTlNcPM4M0fMkSXom5Cb7XZAMYQis2WsNaq0,167
12
12
  honeybee/config.py,sha256=auH_ooOyqMKAeBZxUc2NGUehUcYg8SHya98b5hfNlvM,13836
13
13
  honeybee/dictutil.py,sha256=cOqkhgJSQ3MviIkqOPv8MRb-N-BeDv07cVcNg7w7nLY,1992
14
- honeybee/door.py,sha256=PZwv7us-OC_MLuSckWmwdBZgBQ9xegY9fTps_k5lG8E,26921
14
+ honeybee/door.py,sha256=xbdefvnPPhwWzU66SpNL1C1A1YW5CNC8sLRabFZUf4E,28571
15
15
  honeybee/extensionutil.py,sha256=DDQYhM7tFD3avRSCOjwTzLqX9ldUxl5GzY79V3_sATE,9644
16
- honeybee/face.py,sha256=QGLC_0lrUjTpSpONLrtDWRUUFSdYEw5eG0B1DdIRif8,105662
16
+ honeybee/face.py,sha256=j_0YPI-dZGQQZ8CJNUtmO2LC-IfpVA_Fwp7ivOoBl6Y,107622
17
17
  honeybee/facetype.py,sha256=vCtWZKHp21RH-Yzs8zsHJHuFhJvczNh0yFl8wDe_RWY,4489
18
18
  honeybee/logutil.py,sha256=2gn-6RcWqFLvwdFzBHPqUwFqTj_R3iwHKALrl-2eL7M,2564
19
- honeybee/model.py,sha256=LO2Px1k3eb1lJWpRAZdodr-uNr-m7ES_-yDlyZlNYTI,174113
19
+ honeybee/model.py,sha256=RZIh4MpxYP-3g05536FUJUVmosCRDtWxtQaHwzTP954,174201
20
20
  honeybee/orientation.py,sha256=GogGblASW9OU-fobfDaQ7w5yRbEAFdJJuHwg2fadhKI,5046
21
21
  honeybee/properties.py,sha256=bJ8Zm6Q1ZSDYnlbKGWW_BOlfStm3VhCBM5T_abUeqp4,32488
22
- honeybee/room.py,sha256=a2_avI5GDYiYoci9PLb9ZetYcAmq6uVMQZnszyTuHWY,147839
22
+ honeybee/room.py,sha256=Ga91VmqBTJqYyCY5bX5kHnf3zMe9reG-tHqFOTeWdSc,148639
23
23
  honeybee/search.py,sha256=OiXibGGVb1ff4gTn_768i-sehB-zAYG12c0o3B0RjKE,4718
24
24
  honeybee/shade.py,sha256=G_ujmsPQeKvcc0O1ICiFRhVkjypkKBbgY9wJKck-9uU,19393
25
25
  honeybee/shademesh.py,sha256=oldugnwhu-ibX9f0hfxpO-DvgM8U7S-dYwUjBSVzo4g,13273
@@ -40,9 +40,9 @@ honeybee/writer/model.py,sha256=N7F_jksf-5TrdVecuxTaFWxnPVFLmQs7k8g27TsdB7Q,177
40
40
  honeybee/writer/room.py,sha256=kFghgStTU1SEJSLigXB0VjOWhZtgs4uXuAqdwd4yRQo,174
41
41
  honeybee/writer/shade.py,sha256=EpgX-vMc-s21TnMvNWvWTKyT8iAnxu1nFVXzjY1oyF8,177
42
42
  honeybee/writer/shademesh.py,sha256=Y41bLogJ7dwpvMe5cAWVRDRVqJEwo9e5hFJQjlt6UX8,189
43
- honeybee_core-1.61.17.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
44
- honeybee_core-1.61.17.dist-info/METADATA,sha256=49_6_QwdM9FQjln0lxSMXriLwrb1_KEBLMnTgqCuntQ,3317
45
- honeybee_core-1.61.17.dist-info/WHEEL,sha256=AHX6tWk3qWuce7vKLrj7lnulVHEdWoltgauo8bgCXgU,109
46
- honeybee_core-1.61.17.dist-info/entry_points.txt,sha256=r3YqOm40goBroH3ccUhpwQjvTwu10JWLd0HIRHI1J8E,47
47
- honeybee_core-1.61.17.dist-info/top_level.txt,sha256=8ve7puCRLUA9XDEGc1Mcs-UX9sFjpPV8MeTaIMwQ_Tg,9
48
- honeybee_core-1.61.17.dist-info/RECORD,,
43
+ honeybee_core-1.61.19.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
44
+ honeybee_core-1.61.19.dist-info/METADATA,sha256=JPHx2vrZuyC5rxvxT0c2qhWlGHjo70Xex0RTTRwAxUw,3317
45
+ honeybee_core-1.61.19.dist-info/WHEEL,sha256=AHX6tWk3qWuce7vKLrj7lnulVHEdWoltgauo8bgCXgU,109
46
+ honeybee_core-1.61.19.dist-info/entry_points.txt,sha256=r3YqOm40goBroH3ccUhpwQjvTwu10JWLd0HIRHI1J8E,47
47
+ honeybee_core-1.61.19.dist-info/top_level.txt,sha256=8ve7puCRLUA9XDEGc1Mcs-UX9sFjpPV8MeTaIMwQ_Tg,9
48
+ honeybee_core-1.61.19.dist-info/RECORD,,