def add_window_to_face(self, face, tolerance=0.01): """Add Apertures to a Honeybee Face using these Window Parameters. Args: face: A honeybee-core Face object. tolerance: Optional tolerance value. Default: 0.01, suitable for objects in meters. """ width_seg = LineSegment3D.from_end_points(face.geometry[0], face.geometry[1]) height_seg = LineSegment3D.from_end_points(face.geometry[1], face.geometry[2]) max_width = width_seg.length * 0.99 max_height = (height_seg.length * 0.99) - self.sill_height final_width = max_width if self.width > max_width else self.width final_height = max_height if self.height > max_height else self.height if final_height > 0: face.aperture_by_width_height(final_width, final_height, self.sill_height) # if the Aperture is interior, set adjacent boundary condition if isinstance(face._boundary_condition, Surface): ids = face._boundary_condition.boundary_condition_objects adj_ap_id = '{}_Glz1'.format(ids[0]) final_ids = (adj_ap_id, ) + ids face.apertures[0].boundary_condition = Surface(final_ids, True)
def test_join_segments_disconnected(): """Test the join_segments method with diconnected polylines.""" pts = (Point3D(0, 0), Point3D(2, 0), Point3D(2, 2), Point3D(0, 2)) extra_pts = (Point3D(3, 3), Point3D(4, 3), Point3D(4, 4), Point3D(3, 4)) l_segs = (LineSegment3D.from_end_points(extra_pts[0], extra_pts[1]), LineSegment3D.from_end_points(pts[0], pts[1]), LineSegment3D.from_end_points(pts[2], pts[3]), LineSegment3D.from_end_points(extra_pts[3], extra_pts[2])) p_lines = Polyline3D.join_segments(l_segs, 0.01) assert len(p_lines) == 4
def test_extract_rectangle_complex(): """Test the Face3D extract_rectangle method with a more complex shape.""" pts_1 = (Point3D(-1, -1, 0), Point3D(-12, -1, 0), Point3D(-12, -1, 2), Point3D(-10, -1, 3), Point3D(-1, -1, 3)) plane = Plane(Vector3D(0, 1, 0)) face_1 = Face3D(pts_1, plane) f1_result = face_1.extract_rectangle(0.0001) assert f1_result[0] == LineSegment3D.from_end_points( Point3D(-1, -1, 0), Point3D(-10, -1, 0)) assert f1_result[1] == LineSegment3D.from_end_points( Point3D(-1, -1, 3), Point3D(-10, -1, 3)) assert len(f1_result[2]) == 1 assert len(f1_result[2][0].vertices) == 4
def test_to_from_array(): """Test to/from array method""" test_line = LineSegment3D.from_end_points(Point3D(2, 0, 2), Point3D(2, 2, 2)) line_array = ((2, 0, 2), (2, 2, 2)) assert test_line == LineSegment3D.from_array(line_array) line_array = ((2, 0, 2), (2, 2, 2)) test_line = LineSegment3D.from_end_points(Point3D(2, 0, 2), Point3D(2, 2, 2)) assert test_line.to_array() == line_array test_line_2 = LineSegment3D.from_array(test_line.to_array()) assert test_line == test_line_2
def to_polyline3d(polyline): """Ladybug Polyline3D from a Rhino PolyLineCurve. A LineSegment3D will be returned if the input polyline has only two points. """ pts = [to_point3d(polyline.Point(i)) for i in range(polyline.PointCount)] return Polyline3D(pts) if len(pts) != 2 else LineSegment3D.from_end_points( *pts)
def _my_lb_line_constructor(_line): """Cus' the 'to_line_segment' method has an error (thinks second pt is a vector) """ p1 = to_point3d(_line.PointAtStart) p2 = to_point3d(_line.PointAtEnd) line = LineSegment3D.from_end_points(p1, p2) return line
def test_init_from_endpoints(): """Test the initalization of LineSegment3D from end points.""" pt_1 = Point3D(2, 0, 2) pt_2 = Point3D(2, 2, 2) seg = LineSegment3D.from_end_points(pt_1, pt_2) assert seg.p == Point3D(2, 0, 2) assert seg.v == Vector3D(0, 2, 0) assert seg.p1 == Point3D(2, 0, 2) assert seg.p2 == Point3D(2, 2, 2) assert seg.length == 2
def test_single_window_add_window_to_face(): """Test the add_window_to_face method.""" simple_window = SingleWindow(5, 2, 0.8) height = 3 width = 10 seg = LineSegment3D.from_end_points(Point3D(0, 0, 2), Point3D(width, 0, 2)) face = Face('test_face', Face3D.from_extrusion(seg, Vector3D(0, 0, height))) simple_window.add_window_to_face(face, 0.01) assert len(face.apertures) == 1 assert face.center.x == face.apertures[0].center.x assert face.center.y == face.apertures[0].center.y assert simple_window.area_from_segment(seg, height) == face.apertures[0].area == 10
def test_overhang_add_shading_to_face(): """Test the add_shading_to_face method.""" simple_awning = Overhang(2, 0) height = 3 width = 10 seg = LineSegment3D.from_end_points(Point3D(0, 0, 2), Point3D(width, 0, 2)) face = Face('test_face', Face3D.from_extrusion(seg, Vector3D(0, 0, height))) simple_awning.add_shading_to_face(face, 0.01) assert len(face.outdoor_shades) == 1 assert face.outdoor_shades[0].center.z == pytest.approx(2 + 3, rel=1e-1) assert face.outdoor_shades[0].area == pytest.approx(20, rel=1e-3)
def test_repeating_window_width_height_add_window_to_face(): """Test the add_window_to_face method.""" bod_windows = RepeatingWindowWidthHeight(2, 2, 0.5, 2.5) height = 3 width = 10 seg = LineSegment3D.from_end_points(Point3D(0, 0, 2), Point3D(width, 0, 2)) face = Face('test_face', Face3D.from_extrusion(seg, Vector3D(0, 0, height))) bod_windows.add_window_to_face(face, 0.01) assert len(face.apertures) == 4 assert all(len(ap.geometry.vertices) == 4 for ap in face.apertures) assert sum([ap.area for ap in face.apertures]) == pytest.approx(16, rel=1e-2) assert face.punched_geometry.area == pytest.approx(30 - 16, rel=1e-2)
def test_simple_window_ratio_add_window_to_face(): """Test the add_window_to_face method.""" ashrae_base = SimpleWindowRatio(0.4) height = 3 width = 10 seg = LineSegment3D.from_end_points(Point3D(0, 0, 2), Point3D(width, 0, 2)) face = Face('test_face', Face3D.from_extrusion(seg, Vector3D(0, 0, height))) ashrae_base.add_window_to_face(face, 0.01) assert len(face.apertures) == 1 assert face.center == face.apertures[0].center assert ashrae_base.area_from_segment(seg, height) == face.apertures[0].area == \ width * height * 0.4
def test_repeating_window_ratio_add_window_to_face(): """Test the add_window_to_face method.""" ashrae_base = RepeatingWindowRatio(0.4, 2, 0.8, 3) height = 3 width = 10 seg = LineSegment3D.from_end_points(Point3D(0, 0, 2), Point3D(width, 0, 2)) face = Face('test_face', Face3D.from_extrusion(seg, Vector3D(0, 0, height))) ashrae_base.add_window_to_face(face, 0.01) assert len(face.apertures) == 3 ap_area = sum([ap.area for ap in face.apertures]) assert ashrae_base.area_from_segment(seg, height) == \ pytest.approx(ap_area, rel=1e-3) == width * height * 0.4
def test_louvers_by_distance_add_shading_to_face(): """Test the add_shading_to_face method.""" louvers = LouversByDistance(0.5, 0.3, 1, 30) height = 3 width = 10 seg = LineSegment3D.from_end_points(Point3D(0, 0, 2), Point3D(width, 0, 2)) face = Face('test_face', Face3D.from_extrusion(seg, Vector3D(0, 0, height))) louvers.add_shading_to_face(face, 0.01) assert len(face.outdoor_shades) == 6 shd_area = sum([shd.area for shd in face.outdoor_shades]) assert shd_area == pytest.approx(0.3 * width * 6, rel=1e-3)
def add_window_to_face(self, face, tolerance=0.01): """Add Apertures to a Honeybee Face using these Window Parameters. Args: face: A honeybee-core Face object. tolerance: Optional tolerance value. Default: 0.01, suitable for objects in meters. """ # collect the global properties of the face that set limits on apertures wall_plane = face.geometry.plane width_seg = LineSegment3D.from_end_points(face.geometry[0], face.geometry[1]) height_seg = LineSegment3D.from_end_points(face.geometry[1], face.geometry[2]) max_width = width_seg.length * 0.99 max_height = height_seg.length * 0.99 # loop through each window and create its geometry for i, (o, wid, hgt) in enumerate(zip(self.origins, self.widths, self.heights)): final_width = max_width - o.x if wid + o.x > max_width else wid final_height = max_height - o.y if hgt + o.y > max_height else hgt if final_height > 0 and final_height > 0: # inside wall boundary base_plane = Plane(wall_plane.n, wall_plane.xy_to_xyz(o), wall_plane.x) ap_face = Face3D.from_rectangle(final_width, final_height, base_plane) aperture = Aperture('{}_Glz{}'.format(face.identifier, i + 1), ap_face) aperture._parent = face face.add_aperture(aperture) # if the Aperture is interior, set adjacent boundary condition if isinstance(face._boundary_condition, Surface): ids = face._boundary_condition.boundary_condition_objects adj_ap_id = '{}_Glz{}'.format(ids[0], i + 1) final_ids = (adj_ap_id, ) + ids aperture.boundary_condition = Surface(final_ids, True)
def test_detailed_window_add_window_to_face(): """Test the add_window_to_face method.""" origins = (Point2D(2, 1), Point2D(5, 0.5)) widths = (1, 3) heights = (1, 2) detailed_window = RectangularWindows(origins, widths, heights) height = 3 width = 10 seg = LineSegment3D.from_end_points(Point3D(0, 0, 2), Point3D(width, 0, 2)) face = Face('test_face', Face3D.from_extrusion(seg, Vector3D(0, 0, height))) detailed_window.add_window_to_face(face, 0.01) assert len(face.apertures) == 2 assert len(face.apertures[0].vertices) == 4 assert len(face.apertures[1].vertices) == 4 assert face.apertures[0].area == widths[0] * heights[0] assert face.apertures[1].area == widths[1] * heights[1]
def test_extruded_border_add_shading_to_face(): """Test the add_shading_to_face method.""" simple_border = ExtrudedBorder(0.3) height = 3 width = 10 seg = LineSegment3D.from_end_points(Point3D(0, 0, 2), Point3D(width, 0, 2)) face_1 = Face('test_face', Face3D.from_extrusion(seg, Vector3D(0, 0, height))) face_2 = face_1.duplicate() face_2.apertures_by_ratio(0.4) simple_border.add_shading_to_face(face_1, 0.01) simple_border.add_shading_to_face(face_2, 0.01) assert len(face_1.apertures) == 0 assert len(face_1.outdoor_shades) == 0 assert len(face_2.apertures) == 1 assert len(face_2.apertures[0].outdoor_shades) == 4 shd_area = sum([shd.area for shd in face_2.apertures[0].outdoor_shades]) assert shd_area == pytest.approx(0.3 * face_2.apertures[0].perimeter, rel=1e-3)
def to_linesegment3d(line): """Ladybug LineSegment3D from Rhino LineCurve.""" return LineSegment3D.from_end_points(to_point3d(line.PointAtStart), to_point3d(line.PointAtEnd))
def test_join_segments(): """Test the join_segments method.""" pts = (Point3D(0, 0), Point3D(2, 0), Point3D(2, 2), Point3D(0, 2)) l_segs = (LineSegment3D.from_end_points(pts[0], pts[1]), LineSegment3D.from_end_points(pts[1], pts[2]), LineSegment3D.from_end_points(pts[2], pts[3]), LineSegment3D.from_end_points(pts[3], pts[0])) p_lines = Polyline3D.join_segments(l_segs, 0.01) assert len(p_lines) == 1 assert isinstance(p_lines[0], Polyline3D) assert len(p_lines[0]) == 5 assert p_lines[0].is_closed(0.01) l_segs = (LineSegment3D.from_end_points(pts[0], pts[1]), LineSegment3D.from_end_points(pts[2], pts[3]), LineSegment3D.from_end_points(pts[1], pts[2]), LineSegment3D.from_end_points(pts[3], pts[0])) p_lines = Polyline3D.join_segments(l_segs, 0.01) assert len(p_lines) == 1 assert isinstance(p_lines[0], Polyline3D) assert len(p_lines[0]) == 5 assert p_lines[0].is_closed(0.01) l_segs = (LineSegment3D.from_end_points(pts[0], pts[1]), LineSegment3D.from_end_points(pts[1], pts[2]), LineSegment3D.from_end_points(pts[0], pts[3]), LineSegment3D.from_end_points(pts[3], pts[2])) p_lines = Polyline3D.join_segments(l_segs, 0.01) assert len(p_lines) == 1 assert isinstance(p_lines[0], Polyline3D) assert len(p_lines[0]) == 5 assert p_lines[0].is_closed(0.01)
def test_extract_rectangle(): """Test the Face3D extract_rectangle method.""" pts_1 = [ Point3D(0, 0, 0), Point3D(0, 0, 2), Point3D(2, 0, 2), Point3D(2, 0, 0) ] pts_2 = [pt for pt in reversed(pts_1)] pts_3 = [ Point3D(0, 0, 0), Point3D(0, 0, 2), Point3D(2, 0, 2), Point3D(4, 0, 0) ] pts_4 = [ Point3D(-2, 0, 0), Point3D(0, 0, 2), Point3D(2, 0, 2), Point3D(4, 0, 0) ] pts_5 = [ Point3D(0, 0, 0), Point3D(-2, 0, 2), Point3D(4, 0, 2), Point3D(2, 0, 0) ] pts_6 = [ Point3D(0, 0, 0), Point3D(0, 0, 2), Point3D(1, 0, 3), Point3D(2, 0, 2), Point3D(2, 0, 0) ] pts_7 = [ Point3D(-2, 0, 0), Point3D(0, 0, 2), Point3D(2, 0, 2), Point3D(-1, 0, 0) ] plane = Plane(Vector3D(0, 1, 0)) face_1 = Face3D(pts_1, plane) face_2 = Face3D(pts_2, plane) face_3 = Face3D(pts_3, plane) face_4 = Face3D(pts_4, plane) face_5 = Face3D(pts_5, plane) face_6 = Face3D(pts_6, plane) face_7 = Face3D(pts_7, plane) f1_result = face_1.extract_rectangle(0.0001) assert f1_result[0] == LineSegment3D.from_end_points( Point3D(2, 0, 0), Point3D(0, 0, 0)) assert f1_result[1] == LineSegment3D.from_end_points( Point3D(2, 0, 2), Point3D(0, 0, 2)) assert len(f1_result[2]) == 0 f2_result = face_2.extract_rectangle(0.0001) assert f2_result[0] == LineSegment3D.from_end_points( Point3D(2, 0, 0), Point3D(0, 0, 0)) assert f2_result[1] == LineSegment3D.from_end_points( Point3D(2, 0, 2), Point3D(0, 0, 2)) assert len(f2_result[2]) == 0 f3_result = face_3.extract_rectangle(0.0001) assert f3_result[0] == LineSegment3D.from_end_points( Point3D(2, 0, 0), Point3D(0, 0, 0)) assert f3_result[1] == LineSegment3D.from_end_points( Point3D(2, 0, 2), Point3D(0, 0, 2)) assert len(f3_result[2]) == 1 f4_result = face_4.extract_rectangle(0.0001) assert f4_result[0] == LineSegment3D.from_end_points( Point3D(2, 0, 0), Point3D(0, 0, 0)) assert f4_result[1] == LineSegment3D.from_end_points( Point3D(2, 0, 2), Point3D(0, 0, 2)) assert len(f4_result[2]) == 2 f5_result = face_5.extract_rectangle(0.0001) assert f5_result[0] == LineSegment3D.from_end_points( Point3D(2, 0, 0), Point3D(0, 0, 0)) assert f5_result[1] == LineSegment3D.from_end_points( Point3D(2, 0, 2), Point3D(0, 0, 2)) assert len(f5_result[2]) == 2 f6_result = face_6.extract_rectangle(0.0001) assert f6_result[0] == LineSegment3D.from_end_points( Point3D(2, 0, 0), Point3D(0, 0, 0)) assert f6_result[1] == LineSegment3D.from_end_points( Point3D(2, 0, 2), Point3D(0, 0, 2)) assert len(f6_result[2]) == 1 f7_result = face_7.extract_rectangle(0.0001) assert f7_result is None
def test_join_segments_multiple_pline(): """Test the join_segments method with multiple polylines.""" pts = (Point3D(0, 0), Point3D(2, 0), Point3D(2, 2), Point3D(0, 2)) extra_pts = (Point3D(3, 3), Point3D(4, 3), Point3D(4, 4), Point3D(3, 4)) l_segs = (LineSegment3D.from_end_points(extra_pts[0], extra_pts[1]), LineSegment3D.from_end_points(pts[0], pts[1]), LineSegment3D.from_end_points(pts[1], pts[2]), LineSegment3D.from_end_points(pts[0], pts[3]), LineSegment3D.from_end_points(pts[3], pts[2])) p_lines = Polyline3D.join_segments(l_segs, 0.01) assert len(p_lines) == 2 l_segs = (LineSegment3D.from_end_points(extra_pts[0], extra_pts[1]), LineSegment3D.from_end_points(pts[0], pts[1]), LineSegment3D.from_end_points(pts[1], pts[2]), LineSegment3D.from_end_points(pts[0], pts[3]), LineSegment3D.from_end_points(pts[3], pts[2]), LineSegment3D.from_end_points(extra_pts[2], extra_pts[3]), LineSegment3D.from_end_points(extra_pts[1], extra_pts[2]), LineSegment3D.from_end_points(extra_pts[0], extra_pts[3])) p_lines = Polyline3D.join_segments(l_segs, 0.01) assert len(p_lines) == 2 for p_line in p_lines: assert isinstance(p_line, Polyline3D) assert len(p_line) == 5 assert p_line.is_closed(0.01)