def test_split_correct_point_coords(self): a = Point(0, 0) b = Point(0, 10) vector = Vector(a, b) desired_amount_of_vectors = 4 split_vectors = vector.split(desired_amount_of_vectors) self.assertEqual(Vector(Point(0, 2.5), Point(0, 5)), split_vectors[1])
def project(self, point: Vector, mesh_position: Vector): cx = self.C.x cy = self.C.y cz = self.C.z sx = self.S.x sy = self.S.y sz = self.S.z delta = point + mesh_position - self.position dot = delta.dot(self.bearing.projection) if dot <= 0: point.visible = False return d_x = cy * (sz * delta.y + cz * delta.x) - sy * delta.z d_y = sx * (cy * delta.z + sy * (sz * delta.y + cz * delta.x)) + cx * (cz * delta.y - sz * delta.x) d_z = cx * (cy * delta.z + sy * (sz * delta.y + cz * delta.x)) - sx * (cz * delta.y - sz * delta.x) x = (self.view_port.z / d_z) * d_x + self.view_port.x y = (-(self.view_port.z / d_z) * d_y ) + self.view_port.y # reverse y as the screen origin is top left point.projection = Vector(point.label, x, y) point.projection.d = dot point.visible = True
def test_distance(self): v1 = Vector(1, 1, 0) v2 = Vector(2, 2, 0) self.assertAlmostEqual(v1.dist(v2), v2.dist(v1)) self.assertAlmostEqual(v1.dist(v2), pow(2, 0.5))
def test_split_correct_amount_of_vectors(self): a = Point(0, 0) b = Point(0, 10) vector = Vector(a, b) desired_amount_of_vectors = 4 split_vectors = vector.split(desired_amount_of_vectors) self.assertEqual(desired_amount_of_vectors, len(split_vectors))
def test_angle_between_horizontal_line(self): a = Point(0, 0) b = Point(3, 0) c = Point(3, 4) v1 = Vector(a, b) v2 = Vector(a, c) self.assertEqual(53.1301, round(Vector.angle_between(v1, v2), 4))
def test_angle_between_vertical_line(self): a = Point(0, 0) b = Point(0, 10) c = Point(10, 10) v1 = Vector(a, b) v2 = Vector(a, c) self.assertEqual(45, round(Vector.angle_between(v1, v2), 4))
def test_intersection_common_point(self): a = Point(0, 0) b = Point(3, 0) c = Point(3, 4) v1 = Vector(a, b) v2 = Vector(a, c) self.assertEqual(Point(0, 0), Vector.intersection(v1, v2))
def test_equality_incorrect_data(self): a = Point(0, 0) b = Point(3, 4) vector1 = Vector(a, b) c = Point(1, 1) vector2 = Vector(a, c) self.assertNotEqual(vector1, vector2)
def test_equally_split_points(self): a = Point(0, 0) b = Point(0, 10) vector = Vector(a, b) points = vector.get_split_points(3) self.assertEqual(points, [a, Point(0, 5), b])
def _reflect_across_screen(self): """Checks if the entity needs to be reflected across the screen and generates a new position if it does """ # Start with the current position new_pos = Vector(self.pos.x, self.pos.y) # For each side of the screen, check if the entity has # exceeded the bounds using the approximate length # Check horizontal # Left-side if (self.pos.x + self._shape.effective_length < 0): dist = abs(0 - (self.pos.x + self._shape.effective_length)) new_pos.x = WINDOW_WIDTH + dist # Right-side elif (self.pos.x - self._shape.effective_length > WINDOW_WIDTH): dist = abs((self.pos.x - self._shape.effective_length) - WINDOW_WIDTH) new_pos.x = -dist # Check vertical # Bottom if (self.pos.y + self._shape.effective_length < 0): dist = abs(0 - (self.pos.y + self._shape.effective_length)) new_pos.y = WINDOW_HEIGHT + dist # Top elif (self.pos.y - self._shape.effective_length > WINDOW_HEIGHT): dist = abs((self.pos.y - self._shape.effective_length) - WINDOW_HEIGHT) new_pos.y = -dist # Set the new position of the entity. # If no reflection was needed, it's just the original position self.pos = new_pos
def test_split_proportions(self): a = Point(0, 0) b = Point(0, 10) vector = Vector(a, b) desired_amount_of_vectors = 4 split_vectors = vector.split(desired_amount_of_vectors, [6, 2, 1, 1]) self.assertEqual(Vector(Point(0, 8), Point(0, 9)), split_vectors[2])
def test_init_dy(self): a = Point(0, 0) b = Point(3, 4) c = Point(6, 0) vector1 = Vector(a, b) vector2 = Vector(b, c) pc = PolygonalChain([vector1, vector2]) self.assertEqual(pc.dy, 0)
def test_equally_split_points(self): a = Point(0, 0) b = Point(3, 4) c = Point(6, 0) vector1 = Vector(a, b) vector2 = Vector(b, c) pc = PolygonalChain([vector1, vector2]) self.assertEqual(pc.get_split_points(3), [a, b, c])
def test_outside_of_vector(self): a = Point(0, 0) b = Point(2, 2) c = Point(3, 0) d = Point(3, 3) v1 = Vector(a, b) v2 = Vector(c, d) self.assertEqual(None, Vector.intersection(v1, v2))
def test_intersection_edge(self): a = Point(0, 0) b = Point(3, 0) c = Point(3, -1) d = Point(3, 1) v1 = Vector(a, b) v2 = Vector(c, d) self.assertEqual(Point(3, 0), Vector.intersection(v1, v2))
def test_intersection_angle(self): a = Point(0, 0) b = Point(2, 2) c = Point(0, 2) d = Point(2, 0) v1 = Vector(a, b) v2 = Vector(c, d) self.assertEqual(Point(1, 1), Vector.intersection(v1, v2))
def test_init_end_point(self): a = Point(0, 0) b = Point(10, 10) c = Point(20, 0) vector1 = Vector(a, b) vector2 = Vector(b, c) pc = PolygonalChain([vector1, vector2]) self.assertEqual(pc.end, c)
def test_no_intersection(self): a = Point(0, 0) b = Point(0, 2) c = Point(3, 0) d = Point(3, 3) v1 = Vector(a, b) v2 = Vector(c, d) p = Vector.intersection(v1, v2) self.assertEqual(None, Vector.intersection(v1, v2))
def test_get_normalized(self): v = Vector(1, 1, 1) n = v.unit() self.assertAlmostEqual(n.x, 0.577, 3) self.assertAlmostEqual(n.y, 0.577, 3) self.assertAlmostEqual(n.z, 0.577, 3) v = Vector(0, 0, 0) self.assertRaises(ValueError, v.unit)
def test_intersection1(self): a = Point(638.5244160186169, -690.6187771400942) b = Point(174.0952380952381, 325.61) c = Point(205, 60) d = Point(536, 211) v1 = Vector(b, a) v2 = Vector(d, c) ip = Vector.intersection(v1, v2) self.assertEqual(Point(279.8724486895196, 94.1563134505059), ip)
def test_waged_split_points(self): a = Point(0, 0) b = Point(0, 10) c = Point(10, 10) vector1 = Vector(a, b) vector2 = Vector(b, c) pc = PolygonalChain([vector1, vector2]) self.assertEqual( pc.get_split_points(5, [0, 0.4, 0.5, 0.6, 1]), [a, Point(0, 8), b, Point(2, 10), c])
def test_equally_split_points2(self): a = Point(0, 0) b = Point(0, 10) c = Point(10, 10) vector1 = Vector(a, b) vector2 = Vector(b, c) pc = PolygonalChain([vector1, vector2]) self.assertEqual( pc.get_split_points(5), [a, Point(0, 5), b, Point(5, 10), c])
def __init__(self, canvas: wx.Window, x: int, y: int, radius: int): self.diameter = radius * 2 self.radius = radius self.position = Vector(x, y) self.canvas = canvas self.rect = wx.Rect(x, y, self.diameter, self.diameter) self.velocity = Vector(0, _random_velocity()) self.velocity.x = rotate(random.randint(0, 360)).x * _random_velocity( _MIN_VELOCITY, _MAX_VELOCITY) self.off_screen = False
def __init__(self, x: float, y: float, top_speed: int, drag: int): self.position = Vector(x, y) self.START_POSITION = copy(self.position) self.velocity = Vector(0, 0) self.approach = Vector(0, 0) self.top_speed = top_speed self.drag = drag self.surface = pygame.image.load( ".\\resources\\images\\paddle.png").convert_alpha() self.rect = self.surface.get_rect()
def reset(self): self.projector.models.clear() self.projector.models.append( create_cube(500, self.dimensions, position=Vector(-250, -250, 50, 10), color="blue") ) self.projector.models.append( create_axis(self.dimensions, 200, "green", position=Vector(*[0] * self.dimensions)) ) self.update()
def __init__(self, calculations): self.title = "The Ostwald Triangle" self.maxco2 = calculations.max_co2 self.maxco = calculations.max_co self.maxo2 = calculations.max_o2 self.O2_SERIES_SCALE = 2 self.CO2_SERIES_SCALE = 2 self.set_width(margin_left=10, triangle_width=50) self.set_height(margin_top=10, triangle_width=50) self.A = Point(self.left, self.top) self.B = Point(self.right, self.bot) self.C = self.get_position_from_scale(calculations.C.o2, calculations.C.co2) self.P = self.get_position_from_scale(calculations.P.o2, calculations.P.co2) self.Pco2 = self.get_position_from_scale(0, calculations.P.co2) self.Po2 = self.get_position_from_scale(calculations.P.o2, self.maxco2) self.co2_diagonal_angle = degrees(atan(self.width/self.height)) self.co_line_angle = self.co2_diagonal_angle self.bot_diagonal_angle = 90 - self.co2_diagonal_angle self.coefficient_line_angle = self.calculate_coeff_line_angle() self.lines = {"o2": LineInfo( Vector(self.left, self.top, self.right, self.top), points=self.maxo2 + 1, labels={"name": "Oxygen %"}, series=Series(0, self.maxo2, self.O2_SERIES_SCALE), ), "co2": LineInfo( Vector(self.left, self.bot, self.left, self.top), series=Series(0, self.maxco2, self.CO2_SERIES_SCALE), labels={"name": "Carbon dioxide %"} ), "co": LineInfo( Vector(Point(self.right, self.bot), 180 + self.co_line_angle, self.width * cos(radians(self.co2_diagonal_angle))), series=Series(0, self.maxco, 5), labels={"name": "Carbon monoxide %"} ), "coefficient": LineInfo( self.create_coefficient_line(), series=Series(0, 1.6, 0.2), labels={"name": "Phi coefficient"} # todo coeff latin smbol ), "bot": LineInfo( Vector(self.left, self.bot, self.right, self.bot) ), "diagonal": LineInfo( Vector(self.left, self.top, self.right, self.bot) ), "P-co": LineInfo( self.create_p_co_line() ), "P-o2": LineInfo( self.create_p_o2_line() ), "P-co2": LineInfo( self.create_p_co2_line() ) }
def create_axis(dimensions, size, color, **kw): return Model( dimensions, [ Primitive( Line( Vector.get_zero_vector(dimensions), Vector(*(size if i == d else 0 for i in range(dimensions))) ), color, arrow=LAST) for d in range(dimensions) ], **kw)
def create_cube(size, dimensions, color="black", **kw): lines = [] for d in range(dimensions**2): point = Vector(*(size * (d & 2**i == 2**i) for i in range(dimensions))) for n in range(dimensions): if point.coordinates[n] == 0: lines.append( Line( point, Vector(*(point.coordinates[i] if i != n else size for i in range(dimensions))))) return Model(dimensions, [Primitive(l, color) for l in lines], **kw)
def __init__(self, *triangles: Vector): assert (len(triangles) % 3 == 0), "incorrect number of points for triangles" self.rotation = Vector() self.center = Vector() self.viewportPosition = Vector() self.vertices = triangles self.triangles = [] i = 0 while i < len(triangles): self.triangles.append( Triangle(self.vertices[i], self.vertices[i + 1], self.vertices[i + 2])) i += 3
def interpolate(self, spacing: float = 1) -> Path: """ Interpolates the current path to produce a new path with points 'spacing' apart """ generated = dict(x=[], y=[]) for n in range(len(self) - 1): # get current and next point p0 = self[n] p1 = self[n + 1] # get number of new points segment = p1 - p0 if segment.magnitude <= spacing: if n > 0: prev = Vector(generated["x"][-1], generated["y"][-1]) if (prev - p0).magnitude >= spacing: generated["x"].append(p0.x) generated["y"].append(p0.y) else: continue else: generated["x"].append(p0.x) generated["y"].append(p0.y) else: n_new = int(np.floor(segment.magnitude / spacing)) # create new points for p in np.linspace(0, 1, n_new): if n > 0 and p == 0: continue # avoid doubling generated["x"].append(interpolate.linear(p0.x, p1.x, p)) generated["y"].append(interpolate.linear(p0.y, p1.y, p)) return Path(generated["x"], generated["y"])
def import_from(file_path: str) -> Mesh: f = open(file_path, "r") vertex_regex = re.compile( "v\\s(-?[.0-9]+)\\s(-?[.0-9]+)\\s(-?[.0-9]+)") triangle_regex = re.compile("f\\s(\\d+)\\s(\\d+)\\s(\\d+)") vertices = [] triangles = [] lines = f.readlines() for line in lines: line_type = line[0] if line_type == "#": continue # line is comment elif line_type == "o": pass # mesh name ignored elif line_type == "v": groups = vertex_regex.search(line).groups() vertex = Vector(x=float(groups[0]), y=float(groups[1]), z=float(groups[2])) vertices.append(vertex) elif line_type == "s": pass # Smooth shading ignored elif line_type == "f": groups = triangle_regex.search(line).groups() triangles.append(vertices[int(groups[0]) - 1]) triangles.append(vertices[int(groups[1]) - 1]) triangles.append(vertices[int(groups[2]) - 1]) else: print("ignored unknown format line {}".format(line)) return Mesh(*triangles)
def downsample_euclidean(self, spacing: float = 1) -> Path: """ Downsamples the path keeping only points that are spacing apart. This function looks at the euclidean distance between points, ignores the path length distance between them """ downsampled = dict(x=[], y=[]) for n in range(len(self)): if n == 0: downsampled["x"].append(self[0].x) downsampled["y"].append(self[0].y) else: p0 = Vector(downsampled["x"][-1], downsampled["y"][-1]) p1 = self[n] # if distance > spacing if (p1 - p0).magnitude >= spacing: # the distance between the two could be > spacing # get a new point at the right distance vec = p1 - p0 downsampled["x"].append( p0.x + spacing * np.cos(np.radians(vec.angle)) ) downsampled["y"].append( p0.y + spacing * np.sin(np.radians(vec.angle)) ) return Path(downsampled["x"], downsampled["y"])
def test_init_with_points(self): a = Point(0, 0) b = Point(3, 4) vector = Vector(a, b) self.assertEqual(vector.start.x, 0) self.assertEqual(vector.start.y, 0) self.assertEqual(vector.end.x, 3) self.assertEqual(vector.end.y, 4)
def __init__(self, normal=(), point=()): v = Vector(*[x for x in normal]) if v: v /= v.length() self._normal = v if v: if v.dot(point): p = Point(*[x for x in point]) else: p = Point() else: p = Point() #normalize the point to that closest to origin self._point = p#so apply works if p: p = self.apply((0,))/2 self._point = p self._vec_norm = v.dot(v)
def test_vector_product(self): v1 = Vector(1, 0, 0) v2 = Vector(0, 1, 0) v = v1.vector_product(v2) self.assertEquals(v, Vector(0, 0, 1))
def test_vector_product_parallel(self): v1 = Vector(1, 0, 0) v2 = Vector(2, 0, 0) v = v1.vector_product(v2) self.assertEquals(v.length, 0)
def test_vector_product_zero(self): v1 = Vector(1, 0, 0) v2 = Vector(0, 0, 0) v = v1.vector_product(v2) self.assertEquals(v.length, 0)