Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 05e4ed9

Browse files
committed
Use edgecolor rather than linewidth to control edge display.
An rcParam['patch.force_edgecolor'] was added so that a default edgecolor can be specified to be used always (as in classic mode), or to be used only when a fillable object is not actually filled.
1 parent 88ce601 commit 05e4ed9

File tree

6 files changed

+116
-110
lines changed

6 files changed

+116
-110
lines changed

lib/matplotlib/collections.py

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -492,14 +492,9 @@ def set_linewidth(self, lw):
492492
ACCEPTS: float or sequence of floats
493493
"""
494494
if lw is None:
495-
if (self._edge_default or
496-
mpl.rcParams['_internal.classic_mode'] or
497-
not self._is_filled):
498-
lw = mpl.rcParams['patch.linewidth']
499-
if lw is None:
500-
lw = mpl.rcParams['lines.linewidth']
501-
else:
502-
lw = 0
495+
lw = mpl.rcParams['patch.linewidth']
496+
if lw is None:
497+
lw = mpl.rcParams['lines.linewidth']
503498
# get the un-scaled/broadcast lw
504499
self._us_lw = self._get_value(lw)
505500

@@ -644,6 +639,20 @@ def set_color(self, c):
644639
self.set_facecolor(c)
645640
self.set_edgecolor(c)
646641

642+
def _set_facecolor(self, c):
643+
if c is None:
644+
c = mpl.rcParams['patch.facecolor']
645+
646+
self._is_filled = True
647+
try:
648+
if c.lower() == 'none':
649+
self._is_filled = False
650+
except AttributeError:
651+
pass
652+
self._facecolors = mcolors.to_rgba_array(c, self._alpha)
653+
self.stale = True
654+
655+
647656
def set_facecolor(self, c):
648657
"""
649658
Set the facecolor(s) of the collection. *c* can be a
@@ -655,17 +664,9 @@ def set_facecolor(self, c):
655664
656665
ACCEPTS: matplotlib color spec or sequence of specs
657666
"""
658-
self._is_filled = True
659-
try:
660-
if c.lower() == 'none':
661-
self._is_filled = False
662-
except AttributeError:
663-
pass
664-
if c is None:
665-
c = mpl.rcParams['patch.facecolor']
666-
self._facecolors_original = c
667-
self._facecolors = mcolors.to_rgba_array(c, self._alpha)
668-
self.stale = True
667+
self._original_facecolor = c
668+
self._set_facecolor(c)
669+
669670

670671
def set_facecolors(self, c):
671672
"""alias for set_facecolor"""
@@ -683,6 +684,23 @@ def get_edgecolor(self):
683684
return self._edgecolors
684685
get_edgecolors = get_edgecolor
685686

687+
def _set_edgecolor(self, c):
688+
self._is_stroked = True
689+
try:
690+
if c.lower() == 'none':
691+
self._is_stroked = False
692+
except AttributeError:
693+
pass
694+
695+
try:
696+
if c.lower() == 'face': # Special case: lookup in "get" method.
697+
self._edgecolors = 'face'
698+
return
699+
except AttributeError:
700+
pass
701+
self._edgecolors = mcolors.to_rgba_array(c, self._alpha)
702+
self.stale = True
703+
686704
def set_edgecolor(self, c):
687705
"""
688706
Set the edgecolor(s) of the collection. *c* can be a
@@ -696,24 +714,14 @@ def set_edgecolor(self, c):
696714
697715
ACCEPTS: matplotlib color spec or sequence of specs
698716
"""
699-
self._is_stroked = True
700-
try:
701-
if c.lower() == 'none':
702-
self._is_stroked = False
703-
except AttributeError:
704-
pass
705-
try:
706-
if c.lower() == 'face':
707-
self._edgecolors = 'face'
708-
self._edgecolors_original = 'face'
709-
return
710-
except AttributeError:
711-
pass
717+
self._original_edgecolor = c
712718
if c is None:
713-
c = mpl.rcParams['patch.edgecolor']
714-
self._edgecolors_original = c
715-
self._edgecolors = mcolors.to_rgba_array(c, self._alpha)
716-
self.stale = True
719+
if (mpl.rcParams['patch.force_edgecolor'] or
720+
not self._is_filled or self._edge_default):
721+
c = mpl.rcParams['patch.edgecolor']
722+
else:
723+
c = 'none'
724+
self._set_edgecolor(c)
717725

718726
def set_edgecolors(self, c):
719727
"""alias for set_edgecolor"""
@@ -732,18 +740,8 @@ def set_alpha(self, alpha):
732740
except TypeError:
733741
raise TypeError('alpha must be a float or None')
734742
artist.Artist.set_alpha(self, alpha)
735-
try:
736-
self._facecolors = mcolors.to_rgba_array(
737-
self._facecolors_original, self._alpha)
738-
except (AttributeError, TypeError, IndexError):
739-
pass
740-
try:
741-
if (not isinstance(self._edgecolors_original, six.string_types)
742-
or self._edgecolors_original != str('face')):
743-
self._edgecolors = mcolors.to_rgba_array(
744-
self._edgecolors_original, self._alpha)
745-
except (AttributeError, TypeError, IndexError):
746-
pass
743+
self._set_facecolor(self._original_facecolor)
744+
self._set_edgecolor(self._original_edgecolor)
747745

748746
def get_linewidths(self):
749747
return self._linewidths
@@ -779,9 +777,9 @@ def update_from(self, other):
779777

780778
artist.Artist.update_from(self, other)
781779
self._antialiaseds = other._antialiaseds
782-
self._edgecolors_original = other._edgecolors_original
780+
self._original_edgecolor = other._original_edgecolor
783781
self._edgecolors = other._edgecolors
784-
self._facecolors_original = other._facecolors_original
782+
self._original_facecolor = other._original_facecolor
785783
self._facecolors = other._facecolors
786784
self._linewidths = other._linewidths
787785
self._linestyles = other._linestyles

lib/matplotlib/mpl-data/stylelib/classic.mplstyle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ markers.fillstyle: full
2929
# information on patch properties
3030
patch.linewidth : 1.0 # edge width in points
3131
patch.facecolor : b
32+
patch.force_edgecolor : True
3233
patch.edgecolor : k
3334
patch.antialiased : True # render patches in antialiased (no jaggies)
3435

lib/matplotlib/patches.py

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -154,18 +154,26 @@ def get_verts(self):
154154
return polygons[0]
155155
return []
156156

157+
def _process_radius(self, radius):
158+
if radius is not None:
159+
return radius
160+
if cbook.is_numlike(self._picker):
161+
_radius = self._picker
162+
else:
163+
if self.get_edgecolor()[3] == 0:
164+
_radius = 0
165+
else:
166+
_radius = self.get_linewidth()
167+
return _radius
168+
157169
def contains(self, mouseevent, radius=None):
158170
"""Test whether the mouse event occurred in the patch.
159171
160172
Returns T/F, {}
161173
"""
162174
if six.callable(self._contains):
163175
return self._contains(self, mouseevent)
164-
if radius is None:
165-
if cbook.is_numlike(self._picker):
166-
radius = self._picker
167-
else:
168-
radius = self.get_linewidth()
176+
radius = self._process_radius(radius)
169177
inside = self.get_path().contains_point(
170178
(mouseevent.x, mouseevent.y), self.get_transform(), radius)
171179
return inside, {}
@@ -175,11 +183,7 @@ def contains_point(self, point, radius=None):
175183
Returns *True* if the given point is inside the path
176184
(transformed with its transform attribute).
177185
"""
178-
if radius is None:
179-
if cbook.is_numlike(self._picker):
180-
radius = self._picker
181-
else:
182-
radius = self.get_linewidth()
186+
radius = self._process_radius(radius)
183187
return self.get_path().contains_point(point,
184188
self.get_transform(),
185189
radius)
@@ -281,37 +285,45 @@ def set_aa(self, aa):
281285
"""alias for set_antialiased"""
282286
return self.set_antialiased(aa)
283287

