Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1a7b35b

Browse filesBrowse files
committed
refactor Bezier so it doesn't depend on Path
1 parent 757fb24 commit 1a7b35b
Copy full SHA for 1a7b35b

File tree

Expand file treeCollapse file tree

6 files changed

+172
-154
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+172
-154
lines changed

‎doc/api/next_api_changes/deprecations.rst

Copy file name to clipboardExpand all lines: doc/api/next_api_changes/deprecations.rst
+11-11Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,19 +227,9 @@ The following validators, defined in `.rcsetup`, are deprecated:
227227
``validate_axes_titlelocation``, ``validate_toolbar``,
228228
``validate_ps_papersize``, ``validate_legend_loc``,
229229
``validate_bool_maybe_none``, ``validate_hinting``,
230-
``validate_movie_writers``.
230+
``validate_movie_writers``, ``validate_webagg_address``.
231231
To test whether an rcParam value would be acceptable, one can test e.g. ``rc =
232232
RcParams(); rc[k] = v`` raises an exception.
233-
||||||| constructed merge base
234-
``validate_ps_papersize``, ``validate_legend_log``. To test whether an rcParam
235-
value would be acceptable, one can test e.g. ``rc = RcParams(); rc[k] = v``
236-
raises an exception.
237-
=======
238-
``validate_ps_papersize``, ``validate_legend_loc``,
239-
``validate_webagg_address``.
240-
To test whether an rcParam value would be acceptable, one can test e.g. ``rc =
241-
RcParams(); rc[k] = v`` raises an exception.
242-
>>>>>>> Deprecate validate_webagg_address.
243233

244234
Stricter rcParam validation
245235
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -370,3 +360,13 @@ mathtext ``Glue`` helper classes
370360
The ``Fil``, ``Fill``, ``Filll``, ``NegFil``, ``NegFill``, ``NegFilll``, and
371361
``SsGlue`` classes in the :mod:`matplotlib.mathtext` module are deprecated.
372362
As an alternative, directly construct glue instances with ``Glue("fil")``, etc.
363+
364+
Path helpers in :mod:`.bezier`
365+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
366+
- ``bezier.make_path_regular`` is deprecated. Use ``Path.cleaned()`` (or
367+
``Path.cleaned(curves=True)``, etc.) instead (but note that these methods add
368+
a ``STOP`` code at the end of the path).
369+
- ``bezier.concatenate_paths`` is deprecated. Use ``Path.make_compound_path()``
370+
instead.
371+
- ``bezier.split_path_inout`` (use ``Path.split_path_inout`` instead)
372+
- ``bezier.inside_circle()`` (no replacement)

‎doc/api/next_api_changes/removals.rst

Copy file name to clipboardExpand all lines: doc/api/next_api_changes/removals.rst
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Classes and methods
8484

8585
- ``image.BboxImage.interp_at_native`` property (no replacement)
8686
- ``lines.Line2D.verticalOffset`` property (no replacement)
87-
- ``bezier.find_r_to_boundary_of_closedpath()`` (no relacement)
87+
- ``bezier.find_r_to_boundary_of_closedpath()`` (no replacement)
8888

8989
- ``quiver.Quiver.color()`` (use ``Quiver.get_facecolor()`` instead)
9090
- ``quiver.Quiver.keyvec`` property (no replacement)

‎lib/matplotlib/bezier.py

Copy file name to clipboardExpand all lines: lib/matplotlib/bezier.py
+57-111Lines changed: 57 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
import numpy as np
88

99
import matplotlib.cbook as cbook
10-
from matplotlib.path import Path
1110

1211

1312
class NonIntersectingPathException(ValueError):
1413
pass
1514

15+
1616
# some functions
1717

1818

@@ -68,6 +68,54 @@ def get_normal_points(cx, cy, cos_t, sin_t, length):
6868
return x1, y1, x2, y2
6969

7070

