Components¶
The Component class is the core element [1] of manim-eng, and all
circuit symbols are derived from it. It is therefore useful to understand what
functionality it provides you with. This is not a replacement for the API documentation,
but instead aims to give a more general overview of the wider family of components and
their functionality.
Setting labels and annotations¶
All components have two ways for setting labels and annotations: the
set_label() and set_annotation() methods, and the
label and annotation parameters to the components’ constructors.
Warning
Monopoles (components with one terminal) only support labels and not annotations. They will throw an error if you attempt to set an annotation.
class SettingLabelsAndAnnotations(Scene):
def construct(self):
r1 = Resistor(label="R_1", annotation=1 * KILO * OHM).shift(LEFT)
r2 = Resistor().set_label("R_2").set_annotation(1 * KILO * OHM).shift(RIGHT)
self.add(r1, r2)
Components also have clear_label() and
clear_annotation() methods for removing annotations. Of course, all of
these methods support animation overrides as well — let’s take a look at both of these
in action together.
class SettingLabelsAndAnnotations(Scene):
def construct(self):
r = Resistor()
self.add(r)
self.play(
r.animate.set_label("R"),
r.animate.set_annotation(1 * KILO * OHM),
)
self.wait()
self.play(
r.animate.set_label("R_1"),
r.animate.set_annotation(10 * KILO * OHM),
)
self.wait()
self.play(
r.animate.clear_label(),
r.animate.clear_annotation(),
)
self.wait()
Labels and annotations are additionally discussed further in the next section.
Setting terminal current labels¶
As alluded to in Your first circuit diagram, there are two ways to set the
current labels on terminals of a component. The first is to call the
set_current() method on the terminal, and the second is to call the
set_current() method on the component. As the second is a wrapper
around the first, we will focus on the first here — but this is all applicable to
both.
When setting a terminal current label, you have a few options, namely:
What the label should be (the
labelparameter);Which direction the autogenerated arrow should point (the
outparameter); andThe side of the terminal the label should be placed on (the
belowparameter).
You can provide any number of these parameters to any given call, as long as at least one is specified.
set vs reset¶
You may have noticed that, in addition to set_current(),
terminals also provide reset_current() (with components defining a
similarly named method). The difference between the two lies in how they handle
non-specified label positioning arguments:
resetwill reset any positioning not specified back to the defaults (arrows pointing into components and labels placed to the right of the terminal (as you look down it towards the end); andsetwill respect any previously set values, and only fall back to the default if no value has ever been set for that terminal.
Let’s take a look at an example to see what this means in practice.
class SetVsReset(Scene):
def construct(self):
r1 = Resistor(label=r"\mathrm{set}").shift(2 * LEFT)
r2 = Resistor(label=r"\mathrm{reset}").shift(2 * RIGHT)
self.add(r1, r2)
self.play(
r1.right.animate.set_current("I_1", out=True, below=True),
r2.right.animate.reset_current("I_2", out=True, below=True),
)
self.wait()
self.play(
r1.right.animate.set_current("i_1"),
r2.right.animate.reset_current("i_2"),
)
self.wait()
self.play(
r1.right.animate.clear_current(),
r2.right.animate.clear_current(),
)
self.wait()
We see that set just changed the current label, but reset changed everything
back to defaults.
Clearing terminal current labels¶
As you may have seen in the above example, terminal labels are cleared using
clear_current() (or the component equivalent
Component.clear_current()).
Accessing terminals¶
All components have a property called terminals, which is a list
of the component’s terminals. Regardless of component type, this list is always
available. However, components also define a few other properties that refer to this
terminal list depending on their type to make accessing terminals easier.
Monopoles¶
Monopoles (such as grounds) define the terminal property to refer to
their single available terminal. Using this is often not necessary, as methods that
take a Terminal as input also accept a Monopole (since it is
obvious which terminal is intended in that situation).
Bipoles¶
Bipoles (such as resistors, capacitors, etc.), define the left and
right properties, which refer to their left and right terminals (when
the bipole is unrotated).
Warning
These properties do not change with component orientation! If you rotate a bipole
through 180 degrees, then left will be on the right and vice versa.
There are a few further special cases, which define further terminals on top of left
and right — these are sources and diodes. They define the same set of properties,
but for the sake of providing API links to all of these properties, the full set is
tabulated below.
Component type |
Defined property |
Refers to |
|---|---|---|
The negative terminal of the source |
||
The positive terminal of the source |
||
The negative terminal of the diode (the terminal into which current cannot pass) |
||
The positive terminal of the source (the terminal into which current is allowed to pass) |
||
Aligning components¶
On top of Manim’s existing alignment methods, manim-eng provides
align_terminal() to align the terminal of a component to a point or
another component’s terminal. Let’s take a look at an example.
class AlignTerminal(Scene):
def construct(self):
r = Resistor().shift(UP * 1.5)
l = Inductor().shift(DOWN * 1.5).rotate(-45 * DEGREES)
self.add(r, l)
self.play(l.animate.align_terminal("left", r.right))
Monopoles¶
Since monopoles only have one terminal, it’s a bit annoying to have to tell
align_terminal() the terminal we mean. To overcome this, manim-eng
also provides align_monopole(), which offers identical functionality
but without requiring the terminal to be specified.
class AlignMonopole(Scene):
def construct(self):
r = Resistor().shift(UP * 1.5)
g = Ground().shift(DOWN * 1.5)
self.add(r, g)
self.play(g.animate.align_monopole(r.right))
Footnotes