288+
def _set_edgecolor(self, color):
289+
if color is None:
290+
if (mpl.rcParams['patch.force_edgecolor'] or
291+
not self._fill or self._edge_default):
292+
color = mpl.rcParams['patch.edgecolor']
293+
else:
294+
color = 'none'
295+
self._edgecolor = colors.to_rgba(color, self._alpha)
296+
self.stale = True
297+
284298
def set_edgecolor(self, color):
285299
"""
286300
Set the patch edge color
287301
288-
ACCEPTS: mpl color spec, or None for default, or 'none' for no color
302+
ACCEPTS: mpl color spec, None, 'none', or 'auto'
289303
"""
290-
if color is None:
291-
color = mpl.rcParams['patch.edgecolor']
292304
self._original_edgecolor = color
293-
self._edgecolor = colors.to_rgba(color, self._alpha)
294-
self.stale = True
305+
self._set_edgecolor(color)
306+
295307

296308
def set_ec(self, color):
297309
"""alias for set_edgecolor"""
298310
return self.set_edgecolor(color)
299311

312+
def _set_facecolor(self, color):
313+
alpha = self._alpha if self._fill else 0
314+
self._facecolor = colors.to_rgba(color, alpha)
315+
self.stale = True
316+
300317
def set_facecolor(self, color):
301318
"""
302319
Set the patch face color
303320
304321
ACCEPTS: mpl color spec, or None for default, or 'none' for no color
305322
"""
323+
self._original_facecolor = color # Not strictly needed now.
306324
if color is None:
307325
color = mpl.rcParams['patch.facecolor']
308-
# save: otherwise changing _fill may lose alpha information
309-
self._original_facecolor = color
310-
self._facecolor = colors.to_rgba(color, self._alpha)
311-
if not self._fill:
312-
self._facecolor = list(self._facecolor)
313-
self._facecolor[3] = 0
314-
self.stale = True
326+
self._set_facecolor(color)
315327

