mirror of
https://github.com/3b1b/manim.git
synced 2025-07-27 20:12:24 +08:00
Add alternate smoothing options
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
from manimlib.constants import *
|
||||
from manimlib.mobject.types.vectorized_mobject import VMobject
|
||||
from manimlib.utils.config_ops import digest_config
|
||||
from manimlib.utils.space_ops import get_norm
|
||||
|
||||
|
||||
class ParametricCurve(VMobject):
|
||||
@ -11,7 +10,6 @@ class ParametricCurve(VMobject):
|
||||
"epsilon": 1e-8,
|
||||
# TODO, automatically figure out discontinuities
|
||||
"discontinuities": [],
|
||||
"smoothing": True,
|
||||
}
|
||||
|
||||
def __init__(self, t_func, t_range=None, **kwargs):
|
||||
@ -42,8 +40,7 @@ class ParametricCurve(VMobject):
|
||||
points = np.array([self.t_func(t) for t in t_range])
|
||||
self.start_new_path(points[0])
|
||||
self.add_points_as_corners(points[1:])
|
||||
if self.smoothing:
|
||||
self.make_smooth()
|
||||
self.make_smooth(true_smooth=False)
|
||||
return self
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@ from manimlib.mobject.mobject import Mobject
|
||||
from manimlib.mobject.mobject import Point
|
||||
from manimlib.utils.bezier import bezier
|
||||
from manimlib.utils.bezier import get_smooth_quadratic_bezier_handle_points
|
||||
from manimlib.utils.bezier import get_smooth_cubic_bezier_handle_points
|
||||
from manimlib.utils.bezier import get_quadratic_approximation_of_cubic
|
||||
from manimlib.utils.bezier import interpolate
|
||||
from manimlib.utils.bezier import integer_interpolate
|
||||
@ -402,13 +403,13 @@ class VMobject(Mobject):
|
||||
])
|
||||
return self
|
||||
|
||||
def set_points_smoothly(self, points):
|
||||
def set_points_smoothly(self, points, true_smooth=False):
|
||||
self.set_points_as_corners(points)
|
||||
self.make_smooth()
|
||||
self.make_smooth(true_smooth)
|
||||
return self
|
||||
|
||||
def change_anchor_mode(self, mode):
|
||||
assert(mode in ["jagged", "smooth"])
|
||||
assert(mode in ["jagged", "approx_smooth", "true_smooth"])
|
||||
nppc = self.n_points_per_curve
|
||||
for submob in self.family_members_with_points():
|
||||
subpaths = submob.get_subpaths()
|
||||
@ -416,17 +417,27 @@ class VMobject(Mobject):
|
||||
for subpath in subpaths:
|
||||
anchors = np.vstack([subpath[::nppc], subpath[-1:]])
|
||||
new_subpath = np.array(subpath)
|
||||
if mode == "smooth":
|
||||
if mode == "approx_smooth":
|
||||
new_subpath[1::nppc] = get_smooth_quadratic_bezier_handle_points(anchors)
|
||||
elif mode == "true_smooth":
|
||||
h1, h2 = get_smooth_cubic_bezier_handle_points(anchors)
|
||||
new_subpath = get_quadratic_approximation_of_cubic(anchors[:-1], h1, h2, anchors[1:])
|
||||
elif mode == "jagged":
|
||||
new_subpath[1::nppc] = 0.5 * (anchors[:-1] + anchors[1:])
|
||||
submob.append_points(new_subpath)
|
||||
submob.refresh_triangulation()
|
||||
return self
|
||||
|
||||
def make_smooth(self):
|
||||
# TODO, Change this to not rely on a cubic-to-quadratic conversion
|
||||
return self.change_anchor_mode("smooth")
|
||||
def make_smooth(self, true_smooth=True):
|
||||
"""
|
||||
If true_smooth is set to True, the number of points
|
||||
in the mobject will double, but the effect will be
|
||||
a genuinely smooth (C2) curve. Otherwise, it may not
|
||||
becomes perfectly smooth, but the number of points
|
||||
will stay the same.
|
||||
"""
|
||||
mode = "true_smooth" if true_smooth else "approx_smooth"
|
||||
return self.change_anchor_mode(mode)
|
||||
|
||||
def make_jagged(self):
|
||||
return self.change_anchor_mode("jagged")
|
||||
@ -824,7 +835,7 @@ class VMobject(Mobject):
|
||||
def apply_function(self, function):
|
||||
super().apply_function(function)
|
||||
if self.make_smooth_after_applying_functions:
|
||||
self.make_smooth()
|
||||
self.make_smooth(true_smooth=False)
|
||||
return self
|
||||
|
||||
@triggers_refreshed_triangulation
|
||||
|
@ -134,8 +134,14 @@ def get_smooth_quadratic_bezier_handle_points(points):
|
||||
0.25 * ps[0:-2] + ps[1:-1] - 0.25 * ps[2:]
|
||||
for ps in (points, points[::-1])
|
||||
]
|
||||
handles = 0.5 * np.vstack([smooth_to_right, [smooth_to_left[0]]])
|
||||
handles += 0.5 * np.vstack([smooth_to_right[0], smooth_to_left[::-1]])
|
||||
if np.isclose(points[0], points[-1]).all():
|
||||
last_str = 0.25 * points[-2] + points[-1] - 0.25 * points[1]
|
||||
last_stl = 0.25 * points[1] + points[0] - 0.25 * points[-2]
|
||||
else:
|
||||
last_str = smooth_to_left[0]
|
||||
last_stl = smooth_to_right[0]
|
||||
handles = 0.5 * np.vstack([smooth_to_right, [last_str]])
|
||||
handles += 0.5 * np.vstack([last_stl, smooth_to_left[::-1]])
|
||||
return handles
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user