8000 implement a function `axline_transaxes` · matplotlib/matplotlib@cf835e3 · GitHub
[go: up one dir, main page]

Skip to content

Commit cf835e3

Browse files
committed
implement a function axline_transaxes
for plotting a line through a point in axes coordinates and with a slope in data coordinates fixes #18625
1 parent 80c40b8 commit cf835e3

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,55 @@ def _to_points(xy1, xy2, slope):
876876
self._request_autoscale_view()
877877
return line
878878

879+
def axline_transaxes(self, xy1, slope, **kwargs):
880+
"""
881+
Add an infinitely long straight line.
882+
883+
The line is defined by one point in axes coordinates *xy1* and a
884+
*slope* in data coordinates.
885+
886+
This should only be used with linear scales; the *slope* has no clear
887+
meaning for all other scales, and thus the behavior is undefined.
888+
889+
Parameters
890+
----------
891+
xy1 : (float, float)
892+
Point for the line to pass through, in axes coordinates.
893+
slope : float
894+
The slope of the line, in data coordinates.
895+
896+
Returns
897+
-------
898+
`.Line2D`
899+
900+
Other Parameters
901+
----------------
902+
**kwargs
903+
Valid kwargs are `.Line2D` properties, with the exception of
904+
'transform':
905+
906+
%(_Line2D_docstr)s
907+
908+
See Also
909+
--------
910+
axhline : for horizontal lines
911+
axvline : for vertical lines
912+
913+
Examples
914+
--------
915+
Draw a thick red line passing through (0, 0)
916+
(the lower left corner of the viewport) with slope 1::
917+
918+
>>> axline_transaxes((0, 0), 1, linewidth=4, color='r')
919+
"""
920+
if "transform" in kwargs:
921+
raise TypeError("'transform' is not allowed as a kwarg; "
922+
"axline_transaxes generates its own transform")
923+
924+
line = mlines._AxLineTransAxes(xy1, slope, **kwargs)
925+
self.add_line(line)
926+
return line
927+
879928
@docstring.dedent_interpd
880929
def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs):
881930
"""

lib/matplotlib/lines.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,34 @@ def draw(self, renderer):
14401440
super().draw(renderer)
14411441

14421442

1443+
class _AxLineTransAxes(_AxLine):
1444+
"""
1445+
A helper class that implements `~.Axes.axline_transaxes`, by recomputing
1446+
the artist transform at draw time.
1447+
"""
1448+
1449+
def __init__(self, xy1, slope, **kwargs):
1450+
super().__init__([0, 1], [0, 1], **kwargs)
1451+
self._slope = slope
1452+
self._xy1 = xy1
1453+
1454+
def get_transform(self):
1455+
ax = self.axes
1456+
(vxlo, vylo), (vxhi, vyhi) = ax.transScale.transform(ax.viewLim)
1457+
x, y = (ax.transAxes + ax.transData.inverted()).transform(self._xy1)
1458+
1459+
# find intersections with view limits in either direction,
1460+
# and draw between the middle two points.
1461+
_, start, stop, _ = sorted([
1462+
(vxlo, y + (vxlo - x) * self._slope),
1463+
(vxhi, y + (vxhi - x) * self._slope),
1464+
(x + (vylo< DD41 /span> - y) / self._slope, vylo),
1465+
(x + (vyhi - y) / self._slope, vyhi),
1466+
])
1467+
return (BboxTransformTo(Bbox([start, stop]))
1468+
+ ax.transLimits + ax.transAxes)
1469+
1470+
14431471
class VertexSelector:
14441472
"""
14451473
Manage the callbacks to maintain a list of selected vertices for

lib/matplotlib/tests/test_axes.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4072,6 +4072,19 @@ def test_axline(fig_test, fig_ref):
40724072
ax.axvline(-0.5, color='C5')
40734073

40744074

4075+
@check_figures_equal()
4076+
def test_axline_transform(fig_test, fig_ref):
4077+
ax = fig_test.subplots()
4078+
ax.set(xlim=(-1, 1), ylim=(-1, 1))
4079+
ax.axline_transaxes((0, 0), slope=1)
4080+
ax.axline_transaxes((1, 0.5), slope=1, color='C1')
4081+
4082+
ax = fig_ref.subplots()
4083+
ax.set(xlim=(-1, 1), ylim=(-1, 1))
4084+
ax.plot([-1, 1], [-1, 1])
4085+
ax.plot([0, 1], [-1, 0], color='C1')
4086+
4087+
40754088
def test_axline_args():
40764089
"""Exactly one of *xy2* and *slope* must be specified."""
40774090
fig, ax = plt.subplots()

0 commit comments

Comments
 (0)
0