def get_partial_points_array(self, points, a, b, resolution, axis): if len(points) == 0: return points nu, nv = resolution[:2] points = points.reshape(resolution) max_index = resolution[axis] - 1 lower_index, lower_residue = integer_interpolate(0, max_index, a) upper_index, upper_residue = integer_interpolate(0, max_index, b) if axis == 0: points[:lower_index] = interpolate( points[lower_index], points[lower_index + 1], lower_residue ) points[upper_index + 1:] = interpolate( points[upper_index], points[upper_index + 1], upper_residue ) else: shape = (nu, 1, resolution[2]) points[:, :lower_index] = interpolate( points[:, lower_index], points[:, lower_index + 1], lower_residue ).reshape(shape) points[:, upper_index + 1:] = interpolate( points[:, upper_index], points[:, upper_index + 1], upper_residue ).reshape(shape) return points.reshape((nu * nv, *resolution[2:]))
def pointwise_become_partial(self, vmobject, a, b): assert (isinstance(vmobject, VMobject)) # Partial curve includes three portions: # - A middle section, which matches the curve exactly # - A start, which is some ending portion of an inner cubic # - An end, which is the starting portion of a later inner cubic if a <= 0 and b >= 1: self.set_points(vmobject.points) return self bezier_quads = vmobject.get_cubic_bezier_tuples() num_cubics = len(bezier_quads) lower_index, lower_residue = integer_interpolate(0, num_cubics, a) upper_index, upper_residue = integer_interpolate(0, num_cubics, b) self.clear_points() if num_cubics == 0: return self if lower_index == upper_index: self.append_points( partial_bezier_points(bezier_quads[lower_index], lower_residue, upper_residue)) else: self.append_points( partial_bezier_points(bezier_quads[lower_index], lower_residue, 1)) for quad in bezier_quads[lower_index + 1:upper_index]: self.append_points(quad) self.append_points( partial_bezier_points(bezier_quads[upper_index], 0, upper_residue)) return self
def pointwise_become_partial(self, vmobject, a, b): assert(isinstance(vmobject, VMobject)) # Partial curve includes three portions: # - A middle section, which matches the curve exactly # - A start, which is some ending portion of an inner cubic # - An end, which is the starting portion of a later inner cubic if a <= 0 and b >= 1: self.set_points(vmobject.points) return self bezier_quads = vmobject.get_cubic_bezier_tuples() num_cubics = len(bezier_quads) lower_index, lower_residue = integer_interpolate(0, num_cubics, a) upper_index, upper_residue = integer_interpolate(0, num_cubics, b) self.clear_points() if num_cubics == 0: return self if lower_index == upper_index: self.append_points(partial_bezier_points( bezier_quads[lower_index], lower_residue, upper_residue )) else: self.append_points(partial_bezier_points( bezier_quads[lower_index], lower_residue, 1 )) for quad in bezier_quads[lower_index + 1:upper_index]: self.append_points(quad) self.append_points(partial_bezier_points( bezier_quads[upper_index], 0, upper_residue )) return self
def interpolate_submobject(self, submob, start, outline, alpha): index, subalpha = integer_interpolate(0, 2, alpha) if index == 0: submob.pointwise_become_partial(outline, 0, subalpha) submob.match_style(outline) else: submob.interpolate(outline, start, subalpha)
def pointwise_become_partial(self, vmobject, a, b): assert isinstance(vmobject, VMobject) if a <= 0 and b >= 1: self.become(vmobject) return self num_curves = vmobject.get_num_curves() nppc = self.n_points_per_curve # Partial curve includes three portions: # - A middle section, which matches the curve exactly # - A start, which is some ending portion of an inner quadratic # - An end, which is the starting portion of a later inner quadratic lower_index, lower_residue = integer_interpolate(0, num_curves, a) upper_index, upper_residue = integer_interpolate(0, num_curves, b) i1 = nppc * lower_index i2 = nppc * (lower_index + 1) i3 = nppc * upper_index i4 = nppc * (upper_index + 1) vm_points = vmobject.get_points() new_points = vm_points.copy() if num_curves == 0: new_points[:] = 0 return self if lower_index == upper_index: tup = partial_quadratic_bezier_points( vm_points[i1:i2], lower_residue, upper_residue ) new_points[:i1] = tup[0] new_points[i1:i4] = tup new_points[i4:] = tup[2] new_points[nppc:] = new_points[nppc - 1] else: low_tup = partial_quadratic_bezier_points( vm_points[i1:i2], lower_residue, 1 ) high_tup = partial_quadratic_bezier_points( vm_points[i3:i4], 0, upper_residue ) new_points[0:i1] = low_tup[0] new_points[i1:i2] = low_tup # Keep new_points i2:i3 as they are new_points[i3:i4] = high_tup new_points[i4:] = high_tup[2] self.set_points(new_points) return self
def interpolate(self, alpha): index, subalpha = integer_interpolate(0, len(self.animations), alpha) animation = self.animations[index] if animation is not self.active_animation: self.active_animation.finish() animation.begin() self.active_animation = animation animation.interpolate(subalpha)
def interpolate_submobject(self, submob, start, outline, alpha): index, subalpha = integer_interpolate(0, 2, alpha) if index == 0: submob.pointwise_become_partial( outline, 0, subalpha ) submob.match_style(outline) else: submob.interpolate(outline, start, subalpha)
def pointwise_become_partial(self, vmobject, a, b): assert (isinstance(vmobject, VMobject)) assert (len(self.points) >= len(vmobject.points)) if a <= 0 and b >= 1: self.points[:] = vmobject.points return self bezier_tuple = vmobject.get_bezier_tuples() num_curves = len(bezier_tuple) # Partial curve includes three portions: # - A middle section, which matches the curve exactly # - A start, which is some ending portion of an inner quadratic # - An end, which is the starting portion of a later inner quadratic lower_index, lower_residue = integer_interpolate(0, num_curves, a) upper_index, upper_residue = integer_interpolate(0, num_curves, b) new_point_list = [] if num_curves == 0: self.points[:] = 0 return self if lower_index == upper_index: new_point_list.append( partial_bezier_points(bezier_tuple[lower_index], lower_residue, upper_residue)) else: new_point_list.append( partial_bezier_points(bezier_tuple[lower_index], lower_residue, 1)) for tup in bezier_tuple[lower_index + 1:upper_index]: new_point_list.append(tup) new_point_list.append( partial_bezier_points(bezier_tuple[upper_index], 0, upper_residue)) new_points = np.vstack(new_point_list) self.points[:len(new_points)] = new_points self.points[len(new_points):] = new_points[-1] return self
def interpolate_submobject(self, submob, start, outline, alpha): index, subalpha = integer_interpolate(0, 2, alpha) if index == 1 and self.sm_to_index[hash(submob)] == 0: # First time crossing over submob.set_data(outline.data) submob.unlock_data() submob.lock_matching_data(submob, start) self.sm_to_index[hash(submob)] = 1 if index == 0: submob.pointwise_become_partial(outline, 0, subalpha) else: submob.interpolate(outline, start, subalpha)
def get_partial_points_array(self, points, a, b, resolution, axis): nu, nv = resolution[:2] points = points.reshape(resolution) max_index = resolution[axis] - 1 lower_index, lower_residue = integer_interpolate(0, max_index, a) upper_index, upper_residue = integer_interpolate(0, max_index, b) if axis == 0: points[:lower_index] = interpolate(points[lower_index], points[lower_index + 1], lower_residue) points[upper_index:] = interpolate(points[upper_index], points[upper_index + 1], upper_residue) else: tuples = [ (points[:, :lower_index], lower_index, lower_residue), (points[:, upper_index:], upper_index, upper_residue), ] for to_change, index, residue in tuples: col = interpolate(points[:, index], points[:, index + 1], residue) to_change[:] = col.reshape((nu, 1, *resolution[2:])) return points.reshape((nu * nv, *resolution[2:]))
def interpolate_submobject(self, submob: VMobject, start: VMobject, outline: VMobject, alpha: float) -> None: index, subalpha = integer_interpolate(0, 2, alpha) if index == 1 and self.sm_to_index[hash(submob)] == 0: # First time crossing over submob.set_data(outline.data) submob.unlock_data() if not self.mobject.has_updaters: submob.lock_matching_data(submob, start) submob.needs_new_triangulation = False self.sm_to_index[hash(submob)] = 1 if index == 0: submob.pointwise_become_partial(outline, 0, subalpha) else: submob.interpolate(outline, start, subalpha)
def point_from_proportion(self, alpha): num_curves = self.get_num_curves() n, residue = integer_interpolate(0, num_curves, alpha) curve_func = self.get_nth_curve_function(n) return curve_func(residue)
def quick_point_from_proportion(self, alpha: float) -> np.ndarray: # Assumes all curves have the same length, so is inaccurate num_curves = self.get_num_curves() n, residue = integer_interpolate(0, num_curves, alpha) curve_func = self.get_nth_curve_function(n) return curve_func(residue)
def point_from_proportion(self, alpha): num_cubics = self.get_num_curves() n, residue = integer_interpolate(0, num_cubics, alpha) curve = self.get_nth_curve_function(n) return curve(residue)