passagemath-plot 10.6.31rc3__cp314-cp314-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-plot might be problematic. Click here for more details.

Files changed (82) hide show
  1. passagemath_plot-10.6.31rc3.dist-info/METADATA +172 -0
  2. passagemath_plot-10.6.31rc3.dist-info/RECORD +82 -0
  3. passagemath_plot-10.6.31rc3.dist-info/WHEEL +6 -0
  4. passagemath_plot-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_plot.dylibs/libgfortran.5.dylib +0 -0
  6. passagemath_plot.dylibs/libgsl.28.dylib +0 -0
  7. passagemath_plot.dylibs/libopenblasp-r0.3.29.dylib +0 -0
  8. passagemath_plot.dylibs/libquadmath.0.dylib +0 -0
  9. sage/all__sagemath_plot.py +15 -0
  10. sage/ext_data/threejs/animation.css +195 -0
  11. sage/ext_data/threejs/animation.html +85 -0
  12. sage/ext_data/threejs/animation.js +273 -0
  13. sage/ext_data/threejs/fat_lines.js +48 -0
  14. sage/ext_data/threejs/threejs-version.txt +1 -0
  15. sage/ext_data/threejs/threejs_template.html +597 -0
  16. sage/interfaces/all__sagemath_plot.py +1 -0
  17. sage/interfaces/gnuplot.py +196 -0
  18. sage/interfaces/jmoldata.py +208 -0
  19. sage/interfaces/povray.py +56 -0
  20. sage/plot/all.py +42 -0
  21. sage/plot/animate.py +1796 -0
  22. sage/plot/arc.py +504 -0
  23. sage/plot/arrow.py +671 -0
  24. sage/plot/bar_chart.py +205 -0
  25. sage/plot/bezier_path.py +400 -0
  26. sage/plot/circle.py +435 -0
  27. sage/plot/colors.py +1606 -0
  28. sage/plot/complex_plot.cpython-314-darwin.so +0 -0
  29. sage/plot/complex_plot.pyx +1446 -0
  30. sage/plot/contour_plot.py +1792 -0
  31. sage/plot/density_plot.py +318 -0
  32. sage/plot/disk.py +373 -0
  33. sage/plot/ellipse.py +375 -0
  34. sage/plot/graphics.py +3580 -0
  35. sage/plot/histogram.py +354 -0
  36. sage/plot/hyperbolic_arc.py +404 -0
  37. sage/plot/hyperbolic_polygon.py +416 -0
  38. sage/plot/hyperbolic_regular_polygon.py +296 -0
  39. sage/plot/line.py +626 -0
  40. sage/plot/matrix_plot.py +629 -0
  41. sage/plot/misc.py +509 -0
  42. sage/plot/multigraphics.py +1294 -0
  43. sage/plot/plot.py +4183 -0
  44. sage/plot/plot3d/all.py +23 -0
  45. sage/plot/plot3d/base.cpython-314-darwin.so +0 -0
  46. sage/plot/plot3d/base.pxd +12 -0
  47. sage/plot/plot3d/base.pyx +3378 -0
  48. sage/plot/plot3d/implicit_plot3d.py +659 -0
  49. sage/plot/plot3d/implicit_surface.cpython-314-darwin.so +0 -0
  50. sage/plot/plot3d/implicit_surface.pyx +1453 -0
  51. sage/plot/plot3d/index_face_set.cpython-314-darwin.so +0 -0
  52. sage/plot/plot3d/index_face_set.pxd +32 -0
  53. sage/plot/plot3d/index_face_set.pyx +1873 -0
  54. sage/plot/plot3d/introduction.py +131 -0
  55. sage/plot/plot3d/list_plot3d.py +649 -0
  56. sage/plot/plot3d/parametric_plot3d.py +1130 -0
  57. sage/plot/plot3d/parametric_surface.cpython-314-darwin.so +0 -0
  58. sage/plot/plot3d/parametric_surface.pxd +12 -0
  59. sage/plot/plot3d/parametric_surface.pyx +893 -0
  60. sage/plot/plot3d/platonic.py +601 -0
  61. sage/plot/plot3d/plot3d.py +1442 -0
  62. sage/plot/plot3d/plot_field3d.py +162 -0
  63. sage/plot/plot3d/point_c.pxi +148 -0
  64. sage/plot/plot3d/revolution_plot3d.py +309 -0
  65. sage/plot/plot3d/shapes.cpython-314-darwin.so +0 -0
  66. sage/plot/plot3d/shapes.pxd +22 -0
  67. sage/plot/plot3d/shapes.pyx +1382 -0
  68. sage/plot/plot3d/shapes2.py +1512 -0
  69. sage/plot/plot3d/tachyon.py +1779 -0
  70. sage/plot/plot3d/texture.py +453 -0
  71. sage/plot/plot3d/transform.cpython-314-darwin.so +0 -0
  72. sage/plot/plot3d/transform.pxd +21 -0
  73. sage/plot/plot3d/transform.pyx +268 -0
  74. sage/plot/plot3d/tri_plot.py +589 -0
  75. sage/plot/plot_field.py +362 -0
  76. sage/plot/point.py +624 -0
  77. sage/plot/polygon.py +562 -0
  78. sage/plot/primitive.py +249 -0
  79. sage/plot/scatter_plot.py +199 -0
  80. sage/plot/step.py +85 -0
  81. sage/plot/streamline_plot.py +328 -0
  82. sage/plot/text.py +432 -0
