Source code for manim_pymunk.constraints.VGearJoint

from typing import Optional
from pymunk import Space
from pymunk.constraints import GearJoint
from manim import *
from manim_pymunk.constraints import VConstraint


[docs] class VGearJoint(VConstraint): """A gear joint constrains the rotational speeds of two rigid bodies. It ensures that the two bodies rotate relative to each other at a fixed ratio, simulating the mechanical link of a gear system or a belt drive. Parameters ---------- a_mob The first Mobject to be connected. Typically represents the driving or reference gear. b_mob The second Mobject to be connected. Its rotation is linked to `a_mob` based on the defined `ratio`. phase The angular offset (in radians) between the two bodies. Adjusts the initial relative orientation alignment. ratio The gear ratio. Defines how the angular velocity of `b_mob` relates to `a_mob`. For example, a ratio of 2.0 means `b_mob` rotates twice as fast as `a_mob`. indicator_line_class The class used to visualize the rotational direction or connection (defaults to `Arrow`). If set to `None`, no indicator will be rendered. indicator_line_config A dictionary defining the visual style of the indicator line, including `color` and `stroke_width`. Examples -------- .. manim:: VGearJointExample from manim_pymunk import * class VGearJointExample(SpaceScene): def construct(self): floor = Line(LEFT * 10, RIGHT * 10).shift(DOWN * 2) static_dot1 = Dot(UP * 2) static_dot2 = Dot(UP * 2 + RIGHT * 4) square_1 = Square().move_to(static_dot1) square_2 = Square().move_to(static_dot2) constraints = [ VGearJoint( square_1, square_2, phase=0, ratio=4, ), VPinJoint(static_dot1, square_1), VPinJoint(static_dot2, square_2), ] self.add_static_body(floor, static_dot1, static_dot2) self.add_dynamic_body(square_1, angular_velocity=PI * 2) self.add_dynamic_body(square_2) self.add_shapes_filter(static_dot1, static_dot2, square_1, square_2, group=2) self.add_constraints(*constraints) self.wait(3) """ def __init__( self, a_mob: Mobject, b_mob: Mobject, phase: float = 0.0, ratio: float = 1.0, indicator_line_class: Optional[Line] = Arrow, indicator_line_config: dict = { "color": BLUE, "stroke_width": 2, }, indicator_length: float = 0.4, **kwargs, ): super().__init__(**kwargs) self.a_mob = a_mob self.b_mob = b_mob self.phase = phase self.ratio = ratio self.indicator_a = None self.indicator_b = None self.constraint: Optional[GearJoint] = None self.indicator_line_class = indicator_line_class self.indicator_line_config = indicator_line_config self.indicator_length = indicator_length
[docs] def install(self, space: Space): """Verify the validity of constraint parameters.""" a_body = getattr(self.a_mob, "body", None) b_body = getattr(self.b_mob, "body", None) if not a_body or not b_body: raise ValueError("VGearJoint connected objects must have a Pymunk body.") self.constraint = GearJoint(a_body, b_body, self.phase, self.ratio) if self.indicator_line_class: self.indicator_a = self.indicator_line_class( self.a_mob.get_center(), self.a_mob.get_center() + UP * self.indicator_length, **self.indicator_line_config, ) self.indicator_b = self.indicator_line_class( self.b_mob.get_center(), self.b_mob.get_center() + UP * self.indicator_length, **self.indicator_line_config, ) self.add(self.indicator_a, self.indicator_b) space.add(self.constraint) self.add_updater(self.mob_updater)
[docs] def mob_updater(self, mob, dt): """Visual control updater""" if not self.constraint: return a_body = self.constraint.a b_body = self.constraint.b if isinstance(self.indicator_a, Line): end_a = ( self.a_mob.get_center() + np.array([np.cos(a_body.angle), np.sin(a_body.angle), 0]) * self.indicator_length ) self.indicator_a.put_start_and_end_on(self.a_mob.get_center(), end_a) if isinstance(self.indicator_b, Line): end_b = ( self.b_mob.get_center() + np.array([np.cos(b_body.angle), np.sin(b_body.angle), 0]) * self.indicator_length ) self.indicator_b.put_start_and_end_on(self.b_mob.get_center(), end_b)