71+
# deprecated routines (moved to `.Path`)
72+
73+
74+
@cbook.deprecated("3.3")
75+
def inside_circle(cx, cy, r):
76+
"""
77+
Return a function that checks whether a point is in a circle with center
78+
(*cx*, *cy*) and radius *r*.
79+
80+
The returned function has the signature::
81+
82+
f(xy: Tuple[float, float]) -> bool
83+
"""
84+
r2 = r ** 2
85+
86+
def _f(xy):
87+
x, y = xy
88+
return (x - cx) ** 2 + (y - cy) ** 2 < r2
89+
return _f
90+
91+
92+
@cbook.deprecated("3.3", alternative="Path.make_compound_path()")
93+
def split_path_inout(path, inside, tolerance=0.01, reorder_inout=False):
94+
"""
95+
Divide a path into two segments at the point where ``inside(x, y)``
96+
becomes False.
97+
"""
98+
return path.split_path_inout(inside, tolerance, reorder_inout)
99+
100+
101+
@cbook.deprecated(
102+
"3.3", alternative="Path.cleaned() and remove the final STOP if needed")
103+
def make_path_regular(path):
104+
"""
105+
If the ``codes`` attribute of `.Path` *p* is None, return a copy of *p*
106+
with ``codes`` set to (MOVETO, LINETO, LINETO, ..., LINETO); otherwise
107+
return *p* itself.
108+
"""
109+
return path.make_path_regular()
110+
111+
112+
@cbook.deprecated("3.3", alternative="Path.make_compound_path()")
113+
def concatenate_paths(paths):
114+
"""Concatenate a list of paths into a single path."""
115+
from .path import Path
116+
return Path.make_compound_path(*paths)
117+
118+
71119
# BEZIER routines
72120