316328
def set_fc(self, color):
317329
"""alias for set_facecolor"""
@@ -343,10 +355,10 @@ def set_alpha(self, alpha):
343355
except TypeError:
344356
raise TypeError('alpha must be a float or None')
345357
artist.Artist.set_alpha(self, alpha)
346-
# using self._fill and self._alpha
347-
self.set_facecolor(self._original_facecolor)
348-
self.set_edgecolor(self._original_edgecolor)
349-
self.stale = True
358+
self._set_facecolor(self._facecolor)
359+
self._set_edgecolor(self._original_edgecolor)
360+
# stale is already True
361+
350362

351363
def set_linewidth(self, w):
352364
"""
@@ -355,14 +367,9 @@ def set_linewidth(self, w):
355367
ACCEPTS: float or None for default
356368
"""
357369
if w is None:
358-
if (not self._fill or
359-
self._edge_default or
360-
mpl.rcParams['_internal.classic_mode']):
361-
w = mpl.rcParams['patch.linewidth']
362-
if w is None:
363-
w = mpl.rcParams['axes.linewidth']
364-
else:
365-
w = 0
370+
w = mpl.rcParams['patch.linewidth']
371+
if w is None:
372+
w = mpl.rcParams['axes.linewidth']
366373

367374
self._linewidth = float(w)
368375
# scale the dash pattern by the linewidth
@@ -428,7 +435,8 @@ def set_fill(self, b):
428435
ACCEPTS: [True | False]
429436
"""
430437
self._fill = bool(b)
431-
self.set_facecolor(self._original_facecolor)
438+
self._set_facecolor(self._facecolor)
439+
self._set_edgecolor(self._original_edgecolor)
432440
self.stale = True
433441

434442
def get_fill(self):

lib/matplotlib/rcsetup.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ def validate_color(s):
364364
'return a valid color arg'
365365
try:
366366
if s.lower() == 'none':
367-
return 'None'
367+
return 'none'
368368
except AttributeError:
369369
pass
370370

@@ -906,7 +906,7 @@ def validate_animation_writer_path(p):
906906
'lines.linewidth': [1.5, validate_float], # line width in points
907907
'lines.linestyle': ['-', six.text_type], # solid line
908908
'lines.color': ['C0', validate_color], # first color in color cycle
909-
'lines.marker': ['None', six.text_type], # black
909+
'lines.marker': ['None', six.text_type], # marker name
910910
'lines.markeredgewidth': [1.0, validate_float],
911911
'lines.markersize': [6, validate_float], # markersize, in points
912912
'lines.antialiased': [True, validate_bool], # antialiased (no jaggies)
@@ -922,10 +922,11 @@ def validate_animation_writer_path(p):
922922
'markers.fillstyle': ['full', validate_fillstyle],
923923

924924
## patch props
925-
'patch.linewidth': [None, validate_float_or_None], # line width in points
926-
'patch.edgecolor': ['k', validate_color], # black
927-
'patch.facecolor': ['C0', validate_color], # first color in color cycle
928-
'patch.antialiased': [True, validate_bool], # antialiased (no jaggies)
925+
'patch.linewidth': [1.0, validate_float], # line width in points
926+
'patch.edgecolor': ['k', validate_color],
927+
'patch.force_edgecolor' : [False, validate_bool],
928+
'patch.facecolor': ['C0', validate_color], # first color in cycle
929+
'patch.antialiased': [True, validate_bool], # antialiased (no jaggies)
929930

930931
## hatch props
931932
'hatch.linewidth': [1.0, validate_float],

lib/matplotlib/tests/test_artist.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -182,21 +182,20 @@ def test_remove():
182182
@image_comparison(baseline_images=["default_edges"], remove_text=True,
183183
extensions=['png'], style='default')
184184
def test_default_edges():
185-
with mpl.rc_context({'patch.linewidth': None}):
186-
fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(2, 2)
187-
188-
ax1.plot(np.arange(10), np.arange(10), 'x',
189-
np.arange(10) + 1, np.arange(10), 'o')
190-
ax2.bar(np.arange(10), np.arange(10))
191-
ax3.text(0, 0, "BOX", size=24, bbox=dict(boxstyle='sawtooth'))
192-
ax3.set_xlim((-1, 1))
193-
ax3.set_ylim((-1, 1))
194-
pp1 = mpatches.PathPatch(
195-
mpath.Path([(0, 0), (1, 0), (1, 1), (0, 0)],
196-
[mpath.Path.MOVETO, mpath.Path.CURVE3,
197-
mpath.Path.CURVE3, mpath.Path.CLOSEPOLY]),
198-
fc="none", transform=ax4.transData)
199-
ax4.add_patch(pp1)
185+
fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(2, 2)
186+
187+
ax1.plot(np.arange(10), np.arange(10), 'x',
188+
np.arange(10) + 1, np.arange(10), 'o')
189+
ax2.bar(np.arange(10), np.arange(10))
190+
ax3.text(0, 0, "BOX", size=24, bbox=dict(boxstyle='sawtooth'))
191+
ax3.set_xlim((-1, 1))
192+
ax3.set_ylim((-1, 1))
193+
pp1 = mpatches.PathPatch(
194+
mpath.Path([(0, 0), (1, 0), (1, 1), (0, 0)],
195+
[mpath.Path.MOVETO, mpath.Path.CURVE3,
196+
mpath.Path.CURVE3, mpath.Path.CLOSEPOLY]),
197+
fc="none", transform=ax4.transData)
198+
ax4.add_patch(pp1)
200199

201200

202201
@cleanup

matplotlibrc.template

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,10 @@ backend : $TEMPLATE_BACKEND
102102
# circles. See
103103
# http://matplotlib.org/api/artist_api.html#module-matplotlib.patches
104104
# information on patch properties
105-
#patch.linewidth : None # edge width in points.
106-
# If None, use axes.linewidth when patch
107-
# is not filled.
105+
#patch.linewidth : 1 # edge width in points.
108106
#patch.facecolor : C0
109-
#patch.edgecolor : black
107+
#patch.edgecolor : black # if forced, or patch is not filled
108+
#patch.force_edgecolor : False # True to always use edgecolor
110109
#patch.antialiased : True # render patches in antialiased (no jaggies)
111110

112111
### HATCHES

0 commit comments

Comments
 (0)