Skip to content

Commit a6651be

Browse files
New tip shape :class:.StealthTip, allow specifying tip shape of :class:.NumberLine (#3201)
* added new tip class: StealthTip * let NumberLine propagate tip_shape properly * documentation, tests * black * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed type hint, added some more documentation. * black * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove unused import --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent f247408 commit a6651be

File tree

5 files changed

+70
-2
lines changed

5 files changed

+70
-2
lines changed

manim/mobject/geometry/tips.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"ArrowSquareFilledTip",
1111
"ArrowTriangleTip",
1212
"ArrowTriangleFilledTip",
13+
"StealthTip",
1314
]
1415

1516
import numpy as np
@@ -32,6 +33,7 @@ class ArrowTip(VMobject, metaclass=ConvertToOpenGL):
3233
:class:`ArrowCircleFilledTip`
3334
:class:`ArrowSquareTip`
3435
:class:`ArrowSquareFilledTip`
36+
:class:`StealthTip`
3537
3638
Examples
3739
--------
@@ -179,6 +181,47 @@ def length(self):
179181
return np.linalg.norm(self.vector)
180182

181183

184+
class StealthTip(ArrowTip):
185+
r"""'Stealth' fighter / kite arrow shape.
186+
187+
Naming is inspired by the corresponding
188+
`TikZ arrow shape <https://tikz.dev/tikz-arrows#sec-16.3>`__.
189+
"""
190+
191+
def __init__(
192+
self,
193+
fill_opacity=1,
194+
stroke_width=3,
195+
length=DEFAULT_ARROW_TIP_LENGTH / 2,
196+
start_angle=PI,
197+
**kwargs,
198+
):
199+
self.start_angle = start_angle
200+
VMobject.__init__(
201+
self, fill_opacity=fill_opacity, stroke_width=stroke_width, **kwargs
202+
)
203+
self.set_points_as_corners(
204+
[
205+
[2, 0, 0], # tip
206+
[-1.2, 1.6, 0],
207+
[0, 0, 0], # base
208+
[-1.2, -1.6, 0],
209+
[2, 0, 0], # close path, back to tip
210+
]
211+
)
212+
self.scale(length / self.length)
213+
214+
@property
215+
def length(self):
216+
"""The length of the arrow tip.
217+
218+
In this case, the length is computed as the height of
219+
the triangle encompassing the stealth tip (otherwise,
220+
the tip is scaled too large).
221+
"""
222+
return np.linalg.norm(self.vector) * 1.6
223+
224+
182225
class ArrowTriangleTip(ArrowTip, Triangle):
183226
r"""Triangular arrow tip."""
184227

manim/mobject/graphing/coordinate_systems.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,6 +1783,17 @@ def construct(self):
17831783
# x_min must be > 0 because log is undefined at 0.
17841784
graph = ax.plot(lambda x: x ** 2, x_range=[0.001, 10], use_smoothing=False)
17851785
self.add(ax, graph)
1786+
1787+
Styling arguments can be passed to the underlying :class:`.NumberLine`
1788+
mobjects that represent the axes:
1789+
1790+
.. manim:: AxesWithDifferentTips
1791+
:save_last_frame:
1792+
1793+
class AxesWithDifferentTips(Scene):
1794+
def construct(self):
1795+
ax = Axes(axis_config={'tip_shape': StealthTip})
1796+
self.add(ax)
17861797
"""
17871798

17881799
def __init__(

manim/mobject/graphing/number_line.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
__all__ = ["NumberLine", "UnitInterval"]
66

7-
from typing import Callable, Iterable, Sequence
7+
8+
from typing import TYPE_CHECKING, Callable, Iterable, Sequence
9+
10+
if TYPE_CHECKING:
11+
from manim.mobject.geometry.tips import ArrowTip
812

913
import numpy as np
1014

@@ -49,6 +53,10 @@ class NumberLine(Line):
4953
The width of the tip.
5054
tip_height
5155
The height of the tip.
56+
tip_shape
57+
The mobject class used to construct the tip, or ``None`` (the
58+
default) for the default arrow tip. Passed classes have to inherit
59+
from :class:`.ArrowTip`.
5260
include_numbers
5361
Whether to add numbers to the tick marks. The number of decimal places is determined
5462
by the step size, this default can be overridden by ``decimal_number_config``.
@@ -140,6 +148,7 @@ def __init__(
140148
include_tip: bool = False,
141149
tip_width: float = DEFAULT_ARROW_TIP_LENGTH,
142150
tip_height: float = DEFAULT_ARROW_TIP_LENGTH,
151+
tip_shape: type[ArrowTip] | None = None,
143152
# numbers/labels
144153
include_numbers: bool = False,
145154
font_size: float = 36,
@@ -217,7 +226,11 @@ def __init__(
217226
self.center()
218227

219228
if self.include_tip:
220-
self.add_tip(tip_length=self.tip_height, tip_width=self.tip_width)
229+
self.add_tip(
230+
tip_length=self.tip_height,
231+
tip_width=self.tip_width,
232+
tip_shape=tip_shape,
233+
)
221234
self.tip.set_stroke(self.stroke_color, self.stroke_width)
222235

223236
if self.include_ticks:
211 Bytes
Binary file not shown.

tests/test_graphical_units/test_axes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ def test_axes(scene):
1414
x_length=6,
1515
y_length=6,
1616
color=WHITE,
17+
y_axis_config={"tip_shape": StealthTip},
1718
)
1819
labels = graph.get_axis_labels()
1920
scene.add(graph, labels)

0 commit comments

Comments
 (0)