Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    def pointwise_become_partial(self, mobject, a, b):
        assert(isinstance(mobject, 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(mobject.points)
            self.mark_paths_closed = mobject.mark_paths_closed
            return self
        self.mark_paths_closed = False
        num_cubics = mobject.get_num_anchor_points() - 1
        lower_index = int(a * num_cubics)
        upper_index = int(b * num_cubics)
        points = np.array(
            mobject.points[3 * lower_index:3 * upper_index + 4]
        )
        if len(points) > 1:
            a_residue = (num_cubics * a) % 1
            b_residue = (num_cubics * b) % 1
            if b == 1:
                b_residue = 1
            elif lower_index == upper_index:
                b_residue = (b_residue - a_residue) / (1 - a_residue)

            points[:4] = partial_bezier_points(
                points[:4], a_residue, 1
            )
            points[-4:] = partial_bezier_points(
                points[-4:], 0, b_residue
            )
        self.set_points(points)
        return self
Ejemplo n.º 4
0
    def insert_n_curves_to_point_list(self, n, points):
        if len(points) == 1:
            nppcc = self.n_points_per_cubic_curve
            return np.repeat(points, nppcc * n, 0)
        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
        # it's total length is target_num.  For example,
        # with curr_num = 10, target_num = 15, this would
        # be [0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9]
        repeat_indices = (np.arange(target_num) * curr_num) // target_num

        # If the nth term of this list is k, it means
        # that the nth curve of our path should be split
        # into k pieces.  In the above example, this would
        # be [2, 1, 2, 1, 2, 1, 2, 1, 2, 1]
        split_factors = [sum(repeat_indices == i) for i in range(curr_num)]
        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 "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:]):
                new_points = np.append(new_points,
                                       partial_bezier_points(quad, a1, a2),
                                       axis=0)
        return new_points
Ejemplo n.º 5
0
 def insert_n_anchor_points(self, n):
     curr = self.get_num_anchor_points()
     if curr == 0:
         self.points = np.zeros((1, 3))
         n = n - 1
     if curr == 1:
         self.points = np.repeat(self.points, 3 * n + 1, axis=0)
         return self
     points = np.array([self.points[0]])
     num_curves = curr - 1
     # Curves in self are buckets, and we need to know
     # how many new anchor points to put into each one.
     # Each element of index_allocation is like a bucket,
     # and its value tells you the appropriate index of
     # the smaller curve.
     index_allocation = (
         np.arange(curr + n - 1) * num_curves) // (curr + n - 1)
     for index in range(num_curves):
         curr_bezier_points = self.points[3 * index:3 * index + 4]
         num_inter_curves = sum(index_allocation == index)
         alphas = np.linspace(0, 1, num_inter_curves + 1)
         # alphas = np.arange(0, num_inter_curves+1)/float(num_inter_curves)
         for a, b in zip(alphas, alphas[1:]):
             new_points = partial_bezier_points(
                 curr_bezier_points, a, b
             )
             points = np.append(
                 points, new_points[1:], axis=0
             )
     self.set_points(points)
     return self
    def insert_n_curves_to_point_list(self, n, points):
        nppc = self.n_points_per_curve
        if len(points) == 1:
            return np.repeat(points, nppc * n, 0)

        bezier_groups = self.get_bezier_tuples_from_points(points)
        norms = np.array(
            [get_norm(bg[nppc - 1] - bg[0]) for bg in bezier_groups])
        total_norm = sum(norms)
        # Calculate insertions per curve (ipc)
        if total_norm < 1e-6:
            ipc = [n] + [0] * (len(bezier_groups) - 1)
        else:
            ipc = np.round(n * norms / sum(norms)).astype(int)

        diff = n - sum(ipc)
        for x in range(diff):
            ipc[np.argmin(ipc)] += 1
        for x in range(-diff):
            ipc[np.argmax(ipc)] -= 1

        new_points = []
        for group, n_inserts in zip(bezier_groups, ipc):
            # What was once a single quadratic curve defined
            # by "group" will now be broken into n_inserts + 1
            # smaller quadratic curves
            alphas = np.linspace(0, 1, n_inserts + 2)
            for a1, a2 in zip(alphas, alphas[1:]):
                new_points += partial_bezier_points(group, a1, a2)
        return np.vstack(new_points)
Ejemplo n.º 7
0
    def insert_n_curves_to_point_list(self, n, points):
        if len(points) == 1:
            nppcc = self.n_points_per_cubic_curve
            return np.repeat(points, nppcc * n, 0)
        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
        # it's total length is target_num.  For example,
        # with curr_num = 10, target_num = 15, this would
        # be [0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9]
        repeat_indices = (np.arange(target_num) * curr_num) // target_num

        # If the nth term of this list is k, it means
        # that the nth curve of our path should be split
        # into k pieces.  In the above example, this would
        # be [2, 1, 2, 1, 2, 1, 2, 1, 2, 1]
        split_factors = [
            sum(repeat_indices == i)
            for i in range(curr_num)
        ]
        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 "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:]):
                new_points = np.append(
                    new_points,
                    partial_bezier_points(quad, a1, a2),
                    axis=0
                )
        return new_points
    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 subdivide_sharp_curves(self,
                               angle_threshold=30 * DEGREES,
                               family=True):
        if family:
            vmobs = self.family_members_with_points()
        else:
            vmobs = [self] if self.has_points() else []

        for vmob in vmobs:
            new_points = []
            for tup in vmob.get_bezier_tuples():
                angle = angle_between_vectors(tup[1] - tup[0], tup[2] - tup[1])
                if angle > angle_threshold:
                    n = int(np.ceil(angle / angle_threshold))
                    alphas = np.linspace(0, 1, n + 1)
                    new_points.extend([
                        partial_bezier_points(tup, a1, a2)
                        for a1, a2 in zip(alphas, alphas[1:])
                    ])
                else:
                    new_points.append(tup)
            vmob.points = np.vstack(new_points)
        return self