gpt4 book ai didi

python - 如何使用 manim 创建正确的饼图

转载 作者:行者123 更新时间:2023-12-04 11:48:37 30 4
gpt4 key购买 nike

无论如何,我正在尝试(这实际上是我的第一个 manim 程序)。

from manim import *
import copy
import numpy as np
import random

color_palette = [BLUE, GREEN, YELLOW, GREY_BROWN]

class TestPie(Scene):
def construct(self):
n_elements = 3
radius = 1
weights = np.random.rand(n_elements)
weights /= weights.sum()
angles = weights*np.pi*2
angles_offset = [0]+np.cumsum(weights*np.pi*2)[:-1].tolist()
arcs = [Arc(angles_offset[i], angles[i]) for i in range(n_elements)]
arcs2 = copy.deepcopy(arcs)
triangles = [Polygon(*[
# first element
(radius*np.cos(angles_offset[i]), radius*np.sin(angles_offset[i]),0),
(0, 0, 0), # second element
# third element
(radius*np.cos(angles_offset[(i+1)%n_elements]),
radius*np.sin(angles_offset[(i+1)%n_elements]), 0)], stroke_width=0)
for i in range(n_elements)]
lines = [Line((0,0,0),
(radius*np.cos(angles_offset[i]), radius*np.sin(angles_offset[i]), 0))
for i in range(n_elements)]
for i in range(n_elements):
arcs2[i].set_fill(color_palette[i%len(color_palette)], opacity=0.5)
triangles[i].set_fill(color_palette[i%len(color_palette)], opacity=0.5)

self.play(
*map(lambda obj: ShowCreation(obj, run_time=1), arcs),
*map(lambda obj: ShowCreation(obj, run_time=1), lines),
)
self.play(
*map(lambda i: Transform(arcs[i], arcs2[i], runtime=1), range(n_elements)),
*map(lambda obj: FadeIn(obj, run_time=1), triangles),

)

self.wait()
weights = np.random.rand(n_elements)
weights /= weights.sum()
angles = weights*np.pi*2
angles_offset = [0]+np.cumsum(weights*np.pi*2)[:-1].tolist()
arcs2 = [Arc(angles_offset[i], angles[i]) for i in range(n_elements)]
lines2 = [Line((0,0,0),
(radius*np.cos(angles_offset[i]), radius*np.sin(angles_offset[i]), 0))
for i in range(n_elements)]
triangles2 = [Polygon(*[
# first element
(radius*np.cos(angles_offset[i]), radius*np.sin(angles_offset[i]),0),
(0, 0, 0), # second element
# third element
(radius*np.cos(angles_offset[(i+1)%n_elements]),
radius*np.sin(angles_offset[(i+1)%n_elements]), 0)], stroke_width=0)
for i in range(n_elements)]

for i in range(n_elements):
arcs2[i].set_fill(color_palette[i%len(color_palette)], opacity=0.5)
triangles2[i].set_fill(color_palette[i%len(color_palette)], opacity=0.5)

self.play(
*map(lambda i: Transform(lines[i], lines2[i],
runtime=1), range(n_elements)),
*map(lambda i: Transform(arcs[i], arcs2[i],
runtime=1), range(n_elements)),
*map(lambda i: Transform(triangles[i], triangles2[i],
runtime=1), range(n_elements)),
)
self.wait(2)

输出:
out
因此,我当前的程序有两个问题。我会很感激一点帮助。
1. 由于我使用的是三角形和圆弧,因此您可以在下图中看到一个难看的间隙。
image
2. 我正在使用 Arc 进行丑陋的转换, TriangeLine类,转换应该遵循圆周,现在不是这种情况。您可以在下图中欣赏更多中间丑陋步骤之一。 (如你所见,它不再是圆形的了)
image

最佳答案

对于第一个问题,避免通过精确排列单独的形状来创建形状。事实上,完全避免完全排列单独的形状:图形渲染引擎通常 have trouble rendering such situations .不是从圆形线段和三角形中创建一个圆形扇区,而是创建一个单一的形状来表示将作为单个单元绘制的整个扇区。在这种情况下,请使用 Sector类来表示扇区而不是单独的 ArcPolygon .
对于第二个问题,问题是默认 manim逐点计算中间形状。插值行为由形状的 interpolate 控制方法。通过对形状进行子类化,您可以覆盖 interpolate方法,而是根据定义形状的更自然的高级参数计算中间形状:在这种情况下,是中心、角度和半径。
这两个修复都包含在下面的示例中。

from manim import *
import numpy as np

class MySector(Sector):
""" Circular sector shape with a custom interpolation method. """

def interpolate(self, mobject1, mobject2, alpha, path_func=straight_path):
if not (isinstance(mobject1, MySector) and isinstance(mobject2, MySector)):
return super().interpolate(mobject1, mobject2, alpha, path_func=path_func)

for attr in (
'start_angle', 'angle',
'inner_radius', 'outer_radius',
):
v1 = getattr(mobject1, attr)
v2 = getattr(mobject2, attr)
setattr(self, attr, path_func(v1, v2, alpha))

self.arc_center = path_func(
mobject1.get_arc_center(),
mobject2.get_arc_center(),
alpha
)
self.interpolate_color(mobject1, mobject2, alpha)
self.clear_points()
self.generate_points()
return self


color_palette = [BLUE, GREEN, YELLOW, GREY_BROWN]

class TestPie(Scene):
def construct(self):
weights = np.array([2.0, 3.0, 4.0])
weights /= weights.sum()

angles = weights * TAU
angles_offset = np.cumsum((0, *angles[:-1]))

sectors1 = [
MySector(start_angle=ao, angle=a,
stroke_width=DEFAULT_STROKE_WIDTH,
fill_opacity=0)
for ao, a in zip(angles_offset, angles)
]

sectors2 = [
MySector(start_angle=ao, angle=a,
stroke_width=DEFAULT_STROKE_WIDTH,
fill_color=color_palette[i % len(color_palette)], fill_opacity=0.5)
for i, (ao, a) in enumerate(zip(angles_offset, angles))
]

self.play(
*(ShowCreation(a1, run_time=1) for a1 in sectors1)
)

self.play(
*(Transform(a1, a2, runtime=1) for (a1, a2) in zip(sectors1, sectors2))
)

self.wait()

weights = np.array([4.0, 3.0, 2.0])
weights /= weights.sum()

angles = weights * TAU
angles_offset = np.cumsum((0, *angles[:-1]))

sectors2 = [
MySector(start_angle=ao, angle=a,
stroke_width=DEFAULT_STROKE_WIDTH,
fill_color=color_palette[i % len(color_palette)], fill_opacity=0.5)
for i, (ao, a) in enumerate(zip(angles_offset, angles))
]

self.play(
*(Transform(a1, a2, runtime=1) for (a1, a2) in zip(sectors1, sectors2))
)
self.wait(2)
这是由此产生的动画:
animation
以上不保留构成饼图扇区的线条的初始绘制动画。您可以覆盖 pointwise_become_partial恢复它的方法,或者您可以简单地恢复 Line原始代码中的形状。

关于python - 如何使用 manim 创建正确的饼图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65783858/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com