Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New tip shape :class:.StealthTip, allow specifying tip shape of :class:.NumberLine #3201

Merged
merged 11 commits into from Apr 5, 2023
43 changes: 43 additions & 0 deletions manim/mobject/geometry/tips.py
Expand Up @@ -10,6 +10,7 @@
"ArrowSquareFilledTip",
"ArrowTriangleTip",
"ArrowTriangleFilledTip",
"StealthTip",
]

import numpy as np
Expand All @@ -32,6 +33,7 @@ class ArrowTip(VMobject, metaclass=ConvertToOpenGL):
:class:`ArrowCircleFilledTip`
:class:`ArrowSquareTip`
:class:`ArrowSquareFilledTip`
:class:`StealthTip`

Examples
--------
Expand Down Expand Up @@ -179,6 +181,47 @@ def length(self):
return np.linalg.norm(self.vector)


class StealthTip(ArrowTip):
r"""'Stealth' fighter / kite arrow shape.

Naming is inspired by the corresponding
`TikZ arrow shape <https://tikz.dev/tikz-arrows#sec-16.3>`__.
"""

def __init__(
self,
fill_opacity=1,
stroke_width=3,
length=DEFAULT_ARROW_TIP_LENGTH / 2,
start_angle=PI,
**kwargs,
):
self.start_angle = start_angle
VMobject.__init__(
self, fill_opacity=fill_opacity, stroke_width=stroke_width, **kwargs
)
self.set_points_as_corners(
[
[2, 0, 0], # tip
[-1.2, 1.6, 0],
[0, 0, 0], # base
[-1.2, -1.6, 0],
[2, 0, 0], # close path, back to tip
]
)
self.scale(length / self.length)

@property
def length(self):
"""The length of the arrow tip.

In this case, the length is computed as the height of
the triangle encompassing the stealth tip (otherwise,
the tip is scaled too large).
"""
return np.linalg.norm(self.vector) * 1.6


class ArrowTriangleTip(ArrowTip, Triangle):
r"""Triangular arrow tip."""

Expand Down
11 changes: 11 additions & 0 deletions manim/mobject/graphing/coordinate_systems.py
Expand Up @@ -1783,6 +1783,17 @@ def construct(self):
# x_min must be > 0 because log is undefined at 0.
graph = ax.plot(lambda x: x ** 2, x_range=[0.001, 10], use_smoothing=False)
self.add(ax, graph)

Styling arguments can be passed to the underlying :class:`.NumberLine`
mobjects that represent the axes:

.. manim:: AxesWithDifferentTips
:save_last_frame:

class AxesWithDifferentTips(Scene):
def construct(self):
ax = Axes(axis_config={'tip_shape': StealthTip})
self.add(ax)
"""

def __init__(
Expand Down
17 changes: 15 additions & 2 deletions manim/mobject/graphing/number_line.py
Expand Up @@ -4,7 +4,11 @@

__all__ = ["NumberLine", "UnitInterval"]

from typing import Callable, Iterable, Sequence

from typing import TYPE_CHECKING, Callable, Iterable, Sequence

if TYPE_CHECKING:
from manim.mobject.geometry.tips import ArrowTip

import numpy as np

Expand Down Expand Up @@ -49,6 +53,10 @@ class NumberLine(Line):
The width of the tip.
tip_height
The height of the tip.
tip_shape
The mobject class used to construct the tip, or ``None`` (the
default) for the default arrow tip. Passed classes have to inherit
from :class:`.ArrowTip`.
include_numbers
Whether to add numbers to the tick marks. The number of decimal places is determined
by the step size, this default can be overridden by ``decimal_number_config``.
Expand Down Expand Up @@ -140,6 +148,7 @@ def __init__(
include_tip: bool = False,
tip_width: float = DEFAULT_ARROW_TIP_LENGTH,
tip_height: float = DEFAULT_ARROW_TIP_LENGTH,
tip_shape: type[ArrowTip] | None = None,
behackl marked this conversation as resolved.
Show resolved Hide resolved
# numbers/labels
include_numbers: bool = False,
font_size: float = 36,
Expand Down Expand Up @@ -217,7 +226,11 @@ def __init__(
self.center()

if self.include_tip:
self.add_tip(tip_length=self.tip_height, tip_width=self.tip_width)
self.add_tip(
tip_length=self.tip_height,
tip_width=self.tip_width,
tip_shape=tip_shape,
)
self.tip.set_stroke(self.stroke_color, self.stroke_width)

if self.include_ticks:
Expand Down
Binary file modified tests/test_graphical_units/control_data/plot/axes.npz
Binary file not shown.
1 change: 1 addition & 0 deletions tests/test_graphical_units/test_axes.py
Expand Up @@ -14,6 +14,7 @@ def test_axes(scene):
x_length=6,
y_length=6,
color=WHITE,
y_axis_config={"tip_shape": StealthTip},
MrDiver marked this conversation as resolved.
Show resolved Hide resolved
)
labels = graph.get_axis_labels()
scene.add(graph, labels)
Expand Down