mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Remove add_control_points, re-implement VMobject.align_points
This commit is contained in:
parent
eaf25ff34b
commit
1f46904f9b
9 changed files with 88 additions and 53 deletions
|
@ -365,7 +365,7 @@ class Camera(object):
|
|||
)
|
||||
|
||||
last_p3 = None
|
||||
quads = vmobject.get_all_cubic_bezier_point_tuples()
|
||||
quads = vmobject.get_cubic_bezier_tuples()
|
||||
ctx.new_path()
|
||||
for p0, p1, p2, p3 in quads:
|
||||
if should_start_new_path(last_p3, p0):
|
||||
|
|
|
@ -878,10 +878,10 @@ class Mobject(Container):
|
|||
]).arrange(v2, **kwargs)
|
||||
return self
|
||||
|
||||
def sort(self, point_to_num_func=lambda p: p[0]):
|
||||
self.submobjects.sort(
|
||||
key=lambda m: point_to_num_func(m.get_center())
|
||||
)
|
||||
def sort(self, point_to_num_func=lambda p: p[0], submob_func=None):
|
||||
if submob_func is None:
|
||||
submob_func = lambda m: point_to_num_func(m.get_center())
|
||||
self.submobjects.sort(key=submob_func)
|
||||
return self
|
||||
|
||||
def shuffle(self, recursive=False):
|
||||
|
|
|
@ -350,7 +350,6 @@ class VMobjectFromSVGPathstring(VMobject):
|
|||
|
||||
if command == "M": # moveto
|
||||
self.start_new_path(new_points[0])
|
||||
|
||||
if len(new_points) <= 1:
|
||||
return
|
||||
|
||||
|
@ -383,12 +382,7 @@ class VMobjectFromSVGPathstring(VMobject):
|
|||
elif command == "A": # elliptical Arc
|
||||
raise Exception("Not implemented")
|
||||
elif command == "Z": # closepath
|
||||
if is_closed(points):
|
||||
return
|
||||
# Both handles and new anchor are the start
|
||||
# TODO, is this needed?
|
||||
new_points = points[[0, 0, 0]]
|
||||
# self.mark_paths_closed = True
|
||||
return
|
||||
|
||||
# Handle situations where there's multiple relative control points
|
||||
if isLower and len(new_points) > 3:
|
||||
|
|
|
@ -464,16 +464,6 @@ class VMobject(Mobject):
|
|||
])
|
||||
return self
|
||||
|
||||
# TODO, remove
|
||||
# def add_control_points(self, control_points):
|
||||
# assert(len(control_points) % 3 == 0)
|
||||
# self.points = np.append(
|
||||
# self.points,
|
||||
# control_points,
|
||||
# axis=0
|
||||
# )
|
||||
# return self
|
||||
|
||||
def has_new_path_started(self):
|
||||
nppcc = self.n_points_per_cubic_curve # 4
|
||||
return len(self.points) % nppcc == 1
|
||||
|
@ -580,19 +570,37 @@ class VMobject(Mobject):
|
|||
)
|
||||
|
||||
# Information about line
|
||||
|
||||
def get_all_cubic_bezier_point_tuples(self):
|
||||
points = self.get_points()
|
||||
if self.has_new_path_started():
|
||||
points = points[:-1]
|
||||
# TODO, Throw error if len(points) is > 1 and
|
||||
# not divisible by 4 (i.e. n_points_per_cubic_curve)
|
||||
nppcc = self.n_points_per_cubic_curve
|
||||
def get_cubic_bezier_tuples_from_points(self, points):
|
||||
nppcc = VMobject.CONFIG["n_points_per_cubic_curve"]
|
||||
remainder = len(points) % nppcc
|
||||
points = points[:len(points) - remainder]
|
||||
return np.array([
|
||||
points[i:i + nppcc]
|
||||
for i in range(0, len(points), nppcc)
|
||||
])
|
||||
|
||||
def get_cubic_bezier_tuples(self):
|
||||
return self.get_cubic_bezier_tuples_from_points(
|
||||
self.get_points()
|
||||
)
|
||||
|
||||
def get_subpaths_from_points(self, points):
|
||||
nppcc = VMobject.CONFIG["n_points_per_cubic_curve"]
|
||||
split_indices = filter(
|
||||
lambda n: not self.consider_points_equals(
|
||||
points[n - 1], points[n]
|
||||
),
|
||||
range(nppcc, len(points), nppcc)
|
||||
)
|
||||
split_indices = [0] + list(split_indices) + [len(points)]
|
||||
return [
|
||||
points[i1:i2]
|
||||
for i1, i2 in zip(split_indices, split_indices[1:])
|
||||
]
|
||||
|
||||
def get_subpaths(self):
|
||||
return self.get_subpaths_from_points(self.get_points())
|
||||
|
||||
def get_nth_curve_points(self, n):
|
||||
assert(n < self.get_num_curves())
|
||||
nppcc = self.n_points_per_cubic_curve
|
||||
|
@ -645,9 +653,35 @@ class VMobject(Mobject):
|
|||
|
||||
# Alignment
|
||||
def align_points(self, vmobject):
|
||||
# This will call back to align_points_with_larger
|
||||
Mobject.align_points(self, vmobject)
|
||||
self.align_rgbas(vmobject)
|
||||
nppcc = self.n_points_per_cubic_curve
|
||||
subpaths1 = self.get_subpaths()
|
||||
subpaths2 = vmobject.get_subpaths()
|
||||
new_path1 = np.zeros((0, self.dim))
|
||||
new_path2 = np.zeros((0, self.dim))
|
||||
n_subpaths = max(len(subpaths1), len(subpaths2))
|
||||
|
||||
def get_nth_subpath(path_list, n):
|
||||
if n < len(path_list):
|
||||
return path_list[n]
|
||||
last_path = path_list[n - 1]
|
||||
return [last_path[-1]] * nppcc
|
||||
|
||||
for n in range(n_subpaths):
|
||||
sp1 = get_nth_subpath(subpaths1, n)
|
||||
sp2 = get_nth_subpath(subpaths2, n)
|
||||
diff = len(sp2) - len(sp1)
|
||||
if diff < 0:
|
||||
sp2 = self.insert_n_curves_to_point_list(
|
||||
-diff // nppcc, sp2
|
||||
)
|
||||
elif diff > 0:
|
||||
sp1 = self.insert_n_curves_to_point_list(
|
||||
diff // nppcc, sp1
|
||||
)
|
||||
new_path1 = np.append(new_path1, sp1, axis=0)
|
||||
new_path2 = np.append(new_path2, sp2, axis=0)
|
||||
self.set_points(new_path1)
|
||||
vmobject.set_points(new_path2)
|
||||
return self
|
||||
|
||||
def align_points_with_larger(self, larger_mobject):
|
||||
|
@ -661,8 +695,18 @@ class VMobject(Mobject):
|
|||
new_path_point = None
|
||||
if self.has_new_path_started():
|
||||
new_path_point = self.get_last_point()
|
||||
curr_curve_points = self.get_all_cubic_bezier_point_tuples()
|
||||
curr_num = len(curr_curve_points)
|
||||
self.set_points(
|
||||
self.insert_n_curves_to_point_list(
|
||||
n, self.get_points()
|
||||
)
|
||||
)
|
||||
if new_path_point is not None:
|
||||
self.append_points([new_path_point])
|
||||
return self
|
||||
|
||||
def insert_n_curves_to_point_list(self, n, points):
|
||||
bezier_quads = self.get_cubic_bezier_tuples_from_points(points)
|
||||
curr_num = len(bezier_quads)
|
||||
target_num = curr_num + n
|
||||
# This is an array with values ranging from 0
|
||||
# up to curr_num, with repeats such that
|
||||
|
@ -679,20 +723,19 @@ class VMobject(Mobject):
|
|||
sum(repeat_indices == i)
|
||||
for i in range(curr_num)
|
||||
]
|
||||
|
||||
self.clear_points()
|
||||
for points, sf in zip(curr_curve_points, split_factors):
|
||||
new_points = np.zeros((0, self.dim))
|
||||
for quad, sf in zip(bezier_quads, split_factors):
|
||||
# What was once a single cubic curve defined
|
||||
# by "points" will now be broken into sf
|
||||
# by "quad" will now be broken into sf
|
||||
# smaller cubic curves
|
||||
alphas = np.linspace(0, 1, sf + 1)
|
||||
for a1, a2 in zip(alphas, alphas[1:]):
|
||||
self.append_points(
|
||||
partial_bezier_points(points, a1, a2)
|
||||
new_points = np.append(
|
||||
new_points,
|
||||
partial_bezier_points(quad, a1, a2),
|
||||
axis=0
|
||||
)
|
||||
if new_path_point is not None:
|
||||
self.append_points([new_path_point])
|
||||
return self
|
||||
return new_points
|
||||
|
||||
def align_rgbas(self, vmobject):
|
||||
attrs = ["fill_rgbas", "stroke_rgbas", "background_stroke_rgbas"]
|
||||
|
@ -740,7 +783,7 @@ class VMobject(Mobject):
|
|||
if a <= 0 and b >= 1:
|
||||
self.set_points(vmobject.points)
|
||||
return self
|
||||
bezier_quads = vmobject.get_all_cubic_bezier_point_tuples()
|
||||
bezier_quads = vmobject.get_cubic_bezier_tuples()
|
||||
num_cubics = len(bezier_quads)
|
||||
|
||||
lower_index, lower_residue = integer_interpolate(0, num_cubics, a)
|
||||
|
|
|
@ -1678,10 +1678,8 @@ class AnalyzeCircleGeometry(CircleDiagramFromSlidingBlocks, MovingCameraScene):
|
|||
two_theta_labels.add(label)
|
||||
|
||||
wedge = arc.copy()
|
||||
wedge.add_control_points([
|
||||
*3 * [ORIGIN],
|
||||
*3 * [wedge.points[0]]
|
||||
])
|
||||
wedge.add_line_to(ORIGIN)
|
||||
wedge.add_line_to(wedge.points[0])
|
||||
wedge.set_stroke(width=0)
|
||||
wedge.set_fill(arc.get_color(), 0.2)
|
||||
wedges.add(wedge)
|
||||
|
|
|
@ -842,7 +842,7 @@ class Test(Scene):
|
|||
for arc, vect in zip(arcs, [DOWN+RIGHT, RIGHT]):
|
||||
arc_copy = arc.copy()
|
||||
point = domino1.get_critical_point(vect)
|
||||
arc_copy.add_control_points(3*[point])
|
||||
arc_copy.add_line_to([point])
|
||||
arc_copy.set_stroke(width = 0)
|
||||
arc_copy.set_fill(
|
||||
arc.get_stroke_color(),
|
||||
|
|
|
@ -608,7 +608,7 @@ class FakeDiagram(TeacherStudentsScene):
|
|||
axis_point = end_point[0]*RIGHT + gs.graph_origin[1]*UP
|
||||
for alpha in np.linspace(0, 1, 20):
|
||||
point = interpolate(axis_point, graph.points[0], alpha)
|
||||
graph.add_control_points(3*[point])
|
||||
graph.add_line_to(point)
|
||||
graph.set_stroke(width = 1)
|
||||
graph.set_fill(opacity = 1)
|
||||
graph.set_color(BLUE_D)
|
||||
|
|
|
@ -574,7 +574,7 @@ class IntegrationByParts(Scene):
|
|||
regions = []
|
||||
for vect, color in (UP+RIGHT, BLUE), (DOWN+LEFT, GREEN):
|
||||
region = curve.copy()
|
||||
region.add_control_points(3*[rect.get_corner(vect)])
|
||||
region.add_line_to(rect.get_corner(vect))
|
||||
region.set_stroke(width = 0)
|
||||
region.set_fill(color = color, opacity = 0.5)
|
||||
regions.append(region)
|
||||
|
|
|
@ -340,7 +340,7 @@ class SourcesOfOriginality(TeacherStudentsScene):
|
|||
|
||||
blob1, blob2 = VMobject(), VMobject()
|
||||
blob1.set_points_smoothly(points + [points[0]])
|
||||
blob1.add_control_points(3 * len(added_points) * [points[0]])
|
||||
blob1.append_points(3 * len(added_points) * [points[0]])
|
||||
blob2.set_points_smoothly(points + added_points + [points[0]])
|
||||
for blob in blob1, blob2:
|
||||
blob.set_stroke(width=0)
|
||||
|
|
Loading…
Add table
Reference in a new issue