def test_normal_vector(self, a: Point): if isclose(abs(a), 0.0): with pytest.raises(ZeroDivisionError): a.normal() else: angle = a.normal().angle() - a.angle() assert isclose(angle, np.pi / 2.0)
def test_rotation_about_zero(self, a: Point, angle: Angle): assume(abs(a) != 0) b = a.rotate(angle, Point(0.0, 0.0)) aa = a.angle() bb = b.angle() note(f"a angle: {aa}") note(f"b angle: {bb}") assert isclose(bb - aa, angle)
def __init__( self, start: Point, length: float, width: float = None, bar_length: float = None, num_windings: int = 11, teeth: bool = False, ): B = start n = num_windings - 1 # n counts teeth intervals if n <= 6: n = 7 # n must be odd: if n % 2 == 0: n = n + 1 L = length if width is None: w = L / 10.0 else: w = width / 2.0 s = bar_length shapes = {} if s is None: f = Spring.spring_fraction s = L * (1 - f) / 2.0 # start of spring self.bar_length = s # record self.width = 2 * w p0 = Point(B.x, B.y + s) p1 = Point(B.x, B.y + L - s) p2 = Point(B.x, B.y + L) if s >= L: raise ValueError( "length of first bar: %g is larger than total length: %g" % (s, L)) shapes["bar1"] = Line(B, p0) spring_length = L - 2 * s t = spring_length / n # height increment per winding if teeth: resolution = 4 else: resolution = 90 q = np.linspace(0, n, n * resolution + 1) xs = p0.x + w * np.sin(2 * np.pi * q) ys = p0.y + q * t points = Point.from_coordinate_lists(xs, ys) shapes["spiral"] = Curve(points) shapes["bar2"] = Line(p1, p2) super().__init__(shapes)
def test_angle(self, a: Point): if a.x != 0.0: assume(abs(a.y / a.x) < 1e4) if a.y != 0.0: assume(abs(a.x / a.y) < 1e4) angle = a.angle() note(angle) b = Point(abs(a), 0.0).rotate(angle, Point(0.0, 0.0)) note(f"The angle is : {np.format_float_scientific(a.angle())}") note(f"The length is : {np.format_float_scientific(abs(a))}") assert b == a assert -np.pi <= angle <= np.pi
def composition(self): shape1 = Line(Point(0, 1), Point(1, 1)) shape2 = Line(Point(1, 1), Point(0, 2)) text = Text("This is a test.", Point(2, 2)) composition = Composition( { "shape1": shape1, "shape2": shape2, "test": text, } ) return composition
def main(): circle = Circle(Point(0, 0), 1) line = Line(Point(0, 0), Point(0, 1)) def func(frame: int): new_line = line.rotate(Angle(2 * np.pi * frame / 360), Point(0, 0)) model = Composition({"circle": circle, "line": new_line}) return model fig = Figure(-1.2, 1.2, -1.2, 1.2, backend=MatplotlibBackend) fig.animate(func, (0, 360)) fig.save_animation("animation.mp4")
def test_rotation(self, a: Point, angle: Angle, center: Point): assume(abs(a - center) != 0) b = a.rotate(angle, center) new_angle = (b - center).angle() - (a - center).angle() note(angle) note(new_angle) assert isclose(angle, angle)
def main() -> None: logging.basicConfig(level=logging.INFO) L = 8.0 H = 1.0 x_pos = 2.0 y_pos = 3.0 fig = Figure(0, x_pos + 1.2 * L, 0, y_pos + 5 * H, MatplotlibBackend) p0 = Point(x_pos, y_pos) main = Rectangle(p0, L, H).set_fill_pattern(Style.FillPattern.UP_LEFT_TO_RIGHT) h = L / 16 # size of support, clamped wall etc support = SimpleSupport(p0, h) clamped = Rectangle(p0 + Point(L, 0) - Point(0, 2 * h), h, 6 * h).set_fill_pattern(Style.FillPattern.UP_RIGHT_TO_LEFT) F_pt = Point(p0.x + L / 2, p0.y + H) force = Force("$F$", F_pt + Point(0, 2 * H), F_pt).set_line_width(3) L_dim = LinearDimension("$L$", Point(x_pos, p0.y - 3 * h), Point(x_pos + L, p0.y - 3 * h)) beam = Composition({ "main": main, "simply supported end": support, "clamped end": clamped, "force": force, "L": L_dim, }) fig.add(beam) fig.show()
def test_unit_vector(self, x: float, y: float): a = Point(x, y) if isclose(abs(a), 0.0): with pytest.raises(ZeroDivisionError): a.unit_vector else: b = a.unit_vector note(f"angle of a: {np.format_float_scientific(a.angle)}") note(f"angle of b: {np.format_float_scientific(b.angle)}") assert isclose(a.angle, b.angle) note(f"magnitude of b: {abs(b)}") assert isclose(abs(b), 1.0)
def inclined_plane(): theta = np.pi / 6 L = 10.0 a = 1.0 x_min = 0.0 y_min = -3.0 B = Point(a + L, 0) A = Point(a, np.tan(theta) * L) wall = Wall([A, B], thickness=-0.25) wall.style.fill_pattern = Style.FillPattern.UP_LEFT_TO_RIGHT angle = ArcWithText( r"$\theta$", center=B, radius=3, start_angle=np.pi - theta, arc_angle=theta ) angle.style.line_color = Style.Color.BLACK angle.style.line_width = 1 ground = Line(Point(B.x - L / 10.0, 0), Point(B.x - L / 2.0, 0)) ground.style.line_color = Style.Color.BLACK ground.style.line_style = Style.LineStyle.DASHED ground.style.line_width = 1 r = 1.0 # radius of wheel help_line = Line(A, B) x = a + 3 * L / 10.0 y = help_line(x=x) contact = Point(x, y) normal_vec = Point(np.sin(theta), np.cos(theta)) c = contact + normal_vec * r outer_wheel = ( Circle(c, r).set_line_color(Style.Color.BLUE).set_fill_color(Style.Color.BLUE) ) hole = ( Circle(c, r / 2.0) .set_line_color(Style.Color.BLUE) .set_fill_color(Style.Color.WHITE) ) wheel = Composition({"outer": outer_wheel, "inner": hole}) N = Force("$N$", contact - normal_vec * 2 * r, contact, spacing=0.2) N.style.line_color = Style.Color.BLACK # text_alignment='left') mg = Gravity(c, 3 * r, text="$Mg$", text_position=Gravity.TextPosition.END) x_const = Line(contact, contact + Point(0, 4)) x_const.style.line_style = Style.LineStyle.DOTTED x_const = x_const.rotate(-theta, contact) x_axis = Axis( start=contact + normal_vec * 3.0 * r, length=4 * r, label="$x$", rotation_angle=-theta, ) body = Composition({"wheel": wheel, "N": N, "mg": mg}) fixed = Composition( { "angle": angle, "inclined wall": wall, "wheel": wheel, "ground": ground, "x start": x_const, "x axis": x_axis, } ) model = Composition({"fixed elements": fixed, "body": body}) fig = Figure(x_min, x_min + 1.5 * L, y_min, y_min + L, backend=MatplotlibBackend) fig.add(model) fig.show() time.sleep(1) tangent_vec = Point(normal_vec.y, -normal_vec.x) def position(t): """Position of center point of wheel.""" return c + tangent_vec * 7 * t ** 2 def move(fig: Shape, t: float, dt: float = None) -> fig: x = position(t) x0 = position(t - dt) displacement = x - x0 return fig["body"].translate(displacement)
def test_coordinates(self, x: float, y: float) -> None: p = Point(x, y) assert p.x == x assert p.y == y
def composition(self): shape1 = Line(Point(0, 1), Point(1, 1)) shape2 = Line(Point(1, 1), Point(0, 2)) composition = Composition({"shape1": shape1, "shape2": shape2}) return composition
def func(frame: int): new_line = line.rotate(Angle(2 * np.pi * frame / 360), Point(0, 0)) model = Composition({"circle": circle, "line": new_line}) return model
def test_equality(self, x: float, y: float) -> None: assert Point(x, y) == Point(x, y)
def test_adding(self, x1: float, x2: float, y1: float, y2: float): a = Point(x1, y1) b = Point(x2, y2) assert a + b == Point(x1 + x2, y1 + y2)
def test_abs(self, x: float, y: float): assume(x * x != inf) assume(y * y != inf) a = Point(x, y) assert abs(a) == np.hypot(x, y)
def test_scale(self, x: float, y: float, s: float): a = Point(x, y) assert a.scale(s) == Point(x * s, y * s)
def test_multiplication(self, x: float, y: float, s: float): a = Point(x, y) assert a * s == Point(x * s, y * s)
def test_subtraction(self, x1: float, x2: float, y1: float, y2: float): a = Point(x1, y1) b = Point(x2, y2) assert a - b == Point(x1 - x2, y1 - y2)
def test_translation(self, x1: float, x2: float, y1: float, y2: float): a = Point(x1, y1) b = Point(x2, y2) assert a + b == Point(x1 + x2, y1 + y2)