|
16 | 16 | from .colors import is_color_like, get_named_colors_mapping |
17 | 17 | from .markers import MarkerStyle |
18 | 18 | from .path import Path |
19 | | -from .transforms import ( |
20 | | - Affine2D, Bbox, BboxTransformFrom, BboxTransformTo, TransformedPath) |
| 19 | +from .transforms import Bbox, BboxTransformTo, TransformedPath |
21 | 20 |
|
22 | 21 | # Imported here for backward compatibility, even though they don't |
23 | 22 | # really belong. |
@@ -1412,34 +1411,57 @@ class _AxLine(Line2D): |
1412 | 1411 | transform at draw time. |
1413 | 1412 | """ |
1414 | 1413 |
|
| 1414 | + def __init__(self, xy1, xy2, slope, **kwargs): |
| 1415 | + super().__init__([0, 1], [0, 1], **kwargs) |
| 1416 | + |
| 1417 | + if (xy2 is None and slope is None or |
| 1418 | + xy2 is not None and slope is not None): |
| 1419 | + raise TypeError( |
| 1420 | + "Exactly one of 'xy2' and 'slope' must be given") |
| 1421 | + |
| 1422 | + self._slope = slope |
| 1423 | + self._xy1 = xy1 |
| 1424 | + self._xy2 = xy2 |
| 1425 | + |
1415 | 1426 | def get_transform(self): |
1416 | 1427 | ax = self.axes |
1417 | | - (x1, y1), (x2, y2) = ax.transScale.transform([*zip(*self.get_data())]) |
1418 | | - dx = x2 - x1 |
1419 | | - dy = y2 - y1 |
1420 | | - if np.allclose(x1, x2): |
1421 | | - if np.allclose(y1, y2): |
1422 | | - raise ValueError( |
1423 | | - f"Cannot draw a line through two identical points " |
1424 | | - f"(x={self.get_xdata()}, y={self.get_ydata()})") |
1425 | | - # First send y1 to 0 and y2 to 1. |
1426 | | - return (Affine2D.from_values(1, 0, 0, 1 / dy, 0, -y1 / dy) |
1427 | | - + ax.get_xaxis_transform(which="grid")) |
1428 | | - if np.allclose(y1, y2): |
1429 | | - # First send x1 to 0 and x2 to 1. |
1430 | | - return (Affine2D.from_values(1 / dx, 0, 0, 1, -x1 / dx, 0) |
1431 | | - + ax.get_yaxis_transform(which="grid")) |
| 1428 | + points_transform = self._transform + ax.transData.inverted() |
| 1429 | + |
| 1430 | + if self._xy2 is not None: |
| 1431 | + # two points were given |
| 1432 | + (x1, y1), (x2, y2) = \ |
| 1433 | + points_transform.transform([self._xy1, self._xy2]) |
| 1434 | + dx = x2 - x1 |
| 1435 | + dy = y2 - y1 |
| 1436 | + if np.allclose(x1, x2): |
| 1437 | + if np.allclose(y1, y2): |
| 1438 | + raise ValueError( |
| 1439 | + f"Cannot draw a line through two identical points " |
| 1440 | + f"(x={(x1, x2)}, y={(y1, y2)})") |
| 1441 | + slope = np.inf |
| 1442 | + else: |
| 1443 | + slope = dy / dx |
| 1444 | + else: |
| 1445 | + # one point and a slope were given |
| 1446 | + x1, y1 = points_transform.transform(self._xy1) |
| 1447 | + slope = self._slope |
1432 | 1448 | (vxlo, vylo), (vxhi, vyhi) = ax.transScale.transform(ax.viewLim) |
1433 | 1449 | # General case: find intersections with view limits in either |
1434 | 1450 | # direction, and draw between the middle two points. |
1435 | | - _, start, stop, _ = sorted([ |
1436 | | - (vxlo, y1 + (vxlo - x1) * dy / dx), |
1437 | | - (vxhi, y1 + (vxhi - x1) * dy / dx), |
1438 | | - (x1 + (vylo - y1) * dx / dy, vylo), |
1439 | | - (x1 + (vyhi - y1) * dx / dy, vyhi), |
1440 | | - ]) |
1441 | | - return (BboxTransformFrom(Bbox([*zip(*self.get_data())])) |
1442 | | - + BboxTransformTo(Bbox([start, stop])) |
| 1451 | + if np.isclose(slope, 0): |
| 1452 | + start = vxlo, y1 |
| 1453 | + stop = vxhi, y1 |
| 1454 | + elif np.isinf(slope): |
| 1455 | + start = x1, vylo |
| 1456 | + stop = x1, vyhi |
| 1457 | + else: |
| 1458 | + _, start, stop, _ = sorted([ |
| 1459 | + (vxlo, y1 + (vxlo - x1) * slope), |
| 1460 | + (vxhi, y1 + (vxhi - x1) * slope), |
| 1461 | + (x1 + (vylo - y1) / slope, vylo), |
| 1462 | + (x1 + (vyhi - y1) / slope, vyhi), |
| 1463 | + ]) |
| 1464 | + return (BboxTransformTo(Bbox([start, stop])) |
1443 | 1465 | + ax.transLimits + ax.transAxes) |
1444 | 1466 |
|
1445 | 1467 | def draw(self, renderer): |
|
0 commit comments