[英]How to fill the space between two arcs and two segments in matplotlib?
我知道這種問題已經發布了好幾次了,但是在你做任何決定之前先聽我說完。
簡而言之,我想把這個:
進入這個:
所有曲線都是圓的六分之一,三條折線近似於螺旋的三個臂,我需要填充由兩個臂和兩個弧定義的所有區域。
我在這個站點上查看了一堆處理類似問題的問題,都提到ax.fill_between
方法,但它涉及 NumPy 數組,我沒有使用 NumPy 數組進行計算。
計算事物的函數如下(減去邊界框部分):
def polygon_spiral(unit, iterations, num_colors=12):
step = 1530/num_colors
palette = ['#'+spectrum_position(round(step*i), 1) for i in range(num_colors)]
colors = [palette[0]]
radius = unit*cos(30)/1.5
y1 = -radius/2
x1 = -unit/2
x2 = unit/2
points = [(0, radius), (x2, y1), (x1, y1)]
polygons = [points]
lines = [[(0, 0), (x1/2, radius/4)], [(0, 0), (0, y1)], [(0, 0), (x2/2, radius/4)]]
side = 4
left_start, left_end = points[0], points[2]
down_start, down_end = points[2], points[1]
right_start, right_end = points[1], points[0]
for i in range(iterations):
left = make_polygon(left_start, left_end, side)
down = make_polygon(down_start, down_end, side)
right = make_polygon(right_start, right_end, side)
polygons.append(left)
polygons.append(down)
polygons.append(right)
colors.extend([palette[(i+1)%num_colors]]*3)
half = (side/2).__ceil__()
left_start, left_end = left[half-1:half+1]
lines[0].append(mid(left_start, left_end))
down_start, down_end = down[half-1:half+1]
lines[1].append(mid(down_start, down_end))
right_start, right_end = right[half-1:half+1]
lines[2].append(mid(right_start, right_end))
side += 1
indices = {0: (1, 2), 1: (0, 2), 2: (0, 1)}
arcs = []
for i in range(iterations+1, 0, -1):
points = [lines[j][i] for j in range(3)]
(x0, y0), (x1, y1), (x2, y2) = points
dx = x1 - x0
dy = y1 - y0
r = (dx*dx + dy*dy)**.5
for k, v in indices.items():
a, b = points[k]
thetas = []
for h in v:
c, d = points[h]
angle = atan2(c - a, d - b)
if angle < 0:
angle += 360
thetas.append(angle)
theta1, theta2 = thetas
if theta1 > theta2:
theta1, theta2 = theta2, theta1
if not np.isclose(theta2 - theta1, 60):
theta1, theta2 = theta2 - 360, theta1
arcs.append([(a, b), r, theta1, theta2])
return {'polygons': polygons, 'lines': lines, 'arcs': arcs, 'colors': colors}
您可以在GitHub 上查看完整的腳本。
關鍵是線條存儲為三個離散頂點的坐標list
(存儲為(x, y)
tuple
s),它們是通過matplotlib.collections.LineCollection
繪制的,弧由其中心的坐標描述,它的半徑,theta1 和 theta2,並通過matplotlib.patches.Arc
繪制。
我沒有在這個腳本的任何地方使用數組,如何在不使用數組和fill_between
的情況下填充由兩個弧和兩個臂定義的區域,如果這不可能,我如何以矢量化方式進行相同的計算並使用fill_between
來填充區域?
我又解決了。
基本上,我使用多邊形填充了這些區域。
每個區域由四條線、兩條直線和兩條弧線包圍。 兩條弧跨度為 60°。
在arcs
list
,包圍該區域的外圓弧和內圓弧的索引相差 3。
所以我取了每對索引差為 3 的弧,並用它們制作了一個多邊形。
我是如何制作多邊形的?
弧跨度為 60°,我在第一個弧上采樣了 61 個點,每對相鄰點有 1° 的角度差,在另一個方向上在第二個弧上采樣了 61 個點:
L = len(arcs)
for i in range(3):
level = 0
for first, second in zip(arcs[i:L:3], arcs[i+3:L:3]):
f = 1 - level / iterations
r, g, b = colorsys.hsv_to_rgb(hues[i], f, f)
strip_colors.append('#{:02x}{:02x}{:02x}'.format(round(r*255), round(g*255), round(b*255)))
vertices = []
(a, b), r, theta1, theta2 = first
for n in range(61):
angle = theta1+n
vertices.append((a+r*cos(angle), b+r*sin(angle)))
(a, b), r, theta1, theta2 = second
for n in range(61):
angle = theta2-n
vertices.append((a+r*cos(angle), b+r*sin(angle)))
strips.append(vertices)
level += 1
完整的代碼在這里。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.