Add alternate smoothing options

This commit is contained in:
Grant Sanderson
2021-02-05 16:29:07 -08:00
parent f87b82a9e9
commit 66817c4e2b
3 changed files with 28 additions and 14 deletions

View File

@ -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

View File

@ -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

View File

@ -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