matplotlib Круглый патч с альфа-каналом создает перекрытие краев и цвета лица - PullRequest
0 голосов
/ 16 декабря 2018

Я довольно новичок в matplotlib и python в целом, и то, что я пытаюсь сделать, довольно просто.Однако даже после некоторого времени поиска в Google я не могу найти решение для этого:

Вот проблема:

Я хотел бы нарисовать круг с другим цветом границы и лица, т.е. установите edgecolor и facecolor по-разному.Я также хотел бы иметь альфа-канал, то есть alpha=0.5.Теперь, когда все это работает нормально, результирующий круг не имеет единственного цвета рамки, но нарисованы 2 границы.Один, внешний, в цвете, который я указал для edgecolor, а другой - в цвете, который я предполагаю как комбинацию между краевым и лицевым цветом.

Вот мой код:

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()

И вот иллюстрация:

circle with 2 border colors

Хорошо, это может быть незначительной вещью, но эта вторая граница сводит меня с ума!

Я что-то не так делаю?Это так и есть?Любая помощь будет высоко ценится.

1 Ответ

0 голосов
/ 16 декабря 2018

В некоторой степени, да, это так, как оно есть.Дело в том, что край буквально нарисован на краю круга.Это означает, что половина ширины кромки рисуется поверх грани круга, а другая половина - снаружи.Если теперь вы установите alpha<1.0, вы увидите, как вы правильно сделали вывод, наложение цвета лица и края.

Однако, вы можете избавиться от этой «дополнительной границы» .Ниже приведены 2 способа, как сделать то, что лучше всего подходит для вас, зависит от того, что именно вы хотите сделать.

Первое предложение :

Самое простое, ИМХО, этона установить только альфа для facecolor.Это можно сделать, установив альфа-канал для facecolor напрямую и пропустив аргумент alpha в вызове Circle.Вы можете установить альфа-канал с помощью colorConverter:

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()

enter image description here

2-е предложение

Более сложный вариант - «протереть» край круга белым краем после построения только грани, а затем только прорисовать край.При таком подходе оба цвета появляются с альфа-каналом.Но обратите внимание, что и в этом случае любой объект, который находится «под» краем, будет полностью замаскирован краем:

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()

enter image description here


Вот суть , которая решает эту проблему после 2-го предложения.Просто скачайте файл mod_patch.py ​​ и начинайте.

Вот как его можно использовать:

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()

enter image description here

Для полноты, вот определение 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...