sage/plot/arrow.py ADDED
@@ -0,0 +1,671 @@
1
+ # sage_setup: distribution = sagemath-plot
2
+ """
3
+ Arrows
4
+ """
5
+ # ***************************************************************************
6
+ # Copyright (C) 2006 Alex Clemesha <clemesha@gmail.com>,
7
+ # William Stein <wstein@gmail.com>,
8
+ # 2008 Mike Hansen <mhansen@gmail.com>,
9
+ # 2009 Emily Kirkman
10
+ #
11
+ # Distributed under the terms of the GNU General Public License (GPL)
12
+ #
13
+ # This code is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ # General Public License for more details.
17
+ #
18
+ # The full text of the GPL is available at:
19
+ #
20
+ # https://www.gnu.org/licenses/
21
+ # ***************************************************************************
22
+ from sage.plot.primitive import GraphicPrimitive
23
+ from sage.misc.decorators import options, rename_keyword
24
+ from sage.plot.colors import to_mpl_color
25
+
26
+
27
+ class CurveArrow(GraphicPrimitive):
28
+ def __init__(self, path, options):
29
+ """
30
+ Return an arrow graphics primitive along the provided path (bezier curve).
31
+
32
+ EXAMPLES::
33
+
34
+ sage: from sage.plot.arrow import CurveArrow
35
+ sage: b = CurveArrow(path=[[(0,0),(.5,.5),(1,0)],[(.5,1),(0,0)]],
36
+ ....: options={})
37
+ sage: b
38
+ CurveArrow from (0, 0) to (0, 0)
39
+ """
40
+ import numpy as np
41
+ self.path = path
42
+ codes = [1] + (len(self.path[0])-1)*[len(self.path[0])]
43
+ vertices = self.path[0]
44
+ for curve in self.path[1:]:
45
+ vertices += curve
46
+ codes += (len(curve))*[len(curve)+1]
47
+ self.codes = codes
48
+ self.vertices = np.array(vertices, float)
49
+ GraphicPrimitive.__init__(self, options)
50
+
51
+ def get_minmax_data(self):
52
+ """
53
+ Return a dictionary with the bounding box data.
54
+
55
+ EXAMPLES::
56
+
57
+ sage: import numpy # to ensure numpy 2.0 compatibility
58
+ sage: if int(numpy.version.short_version[0]) > 1:
59
+ ....: _ = numpy.set_printoptions(legacy="1.25")
60
+ sage: from sage.plot.arrow import CurveArrow
61
+ sage: b = CurveArrow(path=[[(0,0),(.5,.5),(1,0)],[(.5,1),(0,0)]],
62
+ ....: options={})
63
+ sage: d = b.get_minmax_data()
64
+ sage: d['xmin']
65
+ 0.0
66
+ sage: d['xmax']
67
+ 1.0
68
+ """
69
+ return {'xmin': self.vertices[:,0].min(),
70
+ 'xmax': self.vertices[:,0].max(),
71
+ 'ymin': self.vertices[:,1].min(),
72
+ 'ymax': self.vertices[:,1].max()}
73
+
74
+ def _allowed_options(self):
75
+ """
76
+ Return the dictionary of allowed options for the curve arrow graphics
77
+ primitive.
78
+
79
+ EXAMPLES::
80
+
81
+ sage: from sage.plot.arrow import CurveArrow
82
+ sage: list(sorted(CurveArrow(path=[[(0,0),(2,3)]],options={})._allowed_options().items()))
83
+ [('arrowsize', 'The size of the arrowhead'),
84
+ ('arrowstyle', 'todo'),
85
+ ('head', '2-d only: Which end of the path to draw the head (one of 0 (start), 1 (end) or 2 (both)'),
86
+ ('hue', 'The color given as a hue.'),
87
+ ('legend_color', 'The color of the legend text.'),
88
+ ('legend_label', 'The label for this item in the legend.'),
89
+ ('linestyle', "2d only: The style of the line, which is one of
90
+ 'dashed', 'dotted', 'solid', 'dashdot', or '--', ':', '-', '-.',
91
+ respectively."),
92
+ ('rgbcolor', 'The color as an RGB tuple.'),
93
+ ('thickness', 'The thickness of the arrow.'),
94
+ ('width', 'The width of the shaft of the arrow, in points.'),
95
+ ('zorder', '2-d only: The layer level in which to draw')]
96
+ """
97
+ return {'width': 'The width of the shaft of the arrow, in points.',
98
+ 'rgbcolor': 'The color as an RGB tuple.',
99
+ 'hue': 'The color given as a hue.',
100
+ 'legend_label': 'The label for this item in the legend.',
101
+ 'legend_color': 'The color of the legend text.',
102
+ 'arrowstyle': 'todo',
103
+ 'arrowsize': 'The size of the arrowhead',
104
+ 'thickness': 'The thickness of the arrow.',
105
+ 'zorder': '2-d only: The layer level in which to draw',
106
+ 'head': '2-d only: Which end of the path to draw the head (one of 0 (start), 1 (end) or 2 (both)',
107
+ 'linestyle': "2d only: The style of the line, which is one of "
108
+ "'dashed', 'dotted', 'solid', 'dashdot', or '--', ':', '-', '-.', "
109
+ "respectively."}
110
+
111
+ def _repr_(self):
112
+ """
113
+ Text representation of an arrow graphics primitive.
114
+
115
+ EXAMPLES::
116
+
117
+ sage: from sage.plot.arrow import CurveArrow
118
+ sage: CurveArrow(path=[[(0,0),(1,4),(2,3)]],options={})._repr_()
119
+ 'CurveArrow from (0, 0) to (2, 3)'
120
+ """
121
+ return f"CurveArrow from {self.path[0][0]} to {self.path[-1][-1]}"
122
+
123
+ def _render_on_subplot(self, subplot):
124
+ """
125
+ Render this arrow in a subplot.
126
+
127
+ This is the key function that defines how this arrow graphics
128
+ primitive is rendered in matplotlib's library.
129
+
130
+ EXAMPLES:
131
+
132
+ This function implicitly ends up rendering this arrow on a matplotlib
133
+ subplot::
134
+
135
+ sage: arrow(path=[[(0,1), (2,-1), (4,5)]])
136
+ Graphics object consisting of 1 graphics primitive
137
+ """
138
+ from sage.plot.misc import get_matplotlib_linestyle
139
+
140
+ options = self.options()
141
+ width = float(options['width'])
142
+ head = options.pop('head')
143
+ if head == 0:
144
+ style = '<|-'
145
+ elif head == 1:
146
+ style = '-|>'
147
+ elif head == 2:
148
+ style = '<|-|>'
149
+ else:
150
+ raise KeyError('head parameter must be one of 0 (start), 1 (end) or 2 (both)')
151
+ arrowsize = float(options.get('arrowsize', 5))
152
+ head_width = arrowsize
153
+ head_length = arrowsize * 2.0
154
+ color = to_mpl_color(options['rgbcolor'])
155
+ from matplotlib.patches import FancyArrowPatch
156
+ from matplotlib.path import Path
157
+ bpath = Path(self.vertices, self.codes)
158
+ p = FancyArrowPatch(path=bpath,
159
+ lw=width, arrowstyle='{},head_width={},head_length={}'.format(style, head_width, head_length),
160
+ fc=color, ec=color,
161
+ linestyle=get_matplotlib_linestyle(options['linestyle'], return_type='long'))
162
+ p.set_zorder(options['zorder'])
163
+ p.set_label(options['legend_label'])
164
+ subplot.add_patch(p)
165
+ return p
166
+
167
+
168
+ class Arrow(GraphicPrimitive):
169
+ """
170
+ Primitive class that initializes the (line) arrow graphics type.
171
+
172
+ EXAMPLES:
173
+
174
+ We create an arrow graphics object, then take the 0th entry
175
+ in it to get the actual Arrow graphics primitive::
176
+
177
+ sage: P = arrow((0,1), (2,3))[0]
178
+ sage: type(P)
179
+ <class 'sage.plot.arrow.Arrow'>
180
+ sage: P
181
+ Arrow from (0.0,1.0) to (2.0,3.0)
182
+ """
183
+ def __init__(self, xtail, ytail, xhead, yhead, options):
184
+ """
185
+ Create an arrow graphics primitive.
186
+
187
+ EXAMPLES::
188
+
189
+ sage: from sage.plot.arrow import Arrow
190
+ sage: Arrow(0,0,2,3,{})
191
+ Arrow from (0.0,0.0) to (2.0,3.0)
192
+ """
193
+ self.xtail = float(xtail)
194
+ self.xhead = float(xhead)
195
+ self.ytail = float(ytail)
196
+ self.yhead = float(yhead)
197
+ GraphicPrimitive.__init__(self, options)
198
+
199
+ def get_minmax_data(self):
200
+ """
201
+ Return a bounding box for this arrow.
202
+
203
+ EXAMPLES::
204
+
205
+ sage: d = arrow((1,1), (5,5)).get_minmax_data()
206
+ sage: d['xmin']
207
+ 1.0
208
+ sage: d['xmax']
209
+ 5.0
210
+ """
211
+ return {'xmin': min(self.xtail, self.xhead),
212
+ 'xmax': max(self.xtail, self.xhead),
213
+ 'ymin': min(self.ytail, self.yhead),
214
+ 'ymax': max(self.ytail, self.yhead)}
215
+
216
+ def _allowed_options(self):
217
+ """
218
+ Return the dictionary of allowed options for the line arrow graphics
219
+ primitive.
220
+
221
+ EXAMPLES::
222
+
223
+ sage: from sage.plot.arrow import Arrow
224
+ sage: list(sorted(Arrow(0,0,2,3,{})._allowed_options().items()))
225
+ [('arrowshorten', 'The length in points to shorten the arrow.'),
226
+ ('arrowsize', 'The size of the arrowhead'),
227
+ ('head',
228
+ '2-d only: Which end of the path to draw the head (one of 0 (start), 1 (end) or 2 (both)'),
229
+ ('hue', 'The color given as a hue.'),
230
+ ('legend_color', 'The color of the legend text.'),
231
+ ('legend_label', 'The label for this item in the legend.'),
232
+ ('linestyle',
233
+ "2d only: The style of the line, which is one of 'dashed',
234
+ 'dotted', 'solid', 'dashdot', or '--', ':', '-', '-.',
235
+ respectively."),
236
+ ('rgbcolor', 'The color as an RGB tuple.'),
237
+ ('thickness', 'The thickness of the arrow.'),
238
+ ('width', 'The width of the shaft of the arrow, in points.'),
239
+ ('zorder', '2-d only: The layer level in which to draw')]
240
+ """
241
+ return {'width': 'The width of the shaft of the arrow, in points.',
242
+ 'rgbcolor': 'The color as an RGB tuple.',
243
+ 'hue': 'The color given as a hue.',
244
+ 'arrowshorten': 'The length in points to shorten the arrow.',
245
+ 'arrowsize': 'The size of the arrowhead',
246
+ 'thickness': 'The thickness of the arrow.',
247
+ 'legend_label': 'The label for this item in the legend.',
248
+ 'legend_color': 'The color of the legend text.',
249
+ 'zorder': '2-d only: The layer level in which to draw',
250
+ 'head': '2-d only: Which end of the path to draw the head (one of 0 (start), 1 (end) or 2 (both)',
251
+ 'linestyle': "2d only: The style of the line, which is one of "
252
+ "'dashed', 'dotted', 'solid', 'dashdot', or '--', ':', '-', '-.', "
253
+ "respectively."}
254
+
255
+ def _plot3d_options(self, options=None):
256
+ """
257
+ Translate 2D plot options into 3D plot options.
258
+
259
+ EXAMPLES::
260
+
261
+ sage: P = arrow((0,1), (2,3), width=5)
262
+ sage: p=P[0]; p
263
+ Arrow from (0.0,1.0) to (2.0,3.0)
264
+ sage: q=p.plot3d()
265
+ sage: q.thickness
266
+ 5
267
+ """
268
+ if options is None:
269
+ options = self.options()
270
+ options = dict(self.options())
271
+ options_3d = {}
272
+ if 'width' in options:
273
+ options_3d['thickness'] = options['width']
274
+ del options['width']
275
+ # ignore zorder and head in 3d plotting
276
+ if 'zorder' in options:
277
+ del options['zorder']
278
+ if 'head' in options:
279
+ del options['head']
280
+ if 'linestyle' in options:
281
+ del options['linestyle']
282
+ options_3d.update(GraphicPrimitive._plot3d_options(self, options))
283
+ return options_3d
284
+
285
+ def plot3d(self, ztail=0, zhead=0, **kwds):
286
+ """
287
+ Take 2D plot and places it in 3D.
288
+
289
+ EXAMPLES::
290
+
291
+ sage: A = arrow((0,0),(1,1))[0].plot3d()
292
+ sage: A.jmol_repr(A.testing_render_params())[0]
293
+ 'draw line_1 diameter 2 arrow {0.0 0.0 0.0} {1.0 1.0 0.0} '
294
+
295
+ Note that we had to index the arrow to get the Arrow graphics
296
+ primitive. We can also change the height via the :meth:`Graphics.plot3d`
297
+ method, but only as a whole::
298
+
299
+ sage: A = arrow((0,0),(1,1)).plot3d(3)
300
+ sage: A.jmol_repr(A.testing_render_params())[0][0]
301
+ 'draw line_1 diameter 2 arrow {0.0 0.0 3.0} {1.0 1.0 3.0} '
302
+
303
+ Optional arguments place both the head and tail outside the
304
+ `xy`-plane, but at different heights. This must be done on
305
+ the graphics primitive obtained by indexing::
306
+
307
+ sage: A=arrow((0,0),(1,1))[0].plot3d(3,4)
308
+ sage: A.jmol_repr(A.testing_render_params())[0]
309
+ 'draw line_1 diameter 2 arrow {0.0 0.0 3.0} {1.0 1.0 4.0} '
310
+ """
311
+ from sage.plot.plot3d.shapes2 import line3d
312
+ options = self._plot3d_options()
313
+ options.update(kwds)
314
+ return line3d([(self.xtail, self.ytail, ztail), (self.xhead, self.yhead, zhead)], arrow_head=True, **options)
315
+
316
+ def _repr_(self):
317
+ """
318
+ Text representation of an arrow graphics primitive.
319
+
320
+ EXAMPLES::
321
+
322
+ sage: from sage.plot.arrow import Arrow
323
+ sage: Arrow(0,0,2,3,{})._repr_()
324
+ 'Arrow from (0.0,0.0) to (2.0,3.0)'
325
+ """
326
+ return f"Arrow from ({self.xtail},{self.ytail}) to ({self.xhead},{self.yhead})"
327
+
328
+ def _render_on_subplot(self, subplot):
329
+ r"""
330
+ Render this arrow in a subplot. This is the key function that
331
+ defines how this arrow graphics primitive is rendered in
332
+ matplotlib's library.
333
+
334
+ EXAMPLES:
335
+
336
+ This function implicitly ends up rendering this arrow on
337
+ a matplotlib subplot::
338
+
339
+ sage: arrow((0,1), (2,-1))
340
+ Graphics object consisting of 1 graphics primitive
341
+
342
+ TESTS:
343
+
344
+ The length of the ends (shrinkA and shrinkB) should not depend
345
+ on the width of the arrow, because Matplotlib already takes
346
+ this into account. See :issue:`12836`::
347
+
348
+ sage: fig = Graphics().matplotlib()
349
+ sage: sp = fig.add_subplot(1,1,1, label='axis1')
350
+ sage: a = arrow((0,0), (1,1))
351
+ sage: b = arrow((0,0), (1,1), width=20)
352
+ sage: p1 = a[0]._render_on_subplot(sp)
353
+ sage: p2 = b[0]._render_on_subplot(sp)
354
+ sage: p1.shrinkA == p2.shrinkA
355
+ True
356
+ sage: p1.shrinkB == p2.shrinkB
357
+ True
358
+
359
+ Dashed arrows should have solid arrowheads, :issue:`12852`. We tried to
360
+ make up a test for this, which turned out to be fragile and hence was
361
+ removed. In general, robust testing of graphics seems basically need a
362
+ human eye or AI.
363
+ """
364
+ from sage.plot.misc import get_matplotlib_linestyle
365
+
366
+ options = self.options()
367
+ head = options.pop('head')
368
+ if head == 0:
369
+ style = '<|-'
370
+ elif head == 1:
371
+ style = '-|>'
372
+ elif head == 2:
373
+ style = '<|-|>'
374
+ else:
375
+ raise KeyError('head parameter must be one of 0 (start), 1 (end) or 2 (both)')
376
+ width = float(options['width'])
377
+ arrowshorten_end = float(options.get('arrowshorten', 0)) / 2.0
378
+ arrowsize = float(options.get('arrowsize', 5))
379
+ head_width = arrowsize
380
+ head_length = arrowsize * 2.0
381
+ color = to_mpl_color(options['rgbcolor'])
382
+ from matplotlib.patches import FancyArrowPatch
383
+ p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead),
384
+ lw=width,
385
+ arrowstyle='{},head_width={},head_length={}'.format(style, head_width, head_length),
386
+ shrinkA=arrowshorten_end, shrinkB=arrowshorten_end,
387
+ fc=color, ec=color,
388
+ linestyle=get_matplotlib_linestyle(options['linestyle'], return_type='long'))
389
+ p.set_zorder(options['zorder'])
390
+ p.set_label(options['legend_label'])
391
+
392
+ if options['linestyle'] != 'solid':
393
+ # The next few lines work around a design issue in matplotlib.
394
+ # Currently, the specified linestyle is used to draw both the path
395
+ # and the arrowhead. If linestyle is 'dashed', this looks really
396
+ # odd. This code is from Jae-Joon Lee in response to a post to the
397
+ # matplotlib mailing list.
398
+ # See http://sourceforge.net/mailarchive/forum.php?thread_name=CAG%3DuJ%2Bnw2dE05P9TOXTz_zp-mGP3cY801vMH7yt6vgP9_WzU8w%40mail.gmail.com&forum_name=matplotlib-users
399
+
400
+ import matplotlib.patheffects as pe
401
+
402
+ class CheckNthSubPath:
403
+ def __init__(self, patch, n):
404
+ """
405
+ Creates a callable object that returns ``True`` if the
406
+ provided path is the n-th path from the patch.
407
+ """
408
+ self._patch = patch
409
+ self._n = n
410
+
411
+ def get_paths(self, renderer):
412
+ # get_path_in_displaycoord was made private in matplotlib 3.5
413
+ try:
414
+ paths, fillables = self._patch._get_path_in_displaycoord()
415
+ except AttributeError:
416
+ paths, fillables = self._patch.get_path_in_displaycoord()
417
+ return paths
418
+
419
+ def __call__(self, renderer, gc, tpath, affine, rgbFace):
420
+ paths = self.get_paths(renderer)
421
+ if self._n >= len(paths):
422
+ return False
423
+ path = paths[self._n]
424
+ vert1, code1 = path.vertices, path.codes
425
+ import numpy as np
426
+
427
+ return np.array_equal(vert1, tpath.vertices) and np.array_equal(code1, tpath.codes)
428
+
429
+ class ConditionalStroke(pe.RendererBase):
430
+
431
+ def __init__(self, condition_func, pe_list):
432
+ """
433
+ Path effect that is only applied when the ``condition_func``
434
+ returns ``True``.
435
+ """
436
+ super().__init__()
437
+ self._pe_list = pe_list
438
+ self._condition_func = condition_func
439
+
440
+ def draw_path(self, renderer, gc, tpath, affine, rgbFace):
441
+
442
+ if self._condition_func(renderer, gc, tpath, affine, rgbFace):
443
+ for pe1 in self._pe_list:
444
+ pe1.draw_path(renderer, gc, tpath, affine, rgbFace)
445
+
446
+ pe1 = ConditionalStroke(CheckNthSubPath(p, 0), [pe.Stroke()])
447
+ pe2 = ConditionalStroke(CheckNthSubPath(p, 1), [pe.Stroke(dashes={'dash_offset': 0, 'dash_list': None})])
448
+ p.set_path_effects([pe1, pe2])
449
+
450
+ subplot.add_patch(p)
451
+ return p
452
+
453
+
454
+ def arrow(tailpoint=None, headpoint=None, **kwds):
455
+ """
456
+ Return either a 2-dimensional or 3-dimensional arrow depending
457
+ on value of points.
458
+
459
+ For information regarding additional arguments, see either arrow2d?
460
+ or arrow3d?.
461
+
462
+ EXAMPLES::
463
+
464
+ sage: arrow((0,0), (1,1))
465
+ Graphics object consisting of 1 graphics primitive
466
+
467
+ .. PLOT::
468
+
469
+ sphinx_plot(arrow((0,0), (1,1)))
470
+
471
+ ::
472
+
473
+ sage: arrow((0,0,1), (1,1,1))
474
+ Graphics3d Object
475
+
476
+ .. PLOT::
477
+
478
+ sphinx_plot(arrow((0,0,1), (1,1,1)))
479
+
480
+ TESTS:
481
+
482
+ Check that :issue:`35031` is fixed::
483
+
484
+ sage: arrow((0,0), (0,0), linestyle='dashed')
485
+ Graphics object consisting of 1 graphics primitive
486
+ """
487
+ try:
488
+ return arrow2d(tailpoint, headpoint, **kwds)
489
+ except ValueError:
490
+ from sage.plot.plot3d.shapes import arrow3d
491
+ return arrow3d(tailpoint, headpoint, **kwds)
492
+
493
+
494
+ @rename_keyword(color='rgbcolor')
495
+ @options(width=2, rgbcolor=(0,0,1), zorder=2, head=1, linestyle='solid',
496
+ legend_label=None, legend_color=None)
497
+ def arrow2d(tailpoint=None, headpoint=None, path=None, **options):
498
+ """
499
+ If ``tailpoint`` and ``headpoint`` are provided, returns an arrow from
500
+ (xtail, ytail) to (xhead, yhead). If ``tailpoint`` or ``headpoint`` is None and
501
+ ``path`` is not None, returns an arrow along the path. (See further info on
502
+ paths in :class:`bezier_path`).
503
+
504
+ INPUT:
505
+
506
+ - ``tailpoint`` -- the starting point of the arrow
507
+
508
+ - ``headpoint`` -- where the arrow is pointing to
509
+
510
+ - ``path`` -- the list of points and control points (see bezier_path for
511
+ detail) that the arrow will follow from source to destination
512
+
513
+ - ``head`` -- 0, 1 or 2, whether to draw the head at the start (0), end (1)
514
+ or both (2) of the path (using 0 will swap headpoint and tailpoint).
515
+ This is ignored in 3D plotting.
516
+
517
+ - ``linestyle`` -- (default: ``'solid'``) the style of the line, which is
518
+ one of ``'dashed'``, ``'dotted'``, ``'solid'``, ``'dashdot'``,
519
+ or ``'--'``, ``':'``, ``'-'``, ``'-.'``, respectively
520
+
521
+ - ``width`` -- (default: 2) the width of the arrow shaft, in points
522
+
523
+ - ``color`` -- (default: (0,0,1)) the color of the arrow (as an RGB tuple or
524
+ a string)
525
+
526
+ - ``hue`` -- the color of the arrow (as a number)
527
+
528
+ - ``arrowsize`` -- the size of the arrowhead
529
+
530
+ - ``arrowshorten`` -- the length in points to shorten the arrow (ignored if
531
+ using path parameter)
532
+
533
+ - ``legend_label`` -- the label for this item in the legend
534
+
535
+ - ``legend_color`` -- the color for the legend label
536
+
537
+ - ``zorder`` -- the layer level to draw the arrow-- note that this is
538
+ ignored in 3D plotting
539
+
540
+ EXAMPLES:
541
+
542
+ A straight, blue arrow::
543
+
544
+ sage: arrow2d((1,1), (3,3))
545
+ Graphics object consisting of 1 graphics primitive
546
+
547
+ .. PLOT::
548
+
549
+ sphinx_plot(arrow2d((1,1), (3,3)))
550
+
551
+ Make a red arrow::
552
+
553
+ sage: arrow2d((-1,-1), (2,3), color=(1,0,0))
554
+ Graphics object consisting of 1 graphics primitive
555
+
556
+ .. PLOT::
557
+
558
+ sphinx_plot(arrow2d((-1,-1), (2,3), color=(1,0,0)))
559
+
560
+ ::
561
+
562
+ sage: arrow2d((-1,-1), (2,3), color='red')
563
+ Graphics object consisting of 1 graphics primitive
564
+
565
+ .. PLOT::
566
+
567
+ sphinx_plot(arrow2d((-1,-1), (2,3), color='red'))
568
+
569
+ You can change the width of an arrow::
570
+
571
+ sage: arrow2d((1,1), (3,3), width=5, arrowsize=15)
572
+ Graphics object consisting of 1 graphics primitive
573
+
574
+ .. PLOT::
575
+
576
+ P = arrow2d((1,1), (3,3), width=5, arrowsize=15)
577
+ sphinx_plot(P)
578
+
579
+ Use a dashed line instead of a solid one for the arrow::
580
+
581
+ sage: arrow2d((1,1), (3,3), linestyle='dashed')
582
+ Graphics object consisting of 1 graphics primitive
583
+ sage: arrow2d((1,1), (3,3), linestyle='--')
584
+ Graphics object consisting of 1 graphics primitive
585
+
586
+ .. PLOT::
587
+
588
+ P = arrow2d((1,1), (3,3), linestyle='--')
589
+ sphinx_plot(P)
590
+
591
+ A pretty circle of arrows::
592
+
593
+ sage: sum(arrow2d((0,0), (cos(x),sin(x)), hue=x/(2*pi)) # needs sage.symbolic
594
+ ....: for x in [0..2*pi, step=0.1])
595
+ Graphics object consisting of 63 graphics primitives
596
+
597
+ .. PLOT::
598
+
599
+ P = sum([arrow2d((0,0), (cos(x*0.1),sin(x*0.1)), hue=x/(20*pi)) for x in range(floor(20*pi)+1)])
600
+ sphinx_plot(P)
601
+
602
+ If we want to draw the arrow between objects, for example, the
603
+ boundaries of two lines, we can use the ``arrowshorten`` option
604
+ to make the arrow shorter by a certain number of points::
605
+
606
+ sage: L1 = line([(0,0), (1,0)], thickness=10)
607
+ sage: L2 = line([(0,1), (1,1)], thickness=10)
608
+ sage: A = arrow2d((0.5,0), (0.5,1), arrowshorten=10, rgbcolor=(1,0,0))
609
+ sage: L1 + L2 + A
610
+ Graphics object consisting of 3 graphics primitives
611
+
612
+ .. PLOT::
613
+
614
+ L1 = line([(0,0), (1,0)],thickness=10)
615
+ L2 = line([(0,1), (1,1)], thickness=10)
616
+ A = arrow2d((0.5,0), (0.5,1), arrowshorten=10, rgbcolor=(1,0,0))
617
+ sphinx_plot(L1 + L2 + A)
618
+
619
+ If BOTH ``headpoint`` and ``tailpoint`` are None, then an empty plot is
620
+ returned::
621
+
622
+ sage: arrow2d(headpoint=None, tailpoint=None)
623
+ Graphics object consisting of 0 graphics primitives
624
+
625
+ We can also draw an arrow with a legend::
626
+
627
+ sage: arrow((0,0), (0,2), legend_label='up', legend_color='purple')
628
+ Graphics object consisting of 1 graphics primitive
629
+
630
+ .. PLOT::
631
+
632
+ P = arrow((0,0), (0,2), legend_label='up', legend_color='purple')
633
+ sphinx_plot(P)
634
+
635
+ Extra options will get passed on to :meth:`Graphics.show()`, as long as they are valid::
636
+
637
+ sage: arrow2d((-2,2), (7,1), frame=True)
638
+ Graphics object consisting of 1 graphics primitive
639
+
640
+ .. PLOT::
641
+
642
+ sphinx_plot(arrow2d((-2,2), (7,1), frame=True))
643
+
644
+ ::
645
+
646
+ sage: arrow2d((-2,2), (7,1)).show(frame=True)
647
+
648
+ TESTS:
649
+
650
+ Verify that :issue:`36153` is fixed::
651
+
652
+ sage: A = arrow2d((-1,-1), (2,3), legend_label='test')
653
+ """
654
+ from sage.plot.all import Graphics
655
+ g = Graphics()
656
+ g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
657
+
658
+ if headpoint is not None and tailpoint is not None:
659
+ xtail, ytail = tailpoint
660
+ xhead, yhead = headpoint
661
+ g.add_primitive(Arrow(xtail, ytail, xhead, yhead, options=options))
662
+ elif path is not None:
663
+ g.add_primitive(CurveArrow(path, options=options))
664
+ elif tailpoint is None and headpoint is None:
665
+ return g
666
+ else:
667
+ raise TypeError('arrow requires either both headpoint and tailpoint or a path parameter')
668
+ if options['legend_label']:
669
+ g.legend(True)
670
+ g._legend_colors = [options['legend_color']]
671
+ return g