73121
# subdividing bezier curve
@@ -177,12 +225,13 @@ class BezierSegment:
177225
"""
178226

179227
def __init__(self, control_points):
180-
n = len(control_points)
181-
self._orders = np.arange(n)
182-
coeff = [math.factorial(n - 1)
183-
// (math.factorial(i) * math.factorial(n - 1 - i))
184-
for i in range(n)]
185-
self._px = np.asarray(control_points).T * coeff
228+
self.cpoints = np.asarray(control_points)
229+
self.n, self.d = self.cpoints.shape
230+
self._orders = np.arange(self.n)
231+
coeff = [math.factorial(self.n - 1)
232+
// (math.factorial(i) * math.factorial(self.n - 1 - i))
233+
for i in range(self.n)]
234+
self._px = self.cpoints.T * coeff
186235

187236
def point_at_t(self, t):
188237
"""Return the point on the Bezier curve for parameter *t*."""
@@ -222,90 +271,9 @@ def split_bezier_intersecting_with_closedpath(
222271
return _left, _right
223272

224273

225-
# matplotlib specific
226-
227-
228-
def split_path_inout(path, inside, tolerance=0.01, reorder_inout=False):
229-
"""
230-
Divide a path into two segments at the point where ``inside(x, y)`` becomes
231-
False.
232-
"""
233-
path_iter = path.iter_segments()
234-
235-
ctl_points, command = next(path_iter)
236-
begin_inside = inside(ctl_points[-2:]) # true if begin point is inside
237-
238-
ctl_points_old = ctl_points
239-
240-
concat = np.concatenate
241-
242-
iold = 0
243-
i = 1
244-
245-
for ctl_points, command in path_iter:
246-
iold = i
247-
i += len(ctl_points) // 2
248-
if inside(ctl_points[-2:]) != begin_inside:
249-
bezier_path = concat([ctl_points_old[-2:], ctl_points])
250-
break
251-
ctl_points_old = ctl_points
252-
else:
253-
raise ValueError("The path does not intersect with the patch")
254-
255-
bp = bezier_path.reshape((-1, 2))
256-
left, right = split_bezier_intersecting_with_closedpath(
257-
bp, inside, tolerance)
258-
if len(left) == 2:
259-
codes_left = [Path.LINETO]
260-
codes_right = [Path.MOVETO, Path.LINETO]
261-
elif len(left) == 3:
262-
codes_left = [Path.CURVE3, Path.CURVE3]
263-
codes_right = [Path.MOVETO, Path.CURVE3, Path.CURVE3]
264-
elif len(left) == 4:
265-
codes_left = [Path.CURVE4, Path.CURVE4, Path.CURVE4]
266-
codes_right = [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4]
267-
else:
268-
raise AssertionError("This should never be reached")
269-
270-
verts_left = left[1:]
271-
verts_right = right[:]
272-
273-
if path.codes is None:
274-
path_in = Path(concat([path.vertices[:i], verts_left]))
275-
path_out = Path(concat([verts_right, path.vertices[i:]]))
276-
277-
else:
278-
path_in = Path(concat([path.vertices[:iold], verts_left]),
279-
concat([path.codes[:iold], codes_left]))
280-
281-
path_out = Path(concat([verts_right, path.vertices[i:]]),
282-
concat([codes_right, path.codes[i:]]))
283-
284-
if reorder_inout and not begin_inside:
285-
path_in, path_out = path_out, path_in
286-
287-
return path_in, path_out
288-
289-
290-
def inside_circle(cx, cy, r):
291-
"""
292-
Return a function that checks whether a point is in a circle with center
293-
(*cx*, *cy*) and radius *r*.
294-
295-
The returned function has the signature::
296-
297-
f(xy: Tuple[float, float]) -> bool
298-
"""
299-
r2 = r ** 2
300-
301-
def _f(xy):
302-
x, y = xy
303-
return (x - cx) ** 2 + (y - cy) ** 2 < r2
304-
return _f
305-
306-
307274
# quadratic Bezier lines
308275

276+
309277
def get_cos_sin(x0, y0, x1, y1):
310278
dx, dy = x1 - x0, y1 - y0
311279
d = (dx * dx + dy * dy) ** .5
@@ -478,25 +446,3 @@ def make_wedged_bezier2(bezier2, width, w1=1., wm=0.5, w2=0.):
478446
c3x_right, c3y_right)
479447

480448
return path_left, path_right
481-
482-
483-
def make_path_regular(p):
484-
"""
485-
If the ``codes`` attribute of `.Path` *p* is None, return a copy of *p*
486-
with ``codes`` set to (MOVETO, LINETO, LINETO, ..., LINETO); otherwise
487-
return *p* itself.
488-
"""
489-
c = p.codes
490-
if c is None:
491-
c = np.full(len(p.vertices), Path.LINETO, dtype=Path.code_type)
492-
c[0] = Path.MOVETO
493-
return Path(p.vertices, c)
494-
else:
495-
return p
496-
497-
498-
def concatenate_paths(paths):
499-
"""Concatenate a list of paths into a single path."""
500-
vertices = np.concatenate([p.vertices for p in paths])
501-
codes = np.concatenate([make_path_regular(p).codes for p in paths])
502-
return Path(vertices, codes)

‎lib/matplotlib/patches.py

Copy file name to clipboardExpand all lines: lib/matplotlib/patches.py
+32-21Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,28 @@
1010
import matplotlib as mpl
1111
from . import artist, cbook, colors, docstring, lines as mlines, transforms
1212
from .bezier import (
13-
NonIntersectingPathException, concatenate_paths, get_cos_sin,
14-
get_intersection, get_parallels, inside_circle, make_path_regular,
15-
make_wedged_bezier2, split_bezier_intersecting_with_closedpath,
16-
split_path_inout)
13+
NonIntersectingPathException, get_cos_sin, get_intersection, get_parallels,
14+
make_wedged_bezier2, split_bezier_intersecting_with_closedpath)
1715
from .path import Path
1816

1917

18+
def _inside_circle(cx, cy, r):
19+
"""
20+
Return a function that checks whether a point is in a circle with center
21+
(*cx*, *cy*) and radius *r*.
22+
23+
The returned function has the signature::
24+
25+
f(xy: Tuple[float, float]) -> bool
26+
"""
27+
r2 = r ** 2
28+
29+
def _f(xy):
30+
x, y = xy
31+
return (x - cx) ** 2 + (y - cy) ** 2 < r2
32+
return _f
33+
34+
2035
@cbook._define_aliases({
2136
"antialiased": ["aa"],
2237
"edgecolor": ["ec"],
@@ -2414,7 +2429,7 @@ def insideA(xy_display):
24142429
return patchA.contains(xy_event)[0]
24152430

24162431
try:
2417-
left, right = split_path_inout(path, insideA)
2432+
left, right = path.split_path_inout(insideA)
24182433
except ValueError:
24192434
right = path
24202435

@@ -2426,7 +2441,7 @@ def insideB(xy_display):
24262441
return patchB.contains(xy_event)[0]
24272442

24282443
try:
2429-
left, right = split_path_inout(path, insideB)
2444+
left, right = path.split_path_inout(insideB)
24302445
except ValueError:
24312446
left = path
24322447

@@ -2439,15 +2454,15 @@ def _shrink(self, path, shrinkA, shrinkB):
24392454
Shrink the path by fixed size (in points) with shrinkA and shrinkB.
24402455
"""
24412456
if shrinkA:
2442-
insideA = inside_circle(*path.vertices[0], shrinkA)
2457+
insideA = _inside_circle(*path.vertices[0], shrinkA)
24432458
try:
2444-
left, path = split_path_inout(path, insideA)
2459+
left, path = path.split_path_inout(insideA)
24452460
except ValueError:
24462461
pass
24472462
if shrinkB:
2448-
insideB = inside_circle(*path.vertices[-1], shrinkB)
2463+
insideB = _inside_circle(*path.vertices[-1], shrinkB)
24492464
try:
2450-
path, right = split_path_inout(path, insideB)
2465+
path, right = path.split_path_inout(insideB)
24512466
except ValueError:
24522467
pass
24532468
return path
@@ -2872,9 +2887,6 @@ def __call__(self, path, mutation_size, linewidth,
28722887
The __call__ method is a thin wrapper around the transmute method
28732888
and takes care of the aspect ratio.
28742889
"""
2875-
2876-
path = make_path_regular(path)
2877-
28782890
if aspect_ratio is not None:
28792891
# Squeeze the given height by the aspect_ratio
28802892
vertices = path.vertices / [1, aspect_ratio]
@@ -2886,10 +2898,9 @@ def __call__(self, path, mutation_size, linewidth,
28862898
if np.iterable(fillable):
28872899
path_list = []
28882900
for p in zip(path_mutated):
2889-
v, c = p.vertices, p.codes
28902901
# Restore the height
2891-
v[:, 1] = v[:, 1] * aspect_ratio
2892-
path_list.append(Path(v, c))
2902+
path_list.append(
2903+
Path(p.vertices * [1, aspect_ratio], p.codes))
28932904
return path_list, fillable
28942905
else:
28952906
return path_mutated, fillable
@@ -3340,7 +3351,7 @@ def transmute(self, path, mutation_size, linewidth):
33403351

33413352
# divide the path into a head and a tail
33423353
head_length = self.head_length * mutation_size
3343-
in_f = inside_circle(x2, y2, head_length)
3354+
in_f = _inside_circle(x2, y2, head_length)
33443355
arrow_path = [(x0, y0), (x1, y1), (x2, y2)]
33453356

33463357
try:
@@ -3423,7 +3434,7 @@ def transmute(self, path, mutation_size, linewidth):
34233434
arrow_path = [(x0, y0), (x1, y1), (x2, y2)]
34243435

34253436
# path for head
3426-
in_f = inside_circle(x2, y2, head_length)
3437+
in_f = _inside_circle(x2, y2, head_length)
34273438
try:
34283439
path_out, path_in = split_bezier_intersecting_with_closedpath(
34293440
arrow_path, in_f, tolerance=0.01)
@@ -3438,7 +3449,7 @@ def transmute(self, path, mutation_size, linewidth):
34383449
path_head = path_in
34393450

34403451
# path for head
3441-
in_f = inside_circle(x2, y2, head_length * .8)
3452+
in_f = _inside_circle(x2, y2, head_length * .8)
34423453
path_out, path_in = split_bezier_intersecting_with_closedpath(
34433454
arrow_path, in_f, tolerance=0.01)
34443455
path_tail = path_out
@@ -3456,7 +3467,7 @@ def transmute(self, path, mutation_size, linewidth):
34563467
w1=1., wm=0.6, w2=0.3)
34573468

34583469
# path for head
3459-
in_f = inside_circle(x0, y0, tail_width * .3)
3470+
in_f = _inside_circle(x0, y0, tail_width * .3)
34603471
path_in, path_out = split_bezier_intersecting_with_closedpath(
34613472
arrow_path, in_f, tolerance=0.01)
34623473
tail_start = path_in[-1]
@@ -4125,7 +4136,7 @@ def get_path(self):
41254136
"""
41264137
_path, fillable = self.get_path_in_displaycoord()
41274138
if np.iterable(fillable):
4128-
_path = concatenate_paths(_path)
4139+
_path = Path.make_compound_path(*_path)
41294140
return self.get_transform().inverted().transform_path(_path)
41304141

41314142
def get_path_in_displaycoord(self):

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.