mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Change how joint_angles are computed
This commit is contained in:
parent
11df256369
commit
d5575cf1ef
1 changed files with 14 additions and 16 deletions
|
@ -13,6 +13,7 @@ from manimlib.constants import DEFAULT_STROKE_WIDTH
|
||||||
from manimlib.constants import DEGREES
|
from manimlib.constants import DEGREES
|
||||||
from manimlib.constants import JOINT_TYPE_MAP
|
from manimlib.constants import JOINT_TYPE_MAP
|
||||||
from manimlib.constants import ORIGIN, OUT
|
from manimlib.constants import ORIGIN, OUT
|
||||||
|
from manimlib.constants import PI
|
||||||
from manimlib.constants import TAU
|
from manimlib.constants import TAU
|
||||||
from manimlib.mobject.mobject import Mobject
|
from manimlib.mobject.mobject import Mobject
|
||||||
from manimlib.mobject.mobject import Group
|
from manimlib.mobject.mobject import Group
|
||||||
|
@ -654,7 +655,7 @@ class VMobject(Mobject):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def is_smooth(self) -> bool:
|
def is_smooth(self) -> bool:
|
||||||
dots = np.cos(self.get_joint_angles()[0::2, :])
|
dots = np.cos(self.get_joint_angles()[0::2])
|
||||||
return bool((dots > 1 - 1e-3).all())
|
return bool((dots > 1 - 1e-3).all())
|
||||||
|
|
||||||
def change_anchor_mode(self, mode: str) -> Self:
|
def change_anchor_mode(self, mode: str) -> Self:
|
||||||
|
@ -1167,18 +1168,19 @@ class VMobject(Mobject):
|
||||||
product between tangent vectors at a joint
|
product between tangent vectors at a joint
|
||||||
"""
|
"""
|
||||||
if not self.needs_new_joint_angles and not refresh:
|
if not self.needs_new_joint_angles and not refresh:
|
||||||
return self.data["joint_angle"]
|
return self.data["joint_angle"][:, 0]
|
||||||
|
|
||||||
if "joint_angle" in self.locked_data_keys:
|
if "joint_angle" in self.locked_data_keys:
|
||||||
return self.data["joint_angle"]
|
return self.data["joint_angle"][:, 0]
|
||||||
|
|
||||||
self.needs_new_joint_angles = False
|
self.needs_new_joint_angles = False
|
||||||
self._data_has_changed = True
|
self._data_has_changed = True
|
||||||
|
|
||||||
points = self.get_points()
|
# Rotate points such that positive z direction is the normal
|
||||||
|
points = self.get_points() @ rotation_between_vectors(OUT, self.get_unit_normal())
|
||||||
|
|
||||||
if len(points) < 3:
|
if len(points) < 3:
|
||||||
return self.data["joint_angle"]
|
return self.data["joint_angle"][:, 0]
|
||||||
|
|
||||||
# Find all the unit tangent vectors at each joint
|
# Find all the unit tangent vectors at each joint
|
||||||
a0, h, a1 = points[0:-1:2], points[1::2], points[2::2]
|
a0, h, a1 = points[0:-1:2], points[1::2], points[2::2]
|
||||||
|
@ -1201,23 +1203,19 @@ class VMobject(Mobject):
|
||||||
for start, end in zip(starts, ends):
|
for start, end in zip(starts, ends):
|
||||||
if start >= end - 2:
|
if start >= end - 2:
|
||||||
continue
|
continue
|
||||||
if self.consider_points_equal(points[start], points[end]):
|
if (points[start] == points[end]).all():
|
||||||
v_in[start] = v_out[end - 1]
|
v_in[start] = v_out[end - 1]
|
||||||
v_out[end] = v_in[start + 1]
|
v_out[end] = v_in[start + 1]
|
||||||
else:
|
else:
|
||||||
v_in[start] = v_out[start]
|
v_in[start] = v_out[start]
|
||||||
v_out[end] = v_in[end]
|
v_out[end] = v_in[end]
|
||||||
|
|
||||||
# Compute dot and cross products
|
# Find the angles between vectors into each vertex, and out of it
|
||||||
in_dot_out = (v_in * v_out).sum(1)
|
angles_in = np.arctan2(v_in[:, 1], v_in[:, 0])
|
||||||
norm_product = np.sqrt((v_in * v_in).sum(1) * (v_out * v_out).sum(1))
|
angles_out = np.arctan2(v_out[:, 1], v_out[:, 0])
|
||||||
angles = np.arccos(fdiv(in_dot_out, norm_product, zero_over_zero_value=1))
|
angle_diffs = angles_out - angles_in
|
||||||
|
self.data["joint_angle"][:, 0] = (angle_diffs + PI) % TAU - PI
|
||||||
crosses = cross(v_in, v_out)
|
return self.data["joint_angle"][:, 0]
|
||||||
unit_normal = self.get_unit_normal()
|
|
||||||
angles[(crosses * unit_normal[np.newaxis, :]).sum(1) < 0] *= -1
|
|
||||||
self.data["joint_angle"][:, 0] = angles
|
|
||||||
return self.data["joint_angle"]
|
|
||||||
|
|
||||||
def lock_matching_data(self, vmobject1: VMobject, vmobject2: VMobject) -> Self:
|
def lock_matching_data(self, vmobject1: VMobject, vmobject2: VMobject) -> Self:
|
||||||
for mob in [self, vmobject1, vmobject2]:
|
for mob in [self, vmobject1, vmobject2]:
|
||||||
|
|
Loading…
Add table
Reference in a new issue