Files
manim/active_projects/eop/reusables/upright_coins.py

132 lines
4.4 KiB
Python

from mobject.geometry import *
from mobject.svg.tex_mobject import *
from utils.color import *
from active_projects.eop.reusables.eop_helpers import *
from active_projects.eop.reusables.eop_constants import *
class UprightCoin(Circle):
# For use in coin sequences
CONFIG = {
"radius": COIN_RADIUS,
"stroke_width": COIN_STROKE_WIDTH,
"stroke_color": WHITE,
"fill_opacity": 1,
"symbol": "\euro"
}
def __init__(self, **kwargs):
Circle.__init__(self,**kwargs)
self.symbol_mob = TextMobject(self.symbol, stroke_color = self.stroke_color)
self.symbol_mob.set_height(0.5*self.get_height()).move_to(self)
self.add(self.symbol_mob)
class UprightHeads(UprightCoin):
CONFIG = {
"fill_color": COLOR_HEADS_COIN,
"symbol": "H",
}
class UprightTails(UprightCoin):
CONFIG = {
"fill_color": COLOR_TAILS_COIN,
"symbol": "T",
}
class CoinSequence(VGroup):
CONFIG = {
"sequence": [],
"radius" : COIN_RADIUS,
"spacing": COIN_SEQUENCE_SPACING,
"direction": RIGHT
}
def __init__(self, sequence, **kwargs):
VGroup.__init__(self, **kwargs)
self.sequence = sequence
offset = 0
for symbol in self.sequence:
if symbol == "H":
new_coin = UprightHeads(radius = self.radius)
elif symbol == "T":
new_coin = UprightTails(radius = self.radius)
else:
new_coin = UprightCoin(symbol = symbol, radius = self.radius)
new_coin.shift(offset * self.direction)
self.add(new_coin)
offset += self.spacing
class FlatCoin(UprightCoin):
# For use in coin stacks
CONFIG = {
"thickness": COIN_THICKNESS,
"foreshortening": COIN_FORESHORTENING,
"nb_ridges": COIN_NB_RIDGES
}
def __init__(self, **kwargs):
UprightCoin.__init__(self, **kwargs)
self.symbol_mob.rotate(TAU/8)
self.stretch_in_place(self.foreshortening, 1)
# draw the edge
control_points1 = self.points[12:25].tolist()
control_points2 = self.copy().shift(self.thickness * DOWN).points[12:25].tolist()
edge_anchors_and_handles = control_points1
edge_anchors_and_handles.append(edge_anchors_and_handles[-1] + self.thickness * DOWN)
edge_anchors_and_handles.append(edge_anchors_and_handles[-1] + self.thickness * UP)
edge_anchors_and_handles += control_points2[::-1] # list concatenation
edge_anchors_and_handles.append(edge_anchors_and_handles[-1] + self.thickness * UP)
edge_anchors_and_handles.append(edge_anchors_and_handles[-1] + self.thickness * DOWN)
edge_anchors_and_handles.append(control_points1[0])
#edge_anchors_and_handles = edge_anchors_and_handles[::-1]
edge = VMobject()
edge.set_points(edge_anchors_and_handles)
edge.set_fill(
color = self.fill_color,
opacity = self.fill_opacity
)
edge.set_stroke(width = self.stroke_width)
self.add(edge)
# draw the ridges
PI = TAU/2
dtheta = PI/self.nb_ridges
ridge_angles = np.arange(dtheta,PI,dtheta)
# add a twist onto each coin
ridge_angles += np.random.rand(1) * dtheta
# crop the angles that overshoot on either side
ridge_angles = ridge_angles[(ridge_angles > 0) * (ridge_angles < PI)]
ridge_positions = 0.5 * 2 * self.radius * np.array([
np.cos(theta) for theta in ridge_angles
])
ridge_color = interpolate_color(self.stroke_color, self.fill_color, 0.7)
for x in ridge_positions:
y = -(1 - (x/self.radius)**2)**0.5 * self.foreshortening * self.radius
ridge = Line(
x * RIGHT + y * UP,
x * RIGHT + y * UP + self.thickness * DOWN,
stroke_color = ridge_color,
stroke_width = self.stroke_width
)
self.add(ridge)
# redraw the unfilled edge to cover the ridge ends
empty_edge = edge.copy()
empty_edge.set_fill(opacity = 0)
self.add(empty_edge)
class FlatHeads(FlatCoin):
CONFIG = {
"fill_color": COLOR_HEADS_COIN,
"symbol": "H",
}
class FlatTails(FlatCoin):
CONFIG = {
"fill_color": COLOR_TAILS_COIN,
"symbol": "T",
}