def test_xyz_to_xy(): """Test the xyz_to_xy method.""" pt = Point3D(2, 2, 2) vec = Vector3D(0, 0, 2) plane = Plane(vec, pt) test_pt = Point3D(4, 4, 2) assert plane.xyz_to_xy(test_pt) == Point2D(2, 2) test_pt = Point3D(0, 0, 2) assert plane.xyz_to_xy(test_pt) == Point2D(-2, -2) assert isinstance(plane.xyz_to_xy(test_pt), Point2D)
def aperture_by_width_height(self, width, height, sill_height=1, aperture_name=None): """Add a single rectangular aperture to the center of this face. While the resulting aperture will always be in the plane of this Face, this method will not check to ensure that the aperture has all of its vertices completely within the boundary of this Face. The are_sub_faces_valid() method can be used afterwards to check this. Args: width: A number for the Aperture width. height: A number for the Aperture height. sill_height: A number for the sill height. Default: 1. aperture_name: Optional name for the aperture. If None, the default name will follow the convention "[face_name]_Glz[count]" where [count] is one more than the current numer of apertures in the face. Returns: The new Aperture object that has been generated. Usage: room = Room.from_box(3.0, 6.0, 3.2, 180) room[1].aperture_by_width_height(2, 2, .7) # aperture in front room[2].aperture_by_width_height(4, 1.5, .5) # aperture on right room[2].aperture_by_width_height(4, 0.5, 2.2) # aperture on right """ # Perform checks self._acceptable_sub_face_check(Aperture) # Generate the aperture geometry face_plane = Plane(self._geometry.plane.n, self._geometry.min) if face_plane.y.z < 0: face_plane = face_plane.rotate(face_plane.n, math.pi, face_plane.o) center2d = face_plane.xyz_to_xy(self._geometry.center) x_dist = width / 2 lower_left = Point2D(center2d.x - x_dist, sill_height) lower_right = Point2D(center2d.x + x_dist, sill_height) upper_right = Point2D(center2d.x + x_dist, sill_height + height) upper_left = Point2D(center2d.x - x_dist, sill_height + height) ap_verts2d = (lower_left, lower_right, upper_right, upper_left) ap_verts3d = tuple(face_plane.xy_to_xyz(pt) for pt in ap_verts2d) ap_face = Face3D(ap_verts3d, self._geometry.plane) if self.normal.angle(ap_face.normal) > math.pi / 2: # reversed normal ap_face = ap_face.flip() # Create the aperture and add it to this Face name = aperture_name or '{}_Glz{}'.format(self.display_name, len(self.apertures)) aperture = Aperture(name, ap_face) aperture._parent = self self._apertures.append(aperture) return aperture