问题描述
我有一个椭圆
,我想用不同部分的颜色 solid 填充
.为此,我使用了 arcs
补丁.我目前正在绘制多个 arcs
,并使用 zorder
重叠相应的 arcs
.
主要问题是我无法固定填充 arc
补丁,并且它们不能整齐地填充 ellipse
.也不重叠,所以我可以使用透明度参数.
将matplotlib.pyplot导入为plt将matplotlib导入为mpl导入数学无花果,ax = plt.subplots(figsize =(8,5))ax.grid(假)ax.set_xlim(-85,85)ax.set_ylim(-70,70)Arc1_xy = -68,0Arc2_xy = -48,0Arc3_xy = 15,0Arc4_xy = 68,0Arc5_xy = 48,0Arc6_xy = -15,0E_xy = 0,0角度=数学度(math.acos(2/9.15))Arc1 = mpl.patches.Arc(Arc1_xy,75,92,angle = 360,theta2 = angle,theta1 = 360-angle,color ='w',lw = 1,alpha = 1,hatch ='oooooo',zorder =3)Arc2 = mpl.patches.Arc(Arc2_xy,64,94,angle = 180,theta2 = angle,theta1 = 360-angle,color ='w',lw = 1,alpha = 1,hatch ='oooooo',zorder =3)Arc3 = mpl.patches.Arc(Arc3_xy,190,132,angle = -180,theta2 = angle,theta1 = 360-angle,color ='w',lw = 1,alpha = 1,hatch ='oooooo',zorder= 1)Arc4 = mpl.patches.Arc(Arc4_xy,75,92,angle = 180,theta2 = angle,theta1 = 360-angle,color ='w',lw = 1,alpha = 1,hatch ='oooooo',zorder =3)Arc5 = mpl.patches.Arc(Arc5_xy,64,94,angle = 0,theta2 = angle,theta1 = 0-angle,color ='w',lw = 1,alpha = 1,hatch ='oooooo',zorder =3)Arc6 = mpl.patches.Arc(Arc6_xy,190,132,angle = 360,theta2 = angle,theta1 = 360-angle,color ='w',lw = 1,alpha = 1,hatch ='oooooo',zorder =1)椭圆= mpl.patches.Ellipse(E_xy,160,130,lw = 1,颜色='白色',alpha = 1,填充= False)ax.add_patch(Arc1)ax.add_patch(Arc2)ax.add_patch(Arc3)ax.add_patch(Arc4)ax.add_patch(Arc5)ax.add_patch(Arc6)ax.add_patch(椭圆)Arc1.set_color('绿色')Arc2.set_color('绿色')Arc3.set_color('blue')Arc4.set_color('红色')Arc5.set_color('红色')Arc6.set_color('紫色')
主要问题是我想在椭圆
的内部填充不同颜色的部分.理想情况下,这些部分不会重叠,因此我可以使用 alpha
.同样, arcs
也不完全适合 ellipse
.
您的问题不是很清楚.这是您代码的更新版本:
#已编辑,请参见下文
Arc4
填充椭圆的另一侧.是您所期望的吗?
我还添加了一个有关如何使用颜色图的示例.有各种各样的
您说要固定填充椭圆.不使用色块".要进行实心填充,只需使用您所在区域的 fill
和 color
参数(如果不需要,请删除 hatch
).但是,我看不出没有补丁"如何可以实现想要的目标.抱歉.
希望获得帮助.
编辑2
经过澄清后,这里是一个新版本:
导入数学导入matplotlib.pyplot作为plt将matplotlib导入为mpldef main():无花果,ax = plt.subplots(figsize =(8,5))ax.grid(假)ax.set_xlim(-85,85)ax.set_ylim(-70,70)Arc1_xy = -68,0E_xy = 0,0#使用预定义的颜色图colormap = plt.cm.get_cmap("Set1")#绘制多个具有不同颜色和样式的椭圆.一切都完美地叠加ellipse = mpl.patches.Ellipse(#基数一,黑线较大,仅供参考E_xy,160、130,lw = 2,颜色='k',填充=否,zorder = 100)#椭圆表示您的子区域.#如果需要更多区域,请添加更多#在此处应用您所在区域的样式(颜色,alpha,阴影线等)面积= [mpl.patches.Ellipse(E_xy,160、130,#非常适合您的基本椭圆color = colormap(i),fill = True,alpha = 0.5,#添加一些样式,填充,颜色,alphazorder = i)因为我的范围是(4)#在这里,我们有4个区域]#定义一些剪切路径#每个区域一个剪辑= [mpl.patches.Arc(#一个覆盖椭圆的右半部分E_xy,160、130,theta1 = -90,theta2 = 90,visible = False#我们不需要显示它,只需将其用于剪切),mpl.patches.Arc(#一个覆盖椭圆的左半部分元组([-x for E_xy中的x]]),160、130,theta1 = 90,theta2 = -90,visible = False#我们不需要显示它,只需将其用于剪切),mpl.patches.Ellipse(#左侧的一个小区域Arc1_xy,75、92,visible = False#我们不需要显示它,只需将其用于剪切),mpl.patches.Ellipse(#右边的一个小区域元组([-x for Arc1_xy中的x]],75、92,visible = False#我们不需要显示它,只需将其用于剪切)]#将所有组件添加到斧头中ax.add_patch(椭圆)对于区域,用zip夹(区域,剪辑):ax.add_patch(区域)ax.add_patch(剪辑)area.set_clip_path(clip)#使用剪切路径剪切区域plt.show()如果__name__ =='__main__':主要的()
和生成的图像:
它是如何工作的:
- 绘制多个完全与基础"重叠的椭圆.这样可以确保您所有的区域都完美地位于内部内部椭圆中(没有一个可以扩展)
- 通过定义剪切路径来裁剪/剪切椭圆以仅显示其中的一部分.这些剪切路径必须穿过(或至少遵循)基本的椭圆边框以使其充满(这就是为什么我使用椭圆的中心和尺寸来更改Arc3的原因,否则椭圆内的边框,如第一个图所示).
您最近一次尝试并没有那么远.要对区域进行样式设置,您必须将样式应用于基本椭圆(在我的代码的 ares
列表中列出),而不是对剪切路径(在 clips
列表中列出)在我的代码中). area
和 clips
这两个列表都必须具有相同的长度!如果您想在椭圆中添加更多子区域,则可以自行决定添加更多区域和更多剪切路径.
顺便说一句,我看到了您更新的问题和您对使区域不重叠的要求.这将需要更多的工作.您可以使用 matplotlip.path
模块.
I have an ellipse
that I want to solid fill
with colors in different sections. To achieve this I'm using arcs
patches. I'm currently drawing multiple arcs
and using zorder
to overlap the appropriate arcs
.
Main issues are that I cannot solid fill arc
patches and they are not neatly filling the ellipse
. It would be great if the areas didn't overlap either so I could use transparency parameters.
import matplotlib.pyplot as plt
import matplotlib as mpl
import math
fig, ax = plt.subplots(figsize = (8,5))
ax.grid(False)
ax.set_xlim(-85,85)
ax.set_ylim(-70,70)
Arc1_xy = -68, 0
Arc2_xy = -48,0
Arc3_xy = 15, 0
Arc4_xy = 68, 0
Arc5_xy = 48,0
Arc6_xy = -15, 0
E_xy = 0,0
angle = math.degrees(math.acos(2/9.15))
Arc1 = mpl.patches.Arc(Arc1_xy, 75, 92, angle = 360, theta2 = angle, theta1 = 360-angle, color = 'w', lw = 1, alpha = 1, hatch = 'oooooo', zorder = 3)
Arc2 = mpl.patches.Arc(Arc2_xy, 64, 94, angle = 180, theta2 = angle, theta1 = 360-angle, color = 'w', lw = 1, alpha = 1, hatch = 'oooooo', zorder = 3)
Arc3 = mpl.patches.Arc(Arc3_xy, 190, 132, angle = -180, theta2 = angle, theta1 = 360-angle, color = 'w', lw = 1, alpha = 1, hatch = 'oooooo', zorder = 1)
Arc4 = mpl.patches.Arc(Arc4_xy, 75, 92, angle = 180, theta2 = angle, theta1 = 360-angle, color = 'w', lw = 1, alpha = 1, hatch = 'oooooo', zorder = 3)
Arc5 = mpl.patches.Arc(Arc5_xy, 64, 94, angle = 0, theta2 = angle, theta1 = 0-angle, color = 'w', lw = 1, alpha = 1, hatch = 'oooooo', zorder = 3)
Arc6 = mpl.patches.Arc(Arc6_xy, 190, 132, angle = 360, theta2 = angle, theta1 = 360-angle, color = 'w', lw = 1, alpha = 1, hatch = 'oooooo', zorder = 1)
Ellipse = mpl.patches.Ellipse(E_xy, 160, 130, lw = 1, color = 'white', alpha = 1, fill = False)
ax.add_patch(Arc1)
ax.add_patch(Arc2)
ax.add_patch(Arc3)
ax.add_patch(Arc4)
ax.add_patch(Arc5)
ax.add_patch(Arc6)
ax.add_patch(Ellipse)
Arc1.set_color('green')
Arc2.set_color('green')
Arc3.set_color('blue')
Arc4.set_color('red')
Arc5.set_color('red')
Arc6.set_color('purple')
The main issues are I want to solid fill the different colored sections within the ellipse
. Ideally the sections would not overlap so I could use alpha
. Also the arcs
don't neatly fit within the ellipse
.
Your question is not very clear. Here is an updated version of your code:
# EDITED, see below
The Arc4
fills the other side of the ellipse. Is it what you expected?
I also added an example on how to use a colormap. There is wide range of colormaps,many of them ranging from 0 to 255 (up to you to normalize to 0.0-1.0).
Another solution could be to draw overlapping ellipses and use the clip_path attribute to only show the required part.
Edit after comment
To fit perfectly the ellipse you have to calculate you arcs to fit it, which is probably difficult (maybe some nice math tricks allow it, but it is out of my knowledge). So my best bet is to draw multiple ellipses of the same size and use clipping paths.
import matplotlib.pyplot as plt
import matplotlib as mpl
def main():
fig, ax = plt.subplots(figsize = (8,5))
ax.grid(False)
ax.set_xlim(-80,80)
ax.set_ylim(-70,70)
Arc1_xy = -68, 0
Arc3_xy = 15, 0
E_xy = 0,0
# Use a predefined colormap
colormap = plt.cm.get_cmap("Set1")
# Draw multiple ellipses with different colors and hatching style. All are perfectly superposed
ellipse = mpl.patches.Ellipse( # Base one, with big black line for reference, in background (zorder=0)
E_xy, 160, 130,
lw = 2, color = 'k', fill=False, zorder=0)
area1 = mpl.patches.Ellipse( # A second one, above the base one, using a color from colormap
E_xy, 160, 130,
lw=1, # Just to highlight that we perfectly fit the base ellipse
color = colormap(0), hatch='o', fill=False, zorder=1)
area2 = mpl.patches.Ellipse( # Third one, above the others
E_xy, 160, 130,
lw=1, # Just to highlight that we perfectly fit the base ellipse
color = colormap(1), hatch='..', fill=False, zorder=2)
# Add more if you want more "sub-areas" in your base ellipse
# Define some clipping paths
clip1 = mpl.patches.Ellipse(
Arc1_xy, 75, 92,
fill=False,
ls=":" # Just to highlight it but you should remove it
# visible=False # We do not need to display it, just to use it for clipping
)
clip2 = mpl.patches.Ellipse(
Arc3_xy, 190, 132, angle = -180,
fill=False,
ls=":" # Just to highlight it but you should remove it
# visible=False # We do not need to display it, just to use it for clipping
)
# Add all your components to your axe
ax.add_patch(ellipse)
ax.add_patch(area1)
ax.add_patch(area2)
ax.add_patch(clip1)
ax.add_patch(clip2)
# Clip the sub-areas with your clipping paths
area1.set_clip_path(clip2)
area2.set_clip_path(clip1)
plt.show()
if __name__ == '__main__':
main()
This will draw you:
- A big black elliptic line (the base ellipse)
- Two hatched (one with dots, one with circles) sub-area inside your base ellipse
- Thin dotted lines, outlining your clipping paths
You say that you want to "solid fill the ellipse. Not use patch". To solid fill, just play with the fill
and color
arguments of your areas (and remove hatch
if you don't want it). However, I don't see how you can achieve what you want without "patch". Sorry.
Hope this help.
Edit 2
After clarifications here is a new version:
import math
import matplotlib.pyplot as plt
import matplotlib as mpl
def main():
fig, ax = plt.subplots(figsize=(8, 5))
ax.grid(False)
ax.set_xlim(-85, 85)
ax.set_ylim(-70, 70)
Arc1_xy = -68, 0
E_xy = 0, 0
# Use a predefined colormap
colormap = plt.cm.get_cmap("Set1")
# Draw multiple ellipses with different colors and style. All are perfectly superposed
ellipse = mpl.patches.Ellipse( # Base one, with big black line for reference
E_xy, 160, 130,
lw=2, color='k', fill=False, zorder=100)
# Ellipses for your sub-areas.
# Add more if you want more areas
# Apply the style of your areas here (colors, alpha, hatch, etc.)
areas = [
mpl.patches.Ellipse(
E_xy, 160, 130, # Perfectly fit your base ellipse
color=colormap(i), fill=True, alpha=0.5, # Add some style, fill, color, alpha
zorder=i)
for i in range(4) # Here, we have 4 areas
]
# Define some clipping paths
# One for each area
clips = [
mpl.patches.Arc( # One covering right half of your ellipse
E_xy, 160, 130, theta1=-90, theta2=90,
visible=False # We do not need to display it, just to use it for clipping
),
mpl.patches.Arc( # One covering left half of your ellipse
tuple([-x for x in E_xy]), 160, 130, theta1=90, theta2=-90,
visible=False # We do not need to display it, just to use it for clipping
),
mpl.patches.Ellipse( # A small area on the left
Arc1_xy, 75, 92,
visible=False # We do not need to display it, just to use it for clipping
),
mpl.patches.Ellipse( # A small area on the right
tuple([-x for x in Arc1_xy]), 75, 92,
visible=False # We do not need to display it, just to use it for clipping
)
]
# Add all your components to your axe
ax.add_patch(ellipse)
for area, clip in zip(areas, clips):
ax.add_patch(area)
ax.add_patch(clip)
area.set_clip_path(clip) # Use clipping paths to clip you areas
plt.show()
if __name__ == '__main__':
main()
And the resulting image:
How does it works is:
- by drawing multiple ellipses perfectly superposed to the "base" one. This make sure that all your areas are perfectly fitted inside your base ellipse (none of them can outreach)
- by defining clipping paths that will crop/clip the ellipses to just show part of them. These clipping paths have to cross (or at least follow) the base ellipse borders to make it filled (that's why I change your Arc3, using the ellipse center and dimensions, else there was a white space on the border, inside the ellipse, as you can see on the first figure).
You were not so far with your last try. To style your areas, you have to apply style to your base ellipses (listed in the areas
list in my code), not to your clipping paths (listed in the clips
list in my code). Both lists, areas
and clips
need to have the same length! Up to you to add more areas and more clipping paths if you want more sub-areas in your ellipses.
By the way, I see your updated question and your requirements to make the areas not overlapping. This will require more work. You can achieve it by building more complicated clipping path, using the matplotlip.path
module.
这篇关于在圆弧补丁之间填充-Matplotlib的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!