Example #1
0
    def point_to_number(self, point: Sequence[float]) -> float:
        """Accepts a point with respect to the scene and returns
        a float along the number line.

        Parameters
        ----------
        point
            A sequence of values consisting of ``(x_coord, y_coord, z_coord)``.

        Returns
        -------
        float
            A float representing a value along the number line.

        Examples
        --------

            >>> from manim import NumberLine
            >>> number_line = NumberLine()
            >>> number_line.point_to_number((0,0,0))
            0.0
            >>> number_line.point_to_number((1,0,0))
            1.0
            >>> number_line.point_to_number([[0.5,0,0],[1,0,0],[1.5,0,0]])
            array([0.5, 1. , 1.5])

        """
        point = np.asarray(point)
        start, end = self.get_start_and_end()
        unit_vect = normalize(end - start)
        proportion = np.dot(point - start, unit_vect) / np.dot(
            end - start, unit_vect)
        return interpolate(self.x_min, self.x_max, proportion)
Example #2
0
    def parallel_to(
        cls, line: Line3D, point: Sequence[float] = ORIGIN, length: float = 5, **kwargs
    ):
        """Returns a line parallel to another line going through
        a given point.

        Parameters
        ----------
        line
            The line to be parallel to.
        point
            The point to pass through.
        kwargs
            Additional parameters to be passed to the class.

        Examples
        --------
        .. manim:: ParallelLineExample
            :save_last_frame:

            class ParallelLineExample(ThreeDScene):
                def construct(self):
                    self.set_camera_orientation(PI / 3, -PI / 4)
                    ax = ThreeDAxes((-5, 5), (-5, 5), (-5, 5), 10, 10, 10)
                    line1 = Line3D(RIGHT * 2, UP + OUT, color=RED)
                    line2 = Line3D.parallel_to(line1, color=YELLOW)
                    self.add(ax, line1, line2)
        """
        point = np.array(point)
        vect = normalize(line.vect)
        return cls(
            point + vect * length / 2,
            point - vect * length / 2,
            **kwargs,
        )
Example #3
0
 def _set_start_and_end_attrs(self, start, end):
     # If either start or end are Mobjects, this
     # gives their centers
     rough_start = self._pointify(start)
     rough_end = self._pointify(end)
     vect = normalize(rough_end - rough_start)
     # Now that we know the direction between them,
     # we can find the appropriate boundary point from
     # start and end, if they're mobjects
     self.start = self._pointify(start, vect)
     self.end = self._pointify(end, -vect)
Example #4
0
    def get_normal_vector(self) -> np.ndarray:
        """Returns the normal of a vector.

        Examples
        --------
        ::

            >>> np.round(Arrow().get_normal_vector()) + 0. # add 0. to avoid negative 0 in output
            array([ 0.,  0., -1.])
        """

        p0, p1, p2 = self.tip.get_start_anchors()[:3]
        return normalize(np.cross(p2 - p1, p1 - p0))
Example #5
0
    def get_projection(self, point: Sequence[float]) -> Sequence[float]:
        """Returns the projection of a point onto a line.

        Parameters
        ----------
        point
            The point to which the line is projected.
        """

        start = self.get_start()
        end = self.get_end()
        unit_vect = normalize(end - start)
        return start + np.dot(point - start, unit_vect) * unit_vect
Example #6
0
    def point_to_number(self, point: Sequence[float]) -> float:
        """Accepts a point with respect to the scene and returns
        a float along the number line.

        Parameters
        ----------
        point
            A sequence of values consisting of ``(x_coord, y_coord, z_coord)``.

        Returns
        -------
        float
            A float representing a value along the number line.
        """
        start, end = self.get_start_and_end()
        unit_vect = normalize(end - start)
        proportion = np.dot(point - start, unit_vect) / np.dot(
            end - start, unit_vect)
        return interpolate(self.x_min, self.x_max, proportion)
