def test_reflect(): """Test the Shade reflect method.""" pts = (Point3D(1, 1, 2), Point3D(2, 1, 2), Point3D(2, 2, 2), Point3D(1, 2, 2)) plane = Plane(Vector3D(0, 0, 1), Point3D(0, 0, 2)) shade = Shade('RectangleShade', Face3D(pts, plane)) origin_1 = Point3D(1, 0, 2) origin_2 = Point3D(0, 0, 2) normal_1 = Vector3D(1, 0, 0) normal_2 = Vector3D(-1, -1, 0).normalize() plane_1 = Plane(normal_1, origin_1) plane_2 = Plane(normal_2, origin_2) plane_3 = Plane(normal_2, origin_1) test_1 = shade.duplicate() test_1.reflect(plane_1) assert test_1.geometry[-1].x == pytest.approx(1, rel=1e-3) assert test_1.geometry[-1].y == pytest.approx(1, rel=1e-3) assert test_1.geometry[-1].z == pytest.approx(2, rel=1e-3) assert test_1.geometry[1].x == pytest.approx(0, rel=1e-3) assert test_1.geometry[1].y == pytest.approx(2, rel=1e-3) assert test_1.geometry[1].z == pytest.approx(2, rel=1e-3) test_1 = shade.duplicate() test_1.reflect(plane_2) assert test_1.geometry[-1].x == pytest.approx(-1, rel=1e-3) assert test_1.geometry[-1].y == pytest.approx(-1, rel=1e-3) assert test_1.geometry[-1].z == pytest.approx(2, rel=1e-3) assert test_1.geometry[1].x == pytest.approx(-2, rel=1e-3) assert test_1.geometry[1].y == pytest.approx(-2, rel=1e-3) assert test_1.geometry[1].z == pytest.approx(2, rel=1e-3) test_2 = shade.duplicate() test_2.reflect(plane_3) assert test_2.geometry[-1].x == pytest.approx(0, rel=1e-3) assert test_2.geometry[-1].y == pytest.approx(0, rel=1e-3) assert test_2.geometry[-1].z == pytest.approx(2, rel=1e-3) assert test_2.geometry[1].x == pytest.approx(-1, rel=1e-3) assert test_2.geometry[1].y == pytest.approx(-1, rel=1e-3) assert test_2.geometry[1].z == pytest.approx(2, rel=1e-3)
def test_polyface3d_init_from_offset_face_hexagon(): """Test the initalization of Poyface3D from_offset_face.""" face = Face3D.from_regular_polygon(6, 2) polyface = Polyface3D.from_offset_face(face, 2) assert len(polyface.vertices) == 12 assert len(polyface.face_indices) == 8 assert len(polyface.faces) == 8 assert len(polyface.edge_indices) == 18 assert len(polyface.edges) == 18 assert len(polyface.naked_edges) == 0 assert len(polyface.non_manifold_edges) == 0 assert len(polyface.internal_edges) == 18 assert polyface.area == pytest.approx(44.784609, rel=1e-3) assert polyface.volume == pytest.approx(20.78460, rel=1e-3) assert polyface.is_solid assert polyface.faces[0].normal.z == pytest.approx(-1, rel=1e-3) assert polyface.faces[-1].normal.z == pytest.approx(1, rel=1e-3) for face in polyface.faces: assert not face.is_clockwise
def test_energy_properties(): """Test the existence of the Room2D energy properties.""" pts = (Point3D(0, 0, 3), Point3D(10, 0, 3), Point3D(10, 10, 3), Point3D(0, 10, 3)) ashrae_base = SimpleWindowRatio(0.4) overhang = Overhang(1) boundarycs = (bcs.outdoors, bcs.ground, bcs.outdoors, bcs.ground) window = (ashrae_base, None, ashrae_base, None) shading = (overhang, None, None, None) room = Room2D('SquareShoebox', Face3D(pts), 3, boundarycs, window, shading) room.properties.energy.program_type = office_program room.properties.energy.add_default_ideal_air() assert hasattr(room.properties, 'energy') assert isinstance(room.properties.energy, Room2DEnergyProperties) assert isinstance(room.properties.energy.construction_set, ConstructionSet) assert isinstance(room.properties.energy.program_type, ProgramType) assert isinstance(room.properties.energy.hvac, IdealAirSystem) assert room.properties.energy.program_type == office_program assert room.properties.energy.is_conditioned
def test_door_init(): """Test the initialization of Door objects.""" pts = (Point3D(0, 0, 0), Point3D(0, 0, 3), Point3D(1, 0, 3), Point3D(1, 0, 0)) unique_id = str(py_uuid.uuid4()) door = Door(unique_id, Face3D(pts)) door.display_name = 'Test Door' str(door) # test the string representation assert door.identifier == unique_id assert door.display_name == 'Test Door' assert isinstance(door.geometry, Face3D) assert len(door.vertices) == 4 assert door.upper_left_vertices[0] == Point3D(1, 0, 3) assert len(door.triangulated_mesh3d.faces) == 2 assert door.normal == Vector3D(0, 1, 0) assert door.center == Point3D(0.5, 0, 1.5) assert door.area == 3 assert door.perimeter == 8 assert isinstance(door.boundary_condition, Outdoors) assert not door.has_parent
def test_doors_by_identifier(): """Test the doors_by_identifier method.""" room = Room.from_box('TinyHouseZone', 5, 10, 3) north_face = room[1] door_verts = [ Point3D(2, 10, 0.1), Point3D(1, 10, 0.1), Point3D(1, 10, 2.5), Point3D(2, 10, 2.5) ] door = Door('FrontDoor', Face3D(door_verts)) north_face.add_door(door) model = Model('TinyHouse', [room]) assert len(model.doors_by_identifier(['FrontDoor'])) == 1 with pytest.raises(ValueError): model.doors_by_identifier(['NotADoor']) model.remove_assigned_doors() with pytest.raises(ValueError): model.shades_by_identifier(['FrontDoor'])
def from_dict(cls, data): """Initialize an ContextShade from a dictionary. Args: data: A dictionary representation of an ContextShade object. """ # check the type of dictionary assert data['type'] == 'ContextShade', 'Expected ContextShade dictionary. ' \ 'Got {}.'.format(data['type']) geometry = tuple( Face3D.from_dict(shd_geo) for shd_geo in data['geometry']) shade = cls(data['identifier'], geometry) if 'display_name' in data and data['display_name'] is not None: shade.display_name = data['display_name'] if 'user_data' in data and data['user_data'] is not None: shade.user_data = data['user_data'] if data['properties']['type'] == 'ContextShadeProperties': shade.properties._load_extension_attr_from_dict(data['properties']) return shade
def from_dict(cls, data): """Initialize an Shade from a dictionary. Args: data: A dictionary representation of an Shade object. """ # check the type of dictionary assert data['type'] == 'Shade', 'Expected Shade dictionary. ' \ 'Got {}.'.format(data['type']) is_detached = data['is_detached'] if 'is_detached' in data else False shade = cls(data['identifier'], Face3D.from_dict(data['geometry']), is_detached) if 'display_name' in data and data['display_name'] is not None: shade.display_name = data['display_name'] if 'user_data' in data and data['user_data'] is not None: shade.user_data = data['user_data'] if data['properties']['type'] == 'ShadeProperties': shade.properties._load_extension_attr_from_dict(data['properties']) return shade
def from_dict(cls, _dict): new_obj = cls() new_obj.quantity = _dict.get('quantity') new_obj._tolerance = _dict.get('_tolerance') new_obj.aperture = Aperture.from_dict( _dict.get('aperture') ) new_obj._shading_factor_winter =_dict.get('_shading_factor_winter') new_obj._shading_factor_summer =_dict.get('_shading_factor_summer') new_obj._glazing_edge_lengths = _dict.get('_glazing_edge_lengths') new_obj.variant_type = _dict.get('variant_type') new_obj.install_depth = _dict.get('install_depth') #---- _edges = _dict.get('_window_edges', {}) _left = _edges.get('Left') _left = LineSegment3D.from_dict( _left ) _right = _edges.get('Right') _right = LineSegment3D.from_dict( _right ) _bottom = _edges.get('Bottom') _bottom = LineSegment3D.from_dict( _bottom ) _top = _edges.get('Top') _top = LineSegment3D.from_dict( _top ) new_obj._window_edges = cls.Output(_left, _right, _bottom, _top) #---- _glazing_surface = _dict.get('_glazing_surface') _glazing_surface = Face3D.from_dict(_glazing_surface) _glazing_surface = from_face3d(_glazing_surface) new_obj._glazing_surface = _glazing_surface new_obj.frame = LBT2PH.windows.PHPP_Frame.from_dict( _dict.get('_frame') ) new_obj.glazing = LBT2PH.windows.PHPP_Glazing.from_dict( _dict.get('_glazing') ) new_obj.installs = LBT2PH.windows.PHPP_Installs.from_dict( _dict.get('_installs') ) new_obj.shading_dimensions = LBT2PH.shading.PHPP_Shading_Dims.from_dict( _dict.get('shading_dimensions') ) return new_obj
def test_reflect(): """Test the Room2D reflect method.""" pts = (Point3D(1, 1, 2), Point3D(2, 1, 2), Point3D(2, 2, 2), Point3D(1, 2, 2)) plane = Plane(Vector3D(0, 0, 1), Point3D(0, 0, 2)) room = Room2D('SquareShoebox', Face3D(pts, plane), 3) origin_1 = Point3D(1, 0, 2) origin_2 = Point3D(0, 0, 2) normal_1 = Vector3D(1, 0, 0) normal_2 = Vector3D(-1, -1, 0).normalize() plane_1 = Plane(normal_1, origin_1) plane_2 = Plane(normal_2, origin_2) plane_3 = Plane(normal_2, origin_1) test_1 = room.duplicate() test_1.reflect(plane_1) assert test_1.floor_geometry[-1].x == pytest.approx(1, rel=1e-3) assert test_1.floor_geometry[-1].y == pytest.approx(1, rel=1e-3) assert test_1.floor_geometry[-1].z == pytest.approx(2, rel=1e-3) assert test_1.floor_geometry[1].x == pytest.approx(0, rel=1e-3) assert test_1.floor_geometry[1].y == pytest.approx(2, rel=1e-3) assert test_1.floor_geometry[1].z == pytest.approx(2, rel=1e-3) test_1 = room.duplicate() test_1.reflect(plane_2) assert test_1.floor_geometry[-1].x == pytest.approx(-1, rel=1e-3) assert test_1.floor_geometry[-1].y == pytest.approx(-1, rel=1e-3) assert test_1.floor_geometry[-1].z == pytest.approx(2, rel=1e-3) assert test_1.floor_geometry[1].x == pytest.approx(-2, rel=1e-3) assert test_1.floor_geometry[1].y == pytest.approx(-2, rel=1e-3) assert test_1.floor_geometry[1].z == pytest.approx(2, rel=1e-3) test_2 = room.duplicate() test_2.reflect(plane_3) assert test_2.floor_geometry[-1].x == pytest.approx(0, rel=1e-3) assert test_2.floor_geometry[-1].y == pytest.approx(0, rel=1e-3) assert test_2.floor_geometry[-1].z == pytest.approx(2, rel=1e-3) assert test_2.floor_geometry[1].x == pytest.approx(-1, rel=1e-3) assert test_2.floor_geometry[1].y == pytest.approx(-1, rel=1e-3) assert test_2.floor_geometry[1].z == pytest.approx(2, rel=1e-3)
def test_init_coplanar(): """Test the initialization of a room with coplanar faces.""" pts_1 = [Point3D(0, 0, 0), Point3D(0, 10, 0), Point3D(10, 10, 0), Point3D(10, 0, 0)] pts_2 = [Point3D(0, 0, 0), Point3D(0, 0, 3), Point3D(0, 10, 3), Point3D(0, 10, 0)] pts_3 = [Point3D(0, 0, 0), Point3D(10, 0, 0), Point3D(10, 0, 3), Point3D(0, 0, 3)] pts_4 = [Point3D(10, 10, 0), Point3D(0, 10, 0), Point3D(0, 10, 3), Point3D(10, 10, 3)] pts_5 = [Point3D(10, 10, 0), Point3D(10, 0, 0), Point3D(10, 0, 3), Point3D(10, 10, 3)] pts_6 = [Point3D(10, 0, 3), Point3D(10, 2.5, 3), Point3D(0, 2.5, 3), Point3D(0, 0, 3)] pts_7 = [Point3D(10, 2.5, 3), Point3D(10, 5, 3), Point3D(0, 5, 3), Point3D(0, 2.5, 3)] pts_8 = [Point3D(10, 5, 3), Point3D(10, 10, 3), Point3D(0, 10, 3), Point3D(0, 5, 3)] face_1 = Face('Face 1', Face3D(pts_1)) face_2 = Face('Face 2', Face3D(pts_2)) face_3 = Face('Face 3', Face3D(pts_3)) face_4 = Face('Face 4', Face3D(pts_4)) face_5 = Face('Face 5', Face3D(pts_5)) face_6 = Face('Face 6', Face3D(pts_6)) face_7 = Face('Face 7', Face3D(pts_7)) face_8 = Face('Face 8', Face3D(pts_8)) room = Room('Zone: SHOE_BOX [920980]', [face_1, face_2, face_3, face_4, face_5, face_6, face_7, face_8], 0.01, 1) str(room) # test the string representation of the room assert room.name == 'ZoneSHOE_BOX920980' assert room.display_name == 'Zone: SHOE_BOX [920980]' assert isinstance(room.geometry, Polyface3D) assert len(room.geometry.vertices) == 12 assert len(room) == 8 assert room.center == Point3D(5, 5, 1.5) assert room.volume == 300 assert room.floor_area == 100 assert room.exposed_area == 220 assert room.exterior_wall_area == 120 assert room.exterior_aperture_area == 0 assert room.average_floor_height == 0 assert not room.has_parent assert room.check_solid(0.01, 1)
def test_triangulated_doors(): """Test the triangulated_doors method.""" room = Room.from_box('Tiny House Zone', 5, 10, 3) north_face = room[1] door_verts = [Point3D(2, 10, 0.1), Point3D(1, 10, 0.1), Point3D(1, 10, 2.5), Point3D(1.5, 10, 2.8), Point3D(2, 10, 2.5)] door = Door('Front Door', Face3D(door_verts)) north_face.add_door(door) model = Model('Tiny House', [room]) triangulated_doors, parents_to_edit = model.triangulated_doors() assert len(triangulated_doors) == 1 assert len(parents_to_edit) == 1 assert len(triangulated_doors[0]) == 3 assert len(parents_to_edit[0]) == 3 parents_to_edit[0][0] == door.name parents_to_edit[0][1] == north_face.name for dr in triangulated_doors[0]: assert isinstance(dr, Door) assert len(dr.geometry) == 3
def test_polyface3d_init_from_polyface(): """Test the initalization of room from a Poyface3D.""" bound_pts = [Point3D(0, 0), Point3D(3, 0), Point3D(3, 3), Point3D(0, 3)] hole_pts = [Point3D(1, 1, 0), Point3D(2, 1, 0), Point3D(2, 2, 0), Point3D(1, 2, 0)] face = Face3D(bound_pts, None, [hole_pts]) polyface = Polyface3D.from_offset_face(face, 3) room = Room.from_polyface3d('Donut Zone', polyface) assert room.name == 'DonutZone' assert room.display_name == 'Donut Zone' assert isinstance(room.geometry, Polyface3D) assert len(room.geometry.vertices) == 16 assert len(room) == 10 assert room.center == Point3D(1.5, 1.5, 1.5) assert room.volume == 24 assert room.floor_area == 8 assert room.exposed_area == 56 assert room.exterior_wall_area == 48 assert room.exterior_aperture_area == 0 assert room.average_floor_height == 0 assert not room.has_parent assert room.check_solid(0.01, 1)
def test_move(): """Test the Face3D move method.""" pts_1 = (Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(2, 2, 0), Point3D(0, 2, 0)) plane_1 = Plane(Vector3D(0, 0, 1), Point3D(0, 0, 0)) face_1 = Face3D(pts_1, plane_1) vec_1 = Vector3D(2, 2, 2) new_face = face_1.move(vec_1) assert new_face[0] == Point3D(2, 2, 2) assert new_face[1] == Point3D(4, 2, 2) assert new_face[2] == Point3D(4, 4, 2) assert new_face[3] == Point3D(2, 4, 2) assert new_face.plane.o == face_1.plane.o.move(vec_1) assert new_face.plane.n == face_1.plane.n assert face_1.area == new_face.area assert face_1.perimeter == new_face.perimeter assert face_1.is_clockwise is new_face.is_clockwise assert face_1.is_convex is new_face.is_convex assert face_1.is_self_intersecting is new_face.is_self_intersecting assert new_face.normal == face_1.normal
def from_dict(cls, data): """Initialize an Face from a dictionary. Args: data: A dictionary representation of an Face object. """ # check the type of dictionary assert data['type'] == 'Face', 'Expected Face dictionary. ' \ 'Got {}.'.format(data['type']) face_type = face_types.by_name(data['face_type']) try: bc_class = getattr(hbc, data['boundary_condition']['type']) except AttributeError: raise ValueError( 'Boundary condition "{}" is not supported in this honyebee ' 'installation.'.format(data['boundary_condition']['type'])) bc = bc_class.from_dict(data['boundary_condition']) face = cls(data['name'], Face3D.from_dict(data['geometry']), face_type, bc) if 'display_name' in data and data['display_name'] is not None: face._display_name = data['display_name'] # add sub-faces and shades to faces if 'apertures' in data and data['apertures'] is not None: face._apertures = [ Aperture.from_dict(ap) for ap in data['apertures'] ] for ap in face._apertures: ap._parent = face if 'doors' in data and data['doors'] is not None: face._doors = [Door.from_dict(dr) for dr in data['doors']] for dr in face._doors: dr._parent = face face._recover_shades_from_dict(data) if data['properties']['type'] == 'FaceProperties': face.properties._load_extension_attr_from_dict(data['properties']) return face
def test_aperture_init(): """Test the initialization of Aperture objects.""" pts = (Point3D(0, 0, 0), Point3D(0, 0, 3), Point3D(5, 0, 3), Point3D(5, 0, 0)) unique_id = str(py_uuid.uuid4()) aperture = Aperture(unique_id, Face3D(pts)) aperture.display_name = 'Test Window' str(aperture) # test the string representation assert aperture.identifier == unique_id assert aperture.display_name == 'Test Window' assert isinstance(aperture.geometry, Face3D) assert len(aperture.vertices) == 4 assert aperture.upper_left_vertices[0] == Point3D(5, 0, 3) assert len(aperture.triangulated_mesh3d.faces) == 2 assert aperture.normal == Vector3D(0, 1, 0) assert aperture.center == Point3D(2.5, 0, 1.5) assert aperture.area == 15 assert aperture.perimeter == 16 assert isinstance(aperture.boundary_condition, Outdoors) assert not aperture.is_operable assert not aperture.has_parent
def test_init(): """Test the initialization of a Face.""" vertices = [ Point3D(0, 0, 0), Point3D(0, 10, 0), Point3D(0, 10, 3), Point3D(0, 0, 3) ] face = Face('Wall: SIM_INT_AIR [920980]', Face3D(vertices)) assert face.name == 'WallSIM_INT_AIR920980' assert face.display_name == 'Wall: SIM_INT_AIR [920980]' assert isinstance(face.geometry, Face3D) assert len(face.vertices) == 4 assert face.upper_left_vertices[0] == Point3D(0, 0, 3) assert face.normal == Vector3D(1, 0, 0) assert face.center == Point3D(0, 5, 1.5) assert face.area == 30 assert face.perimeter == 26 assert isinstance(face.boundary_condition, Outdoors) assert isinstance(face.type, Wall) assert not face.has_parent
def test_set_program_type(): """Test the setting of a ProgramType on a Room2D.""" lab_equip_day = ScheduleDay( 'Daily Lab Equipment', [0.25, 0.5, 0.25], [Time(0, 0), Time(9, 0), Time(20, 0)]) lab_equipment = ScheduleRuleset('Lab Equipment', lab_equip_day, None, schedule_types.fractional) lab_vent_day = ScheduleDay( 'Daily Lab Ventilation', [0.5, 1, 0.5], [Time(0, 0), Time(9, 0), Time(20, 0)]) lab_ventilation = ScheduleRuleset('Lab Ventilation', lab_vent_day, None, schedule_types.fractional) lab_program = office_program.duplicate() lab_program.identifier = 'Bio Laboratory' lab_program.electric_equipment.watts_per_area = 50 lab_program.electric_equipment.schedule = lab_equipment lab_program.ventilation.flow_per_person = 0 lab_program.ventilation.flow_per_area = 0 lab_program.ventilation.air_changes_per_hour = 6 lab_program.ventilation.schedule = lab_ventilation pts = (Point3D(0, 0, 3), Point3D(10, 0, 3), Point3D(10, 10, 3), Point3D(0, 10, 3)) ashrae_base = SimpleWindowRatio(0.4) room = Room2D('SquareShoebox', Face3D(pts), 3) room.set_outdoor_window_parameters(ashrae_base) room.properties.energy.program_type = lab_program assert room.properties.energy.program_type.identifier == 'Bio Laboratory' assert room.properties.energy.program_type == lab_program hb_room, adj = room.to_honeybee() assert hb_room.properties.energy.electric_equipment.watts_per_area == 50 assert hb_room.properties.energy.electric_equipment.schedule == lab_equipment assert hb_room.properties.energy.ventilation.flow_per_person == 0 assert hb_room.properties.energy.ventilation.flow_per_area == 0 assert hb_room.properties.energy.ventilation.air_changes_per_hour == 6 assert hb_room.properties.energy.ventilation.schedule == lab_ventilation
def test_countour_fins_by_number(): """Test the countour_fins_by_number method.""" pts_1 = [ Point3D(0, 0, 0), Point3D(0, 0, 2), Point3D(2, 0, 2), Point3D(2, 0, 0) ] plane = Plane(Vector3D(0, 1, 0)) face_1 = Face3D(pts_1, plane) fins = face_1.countour_fins_by_number(4, 0.5, 0.5) assert len(fins) == 4 fins = face_1.countour_fins_by_number(4, 0.5, 0.5, contour_vector=Vector3D(1)) assert len(fins) == 4 fins = face_1.countour_fins_by_number(4, 0.5, 0.5, math.pi / 4) assert len(fins) == 4
def test_triangulated_apertures(): """Test the triangulated_apertures method.""" room = Room.from_box('Tiny House Zone', 5, 10, 3) north_face = room[1] aperture_verts = [Point3D(4.5, 10, 1), Point3D(2.5, 10, 1), Point3D(2.5, 10, 2.5), Point3D(3.5, 10, 2.9), Point3D(4.5, 10, 2.5)] aperture = Aperture('Front Aperture', Face3D(aperture_verts)) north_face.add_aperture(aperture) model = Model('Tiny House', [room]) triangulated_apertures, parents_to_edit = model.triangulated_apertures() assert len(triangulated_apertures) == 1 assert len(parents_to_edit) == 1 assert len(triangulated_apertures[0]) == 3 assert len(parents_to_edit[0]) == 3 parents_to_edit[0][0] == aperture.name parents_to_edit[0][1] == north_face.name for ap in triangulated_apertures[0]: assert isinstance(ap, Aperture) assert len(ap.geometry) == 3
def test_polyface3d_init_from_faces_coplanar_3face(): """Test the initialization of Polyface3D from_faces with three coplanar faces.""" # this is an important case that must be solved # can be done by iterating through naked edges and finding colinear ones pts_1 = [Point3D(0, 0, 0), Point3D(0, 2, 0), Point3D(2, 2, 0), Point3D(2, 0, 0)] pts_2 = [Point3D(0, 0, 0), Point3D(0, 0, 2), Point3D(0, 2, 2), Point3D(0, 2, 0)] pts_3 = [Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(2, 0, 2), Point3D(0, 0, 2)] pts_4 = [Point3D(2, 2, 0), Point3D(0, 2, 0), Point3D(0, 2, 2), Point3D(2, 2, 2)] pts_5 = [Point3D(2, 2, 0), Point3D(2, 0, 0), Point3D(2, 0, 2), Point3D(2, 2, 2)] pts_6 = [Point3D(0, 0, 2), Point3D(0, 0.5, 2), Point3D(2, 0.5, 2), Point3D(2, 0, 2)] pts_7 = [Point3D(0, 0.5, 2), Point3D(0, 1, 2), Point3D(2, 1, 2), Point3D(2, 0.5, 2)] pts_8 = [Point3D(0, 1, 2), Point3D(0, 2, 2), Point3D(2, 2, 2), Point3D(2, 1, 2)] face_1 = Face3D(pts_1) face_2 = Face3D(pts_2) face_3 = Face3D(pts_3) face_4 = Face3D(pts_4) face_5 = Face3D(pts_5) face_6 = Face3D(pts_6) face_7 = Face3D(pts_7) face_8 = Face3D(pts_8) polyface = Polyface3D.from_faces( [face_1, face_2, face_3, face_4, face_5, face_6, face_7, face_8], 0.01) polyface_2 = Polyface3D.from_faces( [face_1, face_2, face_3, face_4, face_5, face_6, face_8], 0.01) assert not polyface.is_solid assert len(polyface.naked_edges) != 0 new_polyface = polyface.merge_overlapping_edges(0.0001, 0.0001) assert new_polyface.is_solid assert len(new_polyface.naked_edges) == 0 assert len(new_polyface.internal_edges) == 14 new_polyface_2 = polyface_2.merge_overlapping_edges(0.0001, 0.0001) assert not new_polyface_2.is_solid assert len(new_polyface_2.naked_edges) != 0
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 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. """ wall_plane = face.geometry.plane # loop through each window and create its geometry for i, polygon in enumerate(self.polygons): pt3d = tuple(wall_plane.xy_to_xyz(pt) for pt in polygon) aperture = Aperture('{}_Glz{}'.format(face.identifier, i + 1), Face3D(pt3d)) 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_from_dict(): """Test the Shade from_dict method with energy properties.""" verts = [ Point3D(0, 0, 0), Point3D(1, 0, 0), Point3D(1, 0, 3), Point3D(0, 0, 3) ] shade = Shade('overhang', Face3D(verts)) light_shelf = ShadeConstruction('Light Shelf', 0.5, 0.5, True) shade.properties.energy.construction = light_shelf fritted_glass_trans = ScheduleRuleset.from_constant_value( 'Fritted Glass', 0.5, schedule_types.fractional) shade.properties.energy.transmittance_schedule = fritted_glass_trans shade_dict = shade.to_dict() new_shade = Shade.from_dict(shade_dict) assert new_shade.properties.energy.construction == light_shelf assert shade.properties.energy.construction.solar_reflectance == 0.5 assert shade.properties.energy.construction.visible_reflectance == 0.5 assert shade.properties.energy.construction.is_specular assert new_shade.properties.energy.transmittance_schedule == fritted_glass_trans assert new_shade.to_dict() == shade_dict
def test_aperture_louvers_by_distance_between(): """Test the creation of a louvers_by_distance_between for Aperture objects.""" pts_1 = (Point3D(0, 0, 0), Point3D(0, 0, 3), Point3D(5, 0, 3), Point3D(5, 0, 0)) aperture = Aperture('RectangleWindow', Face3D(pts_1)) aperture.louvers_by_distance_between(0.5, 0.2, 0.1) assert len(aperture.outdoor_shades) == 6 for louver in aperture.outdoor_shades: assert isinstance(louver, Shade) assert louver.area == 5 * 0.2 assert louver.has_parent aperture.remove_shades() aperture.louvers_by_distance_between(0.5, 0.2, 0.1, max_count=3) assert len(aperture.outdoor_shades) == 3 for louver in aperture.outdoor_shades: assert isinstance(louver, Shade) assert louver.area == 5 * 0.2 assert louver.has_parent aperture.remove_shades() aperture.louvers_by_distance_between(0.5, 0.2, 0.1, max_count=10) assert len(aperture.outdoor_shades) == 6
def test_model_init(): """Test the initialization of Model objects and basic properties.""" pts_1 = (Point3D(0, 0, 3), Point3D(0, 10, 3), Point3D(10, 10, 3), Point3D(10, 0, 3)) pts_2 = (Point3D(10, 0, 3), Point3D(10, 10, 3), Point3D(20, 10, 3), Point3D(20, 0, 3)) pts_3 = (Point3D(0, 10, 3), Point3D(0, 20, 3), Point3D(10, 20, 3), Point3D(10, 10, 3)) pts_4 = (Point3D(10, 10, 3), Point3D(10, 20, 3), Point3D(20, 20, 3), Point3D(20, 10, 3)) room2d_1 = Room2D('Office1', Face3D(pts_1), 3) room2d_2 = Room2D('Office2', Face3D(pts_2), 3) room2d_3 = Room2D('Office3', Face3D(pts_3), 3) room2d_4 = Room2D('Office4', Face3D(pts_4), 3) story = Story('Office_Floor', [room2d_1, room2d_2, room2d_3, room2d_4]) story.solve_room_2d_adjacency(0.01) story.set_outdoor_window_parameters(SimpleWindowRatio(0.4)) story.multiplier = 4 building = Building('Office_Building', [story]) tree_canopy_geo1 = Face3D.from_regular_polygon(6, 6, Plane(o=Point3D(5, -10, 6))) tree_canopy_geo2 = Face3D.from_regular_polygon(6, 2, Plane(o=Point3D(-5, -10, 3))) tree_canopy = ContextShade('Tree_Canopy', [tree_canopy_geo1, tree_canopy_geo2]) model = Model('New_Development', [building], [tree_canopy]) str(model) # test the string representation of the object assert model.identifier == 'New_Development' assert model.display_name == 'New_Development' assert model.units == 'Meters' assert model.tolerance == 0.01 assert model.angle_tolerance == 1.0 assert len(model.buildings) == 1 assert isinstance(model.buildings[0], Building) assert len(model.context_shades) == 1 assert isinstance(model.context_shades[0], ContextShade) assert model.average_story_count == 4 assert model.average_story_count_above_ground == 4 assert model.average_height == 15 assert model.average_height_above_ground == 12 assert model.footprint_area == 100 * 4 assert model.floor_area == 100 * 4 * 4 assert model.exterior_wall_area == 60 * 4 * 4 assert model.exterior_aperture_area == 60 * 4 * 4 * 0.4 assert model.volume == 100 * 3 * 4 * 4 assert model.min.x == pytest.approx(-6.73, rel=1e-2) assert model.min.y == pytest.approx(-16, rel=1e-2) assert model.max == Point2D(20, 20)
def test_duplicate(): """Test what happens to energy properties when duplicating a Face.""" verts = [Point3D(0, 0, 0), Point3D(10, 0, 0), Point3D(10, 0, 10), Point3D(0, 0, 10)] concrete20 = EnergyMaterial('20cm Concrete', 0.2, 2.31, 2322, 832, 'MediumRough', 0.95, 0.75, 0.8) thick_constr = OpaqueConstruction( 'Thick Concrete Construction', [concrete20]) face_original = Face('wall_face', Face3D(verts)) face_original.properties.energy.vent_crack = AFNCrack(0.00001, 0.65) face_dup_1 = face_original.duplicate() assert face_original.properties.energy.host is face_original assert face_dup_1.properties.energy.host is face_dup_1 assert face_original.properties.energy.host is not face_dup_1.properties.energy.host assert face_original.properties.energy.construction == \ face_dup_1.properties.energy.construction assert face_original.properties.energy.vent_crack == \ face_dup_1.properties.energy.vent_crack face_dup_1.properties.energy.construction = thick_constr face_dup_1.properties.energy.vent_crack = AFNCrack(0.001, 0.7) assert face_original.properties.energy.construction != \ face_dup_1.properties.energy.construction assert face_original.properties.energy.vent_crack != \ face_dup_1.properties.energy.vent_crack face_dup_2 = face_dup_1.duplicate() assert face_dup_1.properties.energy.construction == \ face_dup_2.properties.energy.construction face_dup_2.properties.energy.construction = None face_dup_2.properties.energy.vent_crack = None assert face_dup_1.properties.energy.construction != \ face_dup_2.properties.energy.construction assert face_dup_1.properties.energy.vent_crack != \ face_dup_2.properties.energy.vent_crack
def create_room(info, ext_wall, count, i): room = room_class() room.room_id = count room.surf_id = i room.geo_window = ext_wall.sub_faces_by_ratio(ratio=info.room_WWR)[0] room.geo_ene_ext_wall = ext_wall #Creating extwall for radiance w_v = room.geo_window.upper_left_counter_clockwise_vertices e_v = room.geo_ene_ext_wall.upper_left_counter_clockwise_vertices for i in range(3): face = Face3D([e_v[i], e_v[i + 1], w_v[i + 1], w_v[i]]) room.geo_rad_ext_wall_list.append(face) face = Face3D([e_v[3], e_v[0], w_v[0], w_v[3]]) room.geo_rad_ext_wall_list.append(face) # n = ext_wall.normal.normalize() points = list(ext_wall.upper_left_counter_clockwise_vertices) for i in range(4): points.append(points[i] + (-n) * info.room_dim_depth) room.geo_floor = Face3D([points[5], points[6], points[2], points[1]]) room.geo_left_wall = Face3D([points[4], points[5], points[1], points[0]]) room.geo_right_wall = Face3D([points[3], points[2], points[6], points[7]]) room.geo_back_wall = Face3D([points[7], points[6], points[5], points[4]]) room.geo_ceiling = Face3D([points[0], points[3], points[7], points[4]]) return room
def two_buildings_with_terrain(): pts_1 = (Point3D(0, 0, 3), Point3D(10, 0, 3), Point3D(10, 10, 3), Point3D(0, 10, 3)) pts_2 = (Point3D(10, 0, 3), Point3D(20, 0, 3), Point3D(20, 10, 3), Point3D(10, 10, 3)) pts_3 = (Point3D(0, 20, 3), Point3D(20, 20, 3), Point3D(20, 30, 3), Point3D(0, 30, 3)) room2d_1 = Room2D('Office1', Face3D(pts_1), 3) room2d_2 = Room2D('Office2', Face3D(pts_2), 3) room2d_3 = Room2D('Office3', Face3D(pts_3), 3) story_big = Story('OfficeFloorBig', [room2d_3]) story = Story('OfficeFloor', [room2d_1, room2d_2]) story.solve_room_2d_adjacency(0.01) story.set_outdoor_window_parameters(SimpleWindowRatio(0.3)) story.multiplier = 3 building = Building('OfficeBuilding', [story]) building.separate_top_bottom_floors() story_big.set_outdoor_window_parameters(SimpleWindowRatio(0.6)) story_big.multiplier = 4 building_big = Building('OfficeBuildingBig', [story_big]) building_big.separate_top_bottom_floors() tree_canopy_geo1 = Face3D.from_regular_polygon(6, 6, Plane(o=Point3D(5, -10, 6))) tree_canopy_geo2 = Face3D.from_regular_polygon( 6, 2, Plane(o=Point3D(-5, -10, 3))) tree_canopy = ContextShade('TreeCanopy', [tree_canopy_geo1, tree_canopy_geo2]) model = Model('NewDevelopment', [building, building_big], [tree_canopy]) ter_geo = Face3D( (Point3D(0, 0, 0), Point3D(30, 0, 0), Point3D(30, 30, 0), Point3D(0, 30, 3))) terrain = Terrain([ter_geo]) model.properties.uwg.terrain = terrain model.properties.uwg.traffic.watts_per_area = 7 model.properties.uwg.tree_coverage_fraction = 0.25 model.properties.uwg.grass_coverage_fraction = 0.4 return model
def test_model_add_objects(): """Test the addition of objects to a Model and getting objects by identifier.""" pts_1 = (Point3D(0, 0, 3), Point3D(0, 10, 3), Point3D(10, 10, 3), Point3D(10, 0, 3)) pts_2 = (Point3D(10, 0, 3), Point3D(10, 10, 3), Point3D(20, 10, 3), Point3D(20, 0, 3)) pts_3 = (Point3D(0, 20, 3), Point3D(0, 30, 3), Point3D(10, 30, 3), Point3D(10, 20, 3)) pts_4 = (Point3D(10, 20, 3), Point3D(10, 30, 3), Point3D(20, 30, 3), Point3D(20, 20, 3)) room2d_1 = Room2D('Office1', Face3D(pts_1), 3) room2d_2 = Room2D('Office2', Face3D(pts_2), 3) room2d_3 = Room2D('Office3', Face3D(pts_3), 3) room2d_4 = Room2D('Office4', Face3D(pts_4), 3) story_1 = Story('OfficeFloor1', [room2d_1, room2d_2]) story_2 = Story('OfficeFloor2', [room2d_3, room2d_4]) story_1.solve_room_2d_adjacency(0.01) story_1.set_outdoor_window_parameters(SimpleWindowRatio(0.4)) story_1.multiplier = 4 story_2.solve_room_2d_adjacency(0.01) story_2.set_outdoor_window_parameters(SimpleWindowRatio(0.4)) story_2.multiplier = 2 building_1 = Building('OfficeBuilding1', [story_1]) building_2 = Building('OfficeBuilding2', [story_2]) tree_canopy_geo1 = Face3D.from_regular_polygon(6, 6, Plane(o=Point3D(5, -10, 6))) tree_canopy_geo2 = Face3D.from_regular_polygon(6, 2, Plane(o=Point3D(-5, -10, 3))) tree_canopy_1 = ContextShade('TreeCanopy1', [tree_canopy_geo1]) tree_canopy_2 = ContextShade('TreeCanopy2', [tree_canopy_geo2]) model = Model('NewDevelopment', [building_1], [tree_canopy_1]) assert len(model.buildings) == 1 assert len(model.context_shades) == 1 with pytest.raises(AssertionError): model.add_building(tree_canopy_2) model.add_building(building_2) assert len(model.buildings) == 2 with pytest.raises(AssertionError): model.add_context_shade(building_2) model.add_context_shade(tree_canopy_2) assert len(model.context_shades) == 2 assert len(model.buildings_by_identifier(['OfficeBuilding1'])) == 1 with pytest.raises(ValueError): model.buildings_by_identifier(['NotABuilding']) assert len(model.context_shade_by_identifier(['TreeCanopy1'])) == 1 with pytest.raises(ValueError): model.context_shade_by_identifier(['NotAShade'])
def test_duplicate(): """Test what happens to energy properties when duplicating an Aperture.""" verts = [ Point3D(0, 0, 0), Point3D(10, 0, 0), Point3D(10, 0, 10), Point3D(0, 0, 10) ] clear_glass = EnergyWindowMaterialGlazing('Clear Glass', 0.005715, 0.770675, 0.07, 0.8836, 0.0804, 0, 0.84, 0.84, 1.0) gap = EnergyWindowMaterialGas('air gap', thickness=0.0127) triple_pane = WindowConstruction( 'Triple Pane', [clear_glass, gap, clear_glass, gap, clear_glass]) aperture_original = Aperture('wall window', Face3D(verts)) aperture_dup_1 = aperture_original.duplicate() assert aperture_original.properties.energy.host is aperture_original assert aperture_dup_1.properties.energy.host is aperture_dup_1 assert aperture_original.properties.energy.host is not \ aperture_dup_1.properties.energy.host assert aperture_original.properties.energy.construction == \ aperture_dup_1.properties.energy.construction aperture_dup_1.properties.energy.construction = triple_pane assert aperture_original.properties.energy.construction != \ aperture_dup_1.properties.energy.construction aperture_dup_2 = aperture_dup_1.duplicate() assert aperture_dup_1.properties.energy.construction == \ aperture_dup_2.properties.energy.construction aperture_dup_2.properties.energy.construction = None assert aperture_dup_1.properties.energy.construction != \ aperture_dup_2.properties.energy.construction