|
2 | 2 |
|
3 | 3 | from matplotlib import ticker as mticker |
4 | 4 | from matplotlib.transforms import Bbox, Transform |
5 | | -from .clip_path import clip_line_to_rect |
| 5 | + |
| 6 | + |
| 7 | +def _find_line_box_crossings(xys, bbox): |
| 8 | + """ |
| 9 | + Find the points where a polyline crosses a bbox, and the crossing angles. |
| 10 | +
|
| 11 | + Parameters |
| 12 | + ---------- |
| 13 | + xys : (N, 2) array |
| 14 | + The polyline coordinates. |
| 15 | + bbox : `.Bbox` |
| 16 | + The bounding box. |
| 17 | +
|
| 18 | + Returns |
| 19 | + ------- |
| 20 | + list of ((float, float), float) |
| 21 | + Four separate lists of crossings, for the left, right, bottom, and top |
| 22 | + sides of the bbox, respectively. For each list, the entries are the |
| 23 | + ``((x, y), ccw_angle_in_degrees)`` of the crossing, where an angle of 0 |
| 24 | + means that the polyline is moving to the right at the crossing point. |
| 25 | +
|
| 26 | + The entries are computed by linearly interpolating at each crossing |
| 27 | + between the nearest points on either side of the bbox edges. |
| 28 | + """ |
| 29 | + crossings = [] |
| 30 | + dxys = xys[1:] - xys[:-1] |
| 31 | + for sl in [slice(None), slice(None, None, -1)]: |
| 32 | + us, vs = xys.T[sl] # "this" coord, "other" coord |
| 33 | + dus, dvs = dxys.T[sl] |
| 34 | + umin, vmin = bbox.min[sl] |
| 35 | + umax, vmax = bbox.max[sl] |
| 36 | + for u0, inside in [(umin, us > umin), (umax, us < umax)]: |
| 37 | + crossings.append([]) |
| 38 | + idxs, = (inside[:-1] ^ inside[1:]).nonzero() |
| 39 | + for idx in idxs: |
| 40 | + v = vs[idx] + (u0 - us[idx]) * dvs[idx] / dus[idx] |
| 41 | + if not vmin <= v <= vmax: |
| 42 | + continue |
| 43 | + crossing = (u0, v)[sl] |
| 44 | + theta = np.degrees(np.arctan2(*dxys[idx][::-1])) |
| 45 | + crossings[-1].append((crossing, theta)) |
| 46 | + return crossings |
6 | 47 |
|
7 | 48 |
|
8 | 49 | class ExtremeFinderSimple: |
@@ -161,14 +202,12 @@ def _clip_grid_lines_and_find_ticks(self, lines, values, levs, bb): |
161 | 202 | tck_levels = gi["tick_levels"] |
162 | 203 | tck_locs = gi["tick_locs"] |
163 | 204 | for (lx, ly), v, lev in zip(lines, values, levs): |
164 | | - xy, tcks = clip_line_to_rect(lx, ly, bb) |
165 | | - if not xy: |
166 | | - continue |
| 205 | + tcks = _find_line_box_crossings(np.column_stack([lx, ly]), bb) |
167 | 206 | gi["levels"].append(v) |
168 | | - gi["lines"].append(xy) |
| 207 | + gi["lines"].append([(lx, ly)]) |
169 | 208 |
|
170 | 209 | for tck, direction in zip(tcks, |
171 | | - ["left", "bottom", "right", "top"]): |
| 210 | + ["left", "right", "bottom", "top"]): |
172 | 211 | for t in tck: |
173 | 212 | tck_levels[direction].append(lev) |
174 | 213 | tck_locs[direction].append(t) |
|
0 commit comments