Matplotlib如何填充两段圆弧与两条线段围成的封闭区域
方案1:无NumPy、无
fill_between填充实现(优先用,零核心逻辑改动) 根本不需要重构你现有的计算逻辑,也不用转NumPy数组,Matplotlib自带的路径对象完全支持用线段、圆弧拼出任意封闭形状直接填充,你已经算出的所有数据刚好够用。
- 实现原理:你要填的每一块封闭区域,边界都是固定的四段:两条相邻螺旋臂上相邻两层节点之间的折线段、两层节点之间各一段六分之一圆弧,四段刚好首尾闭合。
- 具体操作步骤:
- 导入两个Matplotlib类就行:
from matplotlib.path import Path、from matplotlib.patches import PathPatch,全程不用碰NumPy数组。 - 从最内层到最外层遍历每一层i,再遍历三个螺旋臂两两组合的三个扇区:
- 取相邻两个螺旋臂在第i层的节点p_a、p_b,在第i+1层的节点p_a_next、p_b_next
- 从你已经生成好的
arcs列表里,取出第i层对应p_a到p_b的圆弧参数、第i+1层对应p_a_next到p_b_next的圆弧参数 - 按顺序拼路径:
- 把起点设为p_a,路径指令标为
Path.MOVETO - 沿着第一条螺旋臂,把p_a到p_a_next之间存的所有顶点按顺序加进去,每个点对应指令都是
Path.LINETO - 接外层圆弧:直接调用
Path.arc(),传入你已经算好的外层圆弧圆心、半径、起始角度、终止角度,生成的圆弧段顶点和指令直接拼到路径后面,刚好从p_a_next画到p_b_next - 沿着第二条螺旋臂,把p_b_next到p_b之间的顶点逆序加进去,每个点对应指令还是
Path.LINETO - 接内层圆弧:同样调用
Path.arc(),传入内层圆弧的参数,注意把起始和终止角度调换方向,让圆弧刚好从p_b画回起点p_a - 最后加一个
Path.CLOSEPOLY指令闭合路径
- 把起点设为p_a,路径指令标为
- 用拼好的顶点列表、指令列表生成
Path实例,再转成PathPatch,设置好对应填充颜色加到坐标轴上就完成填充了。
- 导入两个Matplotlib类就行:
- 注意:你现在生成
arcs的时候已经按层、按三个扇区顺序存了所有圆弧参数,遍历的时候直接按索引取就行,不用重新算圆弧;所有坐标用你原来的(x,y)元组就可以,Path原生支持Python原生列表、元组输入,不需要转成数组。
方案2:向量化改造用
fill_between实现(不推荐,改动量大) 如果一定要用fill_between,才需要做向量化改造,性价比很低,改造逻辑如下:
- 所有曲线统一转成极坐标表达:
- 把三个螺旋臂的所有顶点从(x,y)笛卡尔坐标转成(极角theta, 极径r)的NumPy数组,用
np.interp把三个螺旋臂的极角重采样到统一的等距theta网格上,保证同一theta下能取到三个臂的r值。 - 每一层的六分之一圆弧本质是固定r值、theta跨60度的线段,直接在统一theta网格上生成对应段的r数组即可。
- 把三个螺旋臂的所有顶点从(x,y)笛卡尔坐标转成(极角theta, 极径r)的NumPy数组,用
- 填充时按60度一个区间遍历,每个区间的上边界是外层圆弧/外层螺旋臂的r值,下边界是内层圆弧/内层螺旋臂的r值,把极坐标转回笛卡尔坐标后调用
ax.fill_between填充即可。 - 这个方案的问题很明显:需要把你现有基于原生Python数值、元组的计算逻辑全改成NumPy数组操作,还要处理插值精度问题,曲线段容易出现缝隙或者锯齿,效果和开发效率都不如方案1。
内容的提问来源于stack exchange,提问作者Ξένη Γήινος
相关产品推荐
相关产品推荐