Example #7
0
    def perpendicular_to(
        cls, line: Line3D, point: Sequence[float] = ORIGIN, length: float = 5, **kwargs
    ):
        """Returns a line perpendicular to another line going through
        a given point.

        Parameters
        ----------
        line
            The line to be perpendicular to.
        point
            The point to pass through.
        kwargs
            Additional parameters to be passed to the class.

        Examples
        --------
        .. manim:: PerpLineExample
            :save_last_frame:

            class PerpLineExample(ThreeDScene):
                def construct(self):
                    self.set_camera_orientation(PI / 3, -PI / 4)
                    ax = ThreeDAxes((-5, 5), (-5, 5), (-5, 5), 10, 10, 10)
                    line1 = Line3D(RIGHT * 2, UP + OUT, color=RED)
                    line2 = Line3D.perpendicular_to(line1, color=BLUE)
                    self.add(ax, line1, line2)
        """
        point = np.array(point)

        norm = np.cross(line.vect, point - line.start)
        if all(np.linalg.norm(norm) == np.zeros(3)):
            raise ValueError("Could not find the perpendicular.")

        start, end = perpendicular_bisector([line.start, line.end], norm)
        vect = normalize(end - start)
        return cls(
            point + vect * length / 2,
            point - vect * length / 2,
            **kwargs,
        )
Example #8
0
    def set_start_and_end_attrs(self, start, end, **kwargs):
        """Sets the start and end points of the line.

        If either ``start`` or ``end`` are :class:`Mobjects <.Mobject>`, this gives their centers.
        """
        rough_start = self.pointify(start)
        rough_end = self.pointify(end)
        self.vect = rough_end - rough_start
        self.length = np.linalg.norm(self.vect)
        self.direction = normalize(self.vect)
        # Now that we know the direction between them,
        # we can the appropriate boundary point from
        # start and end, if they're mobjects
        self.start = self.pointify(start, self.direction)
        self.end = self.pointify(end, -self.direction)
        super().__init__(
            height=np.linalg.norm(self.vect),
            radius=self.thickness,
            direction=self.direction,
            **kwargs,
        )
        self.shift((self.start + self.end) / 2)
Example #9
0
 def get_unit_vector(self):
     return normalize(self.get_vector())
Example #10
0
    def round_corners(self, radius: float = 0.5):
        """Rounds off the corners of the :class:`Polygram`.

        Parameters
        ----------
        radius
            The curvature of the corners of the :class:`Polygram`.


        .. seealso::
            :class:`.~RoundedRectangle`

        Examples
        --------
        .. manim:: PolygramRoundCorners
            :save_last_frame:

            class PolygramRoundCorners(Scene):
                def construct(self):
                    star = Star(outer_radius=2)

                    shapes = VGroup(star)
                    shapes.add(star.copy().round_corners(radius=0.1))
                    shapes.add(star.copy().round_corners(radius=0.25))

                    shapes.arrange(RIGHT)
                    self.add(shapes)
        """

        if radius == 0:
            return self

        new_points = []

        for vertices in self.get_vertex_groups():
            arcs = []
            for v1, v2, v3 in adjacent_n_tuples(vertices, 3):
                vect1 = v2 - v1
                vect2 = v3 - v2
                unit_vect1 = normalize(vect1)
                unit_vect2 = normalize(vect2)

                angle = angle_between_vectors(vect1, vect2)
                # Negative radius gives concave curves
                angle *= np.sign(radius)

                # Distance between vertex and start of the arc
                cut_off_length = radius * np.tan(angle / 2)

                # Determines counterclockwise vs. clockwise
                sign = np.sign(np.cross(vect1, vect2)[2])

                arc = ArcBetweenPoints(
                    v2 - unit_vect1 * cut_off_length,
                    v2 + unit_vect2 * cut_off_length,
                    angle=sign * angle,
                )
                arcs.append(arc)

            # To ensure that we loop through starting with last
            arcs = [arcs[-1], *arcs[:-1]]
            from manim.mobject.geometry.line import Line

            for arc1, arc2 in adjacent_pairs(arcs):
                new_points.extend(arc1.points)

                line = Line(arc1.get_end(), arc2.get_start())

                # Make sure anchors are evenly distributed
                len_ratio = line.get_length() / arc1.get_arc_length()

                line.insert_n_curves(int(arc1.get_num_curves() * len_ratio))

                new_points.extend(line.points)

        self.set_points(new_points)

        return self