def bounding_box(self): aligned = align_face(self) top_left = Vector3D(min(aligned.xs), max(aligned.ys), max(aligned.zs)) bottom_left = Vector3D(min(aligned.xs), min(aligned.ys), min(aligned.zs)) bottom_right = Vector3D(max(aligned.xs), min(aligned.ys), min(aligned.zs)) top_right = Vector3D(max(aligned.xs), max(aligned.ys), max(aligned.zs)) bbox = Polygon3D([top_left, bottom_left, bottom_right, top_right]) return invert_align_face(self, bbox)
def is_collinear(self, other): if almostequal(other, self) or almostequal(other, -self): return True a = self.p1 - other.p1 b = self.p1 - other.p2 angle_between = a.cross(b) if almostequal(angle_between, Vector3D(0, 0, 0)): return True a = self.p2 - other.p1 b = self.p2 - other.p2 angle_between = a.cross(b) if almostequal(angle_between, Vector3D(0, 0, 0)): return True return False
def getidfplanes(surfaces): """Fast access data structure for potentially matched surfaces. Get a data structure populated with all the surfaces in the IDF, keyed by their distance from the origin, and their normal vector. Parameters ---------- surfaces : list List of all the surfaces. Returns ------- dict """ planes = {} for s in surfaces: poly = Polygon3D(s.coords) rounded_distance = round(poly.distance, 8) rounded_normal_vector = Vector3D( *[round(axis, 8) for axis in poly.normal_vector]) planes.setdefault(rounded_distance, {}).setdefault(rounded_normal_vector, []).append(s) return planes
def floors(self): """Coordinates for each floor in the block. Returns ------- list """ floors = [[self.footprint.invert_orientation() + Vector3D(0,0,fh)] for fh in self.floor_heights] return floors
def normal_vector(self): """Vector perpendicular to the polygon in the outward direction. Uses Newell's Method. Returns ------- Vector3D """ return Vector3D(*normal_vector(self.vertices))
def centroid(self): """The centroid of a polygon. Returns ------- Vector3D """ return Vector3D( sum(self.xs) / len(self), sum(self.ys) / len(self), sum(self.zs) / len(self))
def ceilings(self): """Coordinates for each ceiling in the block. Returns ------- list """ ceilings = [[self.footprint + Vector3D(0,0,ch)] for ch in self.ceiling_heights[:-1]] ceilings.append('') return ceilings
def test_align_z_prime_transformations(self): x_axis = Vector3D(1, 0, 0) y_axis = Vector3D(0, 1, 0) z_axis = Vector3D(0, 0, 1) t = Transformation() outward_normal = Vector3D(0, -1, 0) t = t.align_z_prime(outward_normal) assert x_axis == t * x_axis assert z_axis == t * y_axis result = t * z_axis assert outward_normal == result outward_normal = Vector3D(1, 0, 0) t = t.align_z_prime(outward_normal) assert y_axis == t * x_axis assert z_axis == t * y_axis assert outward_normal == t * z_axis outward_normal = Vector3D(0, 1, 0) t = t.align_z_prime(outward_normal) assert -x_axis == t * x_axis assert z_axis == t * y_axis assert outward_normal == t * z_axis outward_normal = Vector3D(-1, 0, 0) t = t.align_z_prime(outward_normal) assert -y_axis == t * x_axis assert z_axis == t * y_axis assert outward_normal == t * z_axis outward_normal = Vector3D(0, 0, 1) t = t.align_z_prime(outward_normal) assert -x_axis == t * x_axis assert -y_axis == t * y_axis assert outward_normal == t * z_axis outward_normal = Vector3D(0, 0, -1) t = t.align_z_prime(outward_normal) assert -x_axis == t * x_axis assert y_axis == t * y_axis assert outward_normal == t * z_axis
def test_translation_transformations(self): tol = 12 # places trans = Vector3D(1, 1, 1) point1 = Vector3D(1, 0, 0) t = Transformation() # identity transformation temp = t * point1 assert almostequal(1.0, temp.x, tol) assert almostequal(0.0, temp.y, tol) assert almostequal(0.0, temp.z, tol) # move by 1, 1, 1 t = Transformation(translation_matrix(trans)) temp = t * point1 assert almostequal(2.0, temp.x, tol) assert almostequal(1.0, temp.y, tol) assert almostequal(1.0, temp.z, tol) # move by -1, -1, -1 temp = t.inverse() * point1 assert almostequal(0.0, temp.x, tol) assert almostequal(-1.0, temp.y, tol) assert almostequal(-1.0, temp.z, tol) # identity transformation temp = t.inverse() * t * point1 assert almostequal(1.0, temp.x, tol) assert almostequal(0.0, temp.y, tol) assert almostequal(0.0, temp.z, tol) # identity transformation temp = t * t.inverse() * point1 assert almostequal(1.0, temp.x, tol) assert almostequal(0.0, temp.y, tol) assert almostequal(0.0, temp.z, tol)
def translate(surfaces, vector): """Translate all surfaces by a vector. Parameters ---------- surfaces : list A list of EpBunch objects. vector : Vector2D, Vector3D, (x,y) or (x,y,z) list-like Representation of a vector to translate by. """ vector = Vector3D(*vector) for s in surfaces: new_coords = translate_coords(s.coords, vector) s.setcoords(new_coords)
def roofs(self): """Coordinates for each roof of the block. This returns a list with an entry for each floor for consistency with the other properties of the Block object, but should only have roof coordinates in the list in the final position. Returns ------- list """ roofs = [[None] for ch in self.ceiling_heights[:-1]] roofs.append([self.footprint + Vector3D(0,0,self.height)]) return roofs
def translate_coords(coords, vector): """Translate a set of coords by a direction vector. Parameters ---------- coords : list A list of points. vector : Vector2D, Vector3D, (x,y) or (x,y,z) list-like Representation of a vector to translate by. Returns ------- list of Vector3D objects """ return [Vector3D(*v) + vector for v in coords]
def test_translate(self): idf = self.idf surfaces = getidfsurfaces(idf) translate(surfaces, (50, 100)) # move to x + 50, y + 100 result = Polygon3D(surfaces[0].coords).xs expected = [52.0, 52.0, 51.0, 51.0] assert result == expected translate(surfaces, (-50, -100)) # move back translate(surfaces, Vector2D(50, 100)) # move to x + 50, y + 100 result = Polygon3D(surfaces[0].coords).xs expected = [52.0, 52.0, 51.0, 51.0] assert result == expected translate(surfaces, (-50, -100)) # move back translate(surfaces, Vector3D(50, 100, 0)) # move to x + 50, y + 100 result = Polygon3D(surfaces[0].coords).xs expected = [52.0, 52.0, 51.0, 51.0] assert result == expected
def test_collinear(): # same line edge1 = Segment(Vector3D(0,0,0), Vector3D(1,1,1)) edge2 = Segment(Vector3D(0,0,0), Vector3D(1,1,1)) assert edge1.is_collinear(edge2) # opposite direction line edge1 = Segment(Vector3D(1,1,1), Vector3D(0,0,0)) edge2 = Segment(Vector3D(0,0,0), Vector3D(1,1,1)) assert edge1.is_collinear(edge2) # edge1 is longer edge1 = Segment(Vector3D(0,0,0), Vector3D(4,4,4)) edge2 = Segment(Vector3D(1,1,1), Vector3D(2,2,2)) assert edge1.is_collinear(edge2) # same start point, different lengths edge1 = Segment(Vector3D(0,0,0), Vector3D(1,1,1)) edge2 = Segment(Vector3D(0,0,0), Vector3D(2,2,2)) assert edge1.is_collinear(edge2) # something being missed edge1 = Segment(Vector3D(1,4,0), Vector3D(1,0,0)) edge2 = Segment(Vector3D(1,0,0), Vector3D(1,2,0)) assert edge1.is_collinear(edge2) # parallel edge1 = Segment(Vector3D(0,0,0), Vector3D(1,1,1)) edge2 = Segment(Vector3D(1,0,0), Vector3D(2,1,1)) assert not edge1.is_collinear(edge2)
def test_segment_repr(): edge = Segment(Vector3D(0,0,0), Vector3D(2,0,0)) assert eval(repr(edge)) == edge
def __init__(self, vertices): try: self.vertices = [Vector3D(*v) for v in vertices] except TypeError: self.vertices = vertices
def test_align_face_transformations(self): tol = 12 # places vertices = Polygon3D([(1, 0, 1), (1, 0, 0), (2, 0, 0), (2, 0, 1)]) t = Transformation() # rotate 0 degrees about z testVertices = t.rotation(Vector3D(0, 0, 1), 0) * vertices t = Transformation().align_face(testVertices) tempVertices = t.inverse() * testVertices expectedVertices = Polygon3D([(0, 1, 0), (0, 0, 0), (1, 0, 0), (1, 1, 0)]) assert almostequal(tempVertices, expectedVertices, tol) # rotate 30 degrees about z testVertices = t.rotation(Vector3D(0, 0, 1), np.deg2rad(30)) * vertices t = Transformation().align_face(testVertices) tempVertices = t.inverse() * testVertices expectedVertices = Polygon3D([(0, 1, 0), (0, 0, 0), (1, 0, 0), (1, 1, 0)]) assert almostequal(tempVertices, expectedVertices, tol) # rotate -30 degrees about z testVertices = t.rotation(Vector3D(0, 0, 1), -np.deg2rad(30)) * vertices t = Transformation().align_face(testVertices) tempVertices = t.inverse() * testVertices expectedVertices = Polygon3D([(0, 1, 0), (0, 0, 0), (1, 0, 0), (1, 1, 0)]) assert almostequal(tempVertices, expectedVertices, tol) # rotate -30 degrees about x testVertices = t.rotation(Vector3D(1, 0, 0), -np.deg2rad(30)) * vertices t = Transformation().align_face(testVertices) tempVertices = t.inverse() * testVertices expectedVertices = Polygon3D([(0, 1, 0), (0, 0, 0), (1, 0, 0), (1, 1, 0)]) assert almostequal(tempVertices, expectedVertices, tol) # rotate -90 degrees about x testVertices = t.rotation(Vector3D(1, 0, 0), -np.deg2rad(90)) * vertices t = Transformation().align_face(testVertices) tempVertices = t.inverse() * testVertices expectedVertices = Polygon3D([(1, 0, 0), (1, 1, 0), (0, 1, 0), (0, 0, 0)]) assert almostequal(tempVertices, expectedVertices, tol) # rotate 30 degrees about x testVertices = t.rotation(Vector3D(1, 0, 0), np.deg2rad(30)) * vertices t = Transformation().align_face(testVertices) tempVertices = t.inverse() * testVertices expectedVertices = Polygon3D([(0, 1, 0), (0, 0, 0), (1, 0, 0), (1, 1, 0)]) assert almostequal(tempVertices, expectedVertices, tol) # rotate 90 degrees about x testVertices = t.rotation(Vector3D(1, 0, 0), np.deg2rad(90)) * vertices t = Transformation().align_face(testVertices) tempVertices = t.inverse() * testVertices expectedVertices = Polygon3D([(1, 0, 0), (1, 1, 0), (0, 1, 0), (0, 0, 0)]) assert almostequal(tempVertices, expectedVertices, tol)