Exemple #1
0
 def __init__(self, vmob, alpha, **kwargs):
     digest_config(self, kwargs)
     da = self.d_alpha
     a1 = clip(alpha - da, 0, 1)
     a2 = clip(alpha + da, 0, 1)
     super().__init__(vmob.pfp(a1), vmob.pfp(a2), **kwargs)
     self.scale(self.length / self.get_length())
Exemple #2
0
 def get_arc_center_and_angles(x0, y0, rx, ry, phi, large_arc_flag,
                               sweep_flag, x1, y1):
     """
     The parameter functions of an ellipse rotated `phi` radians counterclockwise is (on `alpha`):
         x = cx + rx * cos(alpha) * cos(phi) + ry * sin(alpha) * sin(phi),
         y = cy + rx * cos(alpha) * sin(phi) - ry * sin(alpha) * cos(phi).
     Now we have two points sitting on the ellipse: `(x0, y0)`, `(x1, y1)`, corresponding to 4 equations,
     and we want to hunt for 4 variables: `cx`, `cy`, `alpha0` and `alpha_1`.
     Let `d_alpha = alpha1 - alpha0`, then:
     if `sweep_flag = 0` and `large_arc_flag = 1`, then `PI <= d_alpha < 2 * PI`;
     if `sweep_flag = 0` and `large_arc_flag = 0`, then `0 < d_alpha <= PI`;
     if `sweep_flag = 1` and `large_arc_flag = 0`, then `-PI <= d_alpha < 0`;
     if `sweep_flag = 1` and `large_arc_flag = 1`, then `-2 * PI < d_alpha <= -PI`.
     """
     xd = x1 - x0
     yd = y1 - y0
     if close_to_zero(xd) and close_to_zero(yd):
         raise Exception(
             "Cannot find arc center since the start point and the end point meet."
         )
     # Find `p = cos(alpha1) - cos(alpha0)`, `q = sin(alpha1) - sin(alpha0)`
     eq0 = [rx * np.cos(phi), ry * np.sin(phi), xd]
     eq1 = [rx * np.sin(phi), -ry * np.cos(phi), yd]
     p, q = solve_2d_linear_equation(*zip(eq0, eq1))
     # Find `s = (alpha1 - alpha0) / 2`, `t = (alpha1 + alpha0) / 2`
     # If `sin(s) = 0`, this requires `p = q = 0`,
     # implying `xd = yd = 0`, which is impossible.
     sin_s = (p**2 + q**2)**0.5 / 2
     if sweep_flag:
         sin_s = -sin_s
     sin_s = clip(sin_s, -1, 1)
     s = np.arcsin(sin_s)
     if large_arc_flag:
         if not sweep_flag:
             s = PI - s
         else:
             s = -PI - s
     sin_t = -p / (2 * sin_s)
     cos_t = q / (2 * sin_s)
     cos_t = clip(cos_t, -1, 1)
     t = np.arccos(cos_t)
     if sin_t <= 0:
         t = -t
     # We can make sure `0 < abs(s) < PI`, `-PI <= t < PI`.
     alpha0 = t - s
     alpha_1 = t + s
     cx = x0 - rx * np.cos(alpha0) * np.cos(phi) - ry * np.sin(
         alpha0) * np.sin(phi)
     cy = y0 - rx * np.cos(alpha0) * np.sin(phi) + ry * np.sin(
         alpha0) * np.cos(phi)
     return cx, cy, alpha0, alpha_1
Exemple #3
0
def smooth(t, inflection=10.0):
    error = sigmoid(-inflection / 2)
    return clip(
        (sigmoid(inflection * (t - 0.5)) - error) / (1 - 2 * error),
        0,
        1,
    )
 def get_sub_alpha(self, alpha, index, num_submobjects):
     # TODO, make this more understanable, and/or combine
     # its functionality with AnimationGroup's method
     # build_animations_with_timings
     lag_ratio = self.lag_ratio
     full_length = (num_submobjects - 1) * lag_ratio + 1
     value = alpha * full_length
     lower = index * lag_ratio
     return clip((value - lower), 0, 1)
Exemple #5
0
def angle_between_vectors(v1: np.ndarray, v2: np.ndarray) -> float:
    """
    Returns the angle between two 3D vectors.
    This angle will always be btw 0 and pi
    """
    n1 = get_norm(v1)
    n2 = get_norm(v2)
    if n1 == 0 or n2 == 0:
        return 0
    cos_angle = np.dot(v1, v2) / np.float64(n1 * n2)
    return math.acos(clip(cos_angle, -1, 1))
 def update(m, dt):
     run_time = animation.get_run_time()
     time_ratio = animation.total_time / run_time
     if cycle:
         alpha = time_ratio % 1
     else:
         alpha = clip(time_ratio, 0, 1)
         if alpha >= 1:
             animation.finish()
             m.remove_updater(update)
             return
     animation.interpolate(alpha)
     animation.update_mobjects(dt)
     animation.total_time += dt
Exemple #7
0
 def interpolate(self, alpha: float) -> None:
     # Note, if the run_time of AnimationGroup has been
     # set to something other than its default, these
     # times might not correspond to actual times,
     # e.g. of the surrounding scene.  Instead they'd
     # be a rescaled version.  But that's okay!
     time = alpha * self.max_end_time
     for anim, start_time, end_time in self.anims_with_timings:
         anim_time = end_time - start_time
         if anim_time == 0:
             sub_alpha = 0
         else:
             sub_alpha = clip((time - start_time) / anim_time, 0, 1)
         anim.interpolate(sub_alpha)
Exemple #8
0
 def rotate(self, angle: float, axis: np.ndarray = OUT, **kwargs):
     curr_rot_T = self.get_inverse_camera_rotation_matrix()
     added_rot_T = rotation_matrix_transpose(angle, axis)
     new_rot_T = np.dot(curr_rot_T, added_rot_T)
     Fz = new_rot_T[2]
     phi = np.arccos(clip(Fz[2], -1, 1))
     theta = angle_of_vector(Fz[:2]) + PI / 2
     partial_rot_T = np.dot(
         rotation_matrix_transpose(phi, RIGHT),
         rotation_matrix_transpose(theta, OUT),
     )
     gamma = angle_of_vector(np.dot(partial_rot_T, new_rot_T.T)[:, 0])
     self.set_euler_angles(theta, phi, gamma)
     return self
Exemple #9
0
 def interpolate(self, alpha: float) -> None:
     alpha = clip(alpha, 0, 1)
     self.interpolate_mobject(self.rate_func(alpha))
Exemple #10
0
 def increment_phi(self, dphi):
     phi = self.data["euler_angles"][1]
     new_phi = clip(phi + dphi, 0, PI)
     self.data["euler_angles"][1] = new_phi
     self.refresh_rotation_matrix()
     return self
 def interpolate(self, alpha):
     alpha = clip(alpha, 0, 1)
     self.interpolate_mobject(self.rate_func(alpha))
Exemple #12
0
def angle_between_vectors(v1, v2):
    """
    Returns the angle between two 3D vectors.
    This angle will always be btw 0 and pi
    """
    return math.acos(clip(np.dot(normalize(v1), normalize(v2)), -1, 1))