简体   繁体   English

带有 alpha 的 matplotlib Circle patch 产生边缘和面色的重叠

[英]matplotlib Circle patch with alpha produces overlap of edge and facecolor

I'm fairly new to matplotlib and python in general and what I'm trying to do is rather basic.一般来说,我对 matplotlib 和 python 还很陌生,我想做的是相当基础的。 However, even after quite some googling time I cannot find a solution for this:但是,即使经过相当长的谷歌搜索时间,我也找不到解决方案:

Here is the problem:这是问题所在:

I'd like to draw a circle with different color of the border and the face, ie set edgecolor and facecolor differently.我想画一个边框和脸颜色不同的圆,即设置不同的边edgecolorfacecolor I'd also like to have an alpha-channel, ie alpha=0.5 .我还想要一个 alpha 通道,即alpha=0.5 Now while all of this works fine, the resulting circle does not have a single border color, but 2 borders are drawn.现在,虽然所有这些工作正常,但生成的圆圈没有单一的边框颜色,而是绘制了 2 个边框。 One, the outer, in the color I specified for edgecolor and the other in a color I assume to be a combination between the edgecolor and the facecolor.一个是外部,使用我为edgecolor指定的颜色,另一个使用我假设为 edgecolor 和 facecolor 的组合的颜色。

Here is my code:这是我的代码:

from matplotlib import pyplot as plt
point = (1.0, 1.0)
c = plt.Circle(point, 1, facecolor='green', edgecolor='orange', linewidth=15.0, alpha=0.5)
fig, ax = plt.subplots()
ax.add_artist(c)
plt.show()

And here is an illustration:这是一个例子:

具有 2 种边框颜色的圆圈

Ok, this might be a minor thing, but this 2nd border drives me nuts!好吧,这可能是一件小事,但这第二个边界让我抓狂!

Am I doing something wrong?难道我做错了什么? Is that just the way it is?事情就是这样吗? Any help would be much appreciated.任何帮助将非常感激。

To some extent, yes, this is just the way it is.在某种程度上,是的,这就是事实。 The point is that the edge is literally drawn on the edge of the circle.关键是边缘实际上是画在圆的边缘上的。 This means that half of the edge width is drawn on top of the face of the circle and the other half outside.这意味着边宽的一半画在圆的表面上,另一半画在外面。 If now you set alpha<1.0 you see, as you concluded correctly, an overlap of the facecolor and the edgecolor.如果现在您设置alpha<1.0 ,您会看到,正如您正确得出的结论,facecolor 和 edgecolor 重叠。

However, you can get rid of that 'extra border' .但是,您可以摆脱那个“额外的边界” Below are 2 ways how to do so which one works best for you depends on what exactly you want to do.以下是两种方法,哪一种最适合你取决于你到底想做什么。

1st Suggestion :第一个建议

The simplest, IMHO, is to only set alpha for the facecolor .恕我直言,最简单的方法是只为facecolor设置 alpha This can be done by setting the alpha channel for the facecolor directly and omit the alpha argument in the call of Circle .这可以通过直接设置facecolor的 alpha 通道并在Circle的调用中省略alpha参数来完成。 You can set the alpha-channel with the colorConverter :您可以使用colorConverter设置 alpha 通道:

from matplotlib.colors import colorConverter
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(8, 8))
ax.axis('equal')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
# Here you set alpha for the faceolor
fc = colorConverter.to_rgba('green', alpha=0.5)
point = (1.0, 1.0)
r = 1.0
lw = 15.0
ec = 'orange'
# NOTE: do not set alpha when calling Circle!
c = plt.Circle(point, r,fc=fc, ec=ec, lw=lw)
ax.add_artist(c)
plt.show()

在此处输入图像描述

2nd Suggestion第二个建议

A more elaborated option is to 'wipe' the edge of the circle with a white edge after only plotting the face, then only plot the edge.一个更详细的选项是在仅绘制面部后用白色边缘“擦拭”圆的边缘,然后仅绘制边缘。 With this approach both colours appear with the alpha channel.使用这种方法,两种颜色都与 alpha 通道一起出现。 But note that also in this case any object that lies 'under' the edge will be completely masked by the edge:但请注意,在这种情况下,位于边缘“下方”的任何对象都将被边缘完全遮盖:

import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection

point = (1.0, 1.0)
r = 1.0
alpha = 0.5
lw = 15.0
fc = 'green'
ec = 'orange'
# First only draw the facecolor
c_face = plt.Circle(point, r, alpha=alpha, fc=fc, lw=0.0)
# Draw a non-transparent white edge to wipe the facecolor where they overlap
c_wipe = plt.Circle(point, r, alpha=1.0, ec='white', fc='none', lw=lw)
# Now draw only the edge
c_edge = plt.Circle(point, r, alpha=alpha, fc='none', ec=ec, lw=lw)
circle_patch = PatchCollection([c_face, c_wipe, c_edge], match_original=True)
fig, ax = plt.subplots(figsize=(8, 8))
ax.axis('equal')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
ax.add_artist(circle_patch)
plt.show()

在此处输入图像描述


Here is a gist that deals with this issue following the 2nd suggestion. 这是按照第二条建议处理此问题的要点 Simply download the mod_patch.py file and off you go.只需下载mod_patch.py 文件即可。

Here is how it can be used:以下是它的使用方法:

import matplotlib.pyplot as plt
from mod_patch import get_Patch
fig, ax = plt.subplots(figsize=(8,8))
c = get_Patch(plt.Circle, (0,0.5), 0.5, facecolor='green', edgecolor='orange', alpha=0.5, lw=15)
ax.add_artist(c)
r = get_Patch(plt.Rectangle, (0.5,0), 0.5, 0.5, facecolor='green', edgecolor='orange', alpha=0.5, lw=15)
ax.add_artist(r)
plt.show()

在此处输入图像描述

For completeness, here the definition of get_Patch :为了完整起见,这里定义了get_Patch

from matplotlib.collections import PatchCollection


def get_Patch(a_Patch, *args, **kwargs):
    background_color = kwargs.pop(
        'bgc',
        kwargs.pop('background_color', 'white')
    )
    alpha = kwargs.get('alpha', 1.0)
    patches = []
    lw = kwargs.get('lw', kwargs.get('linewidth', 0.0))
    if alpha < 1.0 and lw:
        color = kwargs.get('c', kwargs.get('color', None))
        fc = kwargs.get('facecolor', kwargs.get('fc', None))
        ec = kwargs.get('edgecolor', kwargs.get('ec', None))
        face_kwargs = dict(kwargs)
        face_kwargs['fc'] = fc if fc is not None else color
        face_kwargs['lw'] = 0.0
        p_face = a_Patch(*args, **face_kwargs)
        patches.append(p_face)
        wipe_kwargs = dict(kwargs)
        wipe_kwargs['fc'] = 'none'
        wipe_kwargs['ec'] = background_color
        wipe_kwargs['alpha'] = 1.0
        p_wipe = a_Patch(*args, **wipe_kwargs)
        patches.append(p_wipe)
        edge_kwargs = dict(kwargs)
        edge_kwargs['fc'] = 'none'
        edge_kwargs['ec'] = ec if ec is not None else color
        p_edge = a_Patch(*args, **edge_kwargs)
        patches.append(p_edge)
    else:
        p_simple = a_Patch(*args, **kwargs)
        patches.append(p_simple)
    return PatchCollection(patches, match_original=True)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM