Continuous Motions

It is possible to create continuous motions of frameworks in PyRigi.

Parametric Motion

The user can specify a parametric motion using the class ParametricMotion. As an example, consider the 4-cycle. A parametric motion can be specified using the following sequence of commands:

import sympy as sp

from pyrigi import graphDB as graphs
from pyrigi import ParametricMotion

motion = ParametricMotion(
    graphs.Cycle(4),
    {
        0: ("0", "0"),
        1: ("1", "0"),
        2: ("4 * (t**2 - 2) / (t**2 + 4)", "12 * t / (t**2 + 4)"),
        3: (
            "(t**4 - 13 * t**2 + 4) / (t**4 + 5 * t**2 + 4)",
            "6 * (t**3 - 2 * t) / (t**4 + 5 * t**2 + 4)",
        ),
    },
    [-sp.oo, sp.oo], # parameter interval
)
motion.animate()
../../_images/04ba30ce623d34df0c12bc8862d31bc70a209d0b98690b264e1045a728cbf199.svg

It is also possible to provide trivial motions in a similar manner. The animation can be formatted using some parameters from PlotStyle as keyword arguments.

motion = ParametricMotion(
    graphs.Complete(5),
    {
        0: ("cos(2*pi/5 + t)", "sin(2*pi/5 + t)"),
        1: ("cos(4*pi/5 + t)", "sin(4*pi/5 + t)"),
        2: ("cos(6*pi/5 + t)", "sin(6*pi/5 + t)"),
        3: ("cos(8*pi/5 + t)", "sin(8*pi/5 + t)"),
        4: ("cos(t)", "sin(t)")
    },
    [0, sp.sympify("2*pi")],
)
motion.animate(
    vertex_labels=False,
    edge_color='blue',
    edge_width=10,
)
../../_images/bb25754c27be44666c8e6052ec869c5a08fbc02076488236508562e1d40c72e3.svg

Internal checks on the edge lengths are in place to ensure that the specified parametric motion never violates the edge-length equations.

Finally, it is possible to create either a .svg animation or a matplotlib animation by setting the parameter animation_format to be either "svg" or "matplotlib". In doing so, the 2D and 3D animations can be displayed.

motion.animate(animation_format="matplotlib")

Approximate Motion

However, a parametric motion is not always available. If you still want to get an intuition for how a deformation path looks, it can be numerically approximated using the class ApproximateMotion. Since a numerical algorithm is used for creating the motion, a NumericalAlgorithmWarning is thrown. It can be turned off using the command ApproximateMotion.silence_numerical_alg_warns=True. As an example, consider the complete bipartite graph \(K_{4,2}\). A cyclic motion of \(K_{4,2}\) can be approximated using the following code:

from pyrigi.motion import ApproximateMotion
from pyrigi import frameworkDB as frameworks
ApproximateMotion.silence_numerical_alg_warns=True
F = frameworks.CompleteBipartite(2,4)
motion = ApproximateMotion(F, 393, chosen_flex=0, step_size=0.15)
motion.animate()
../../_images/41f25722026bd1ce4634f238978eea5a0391f27177efdba99c271f5e6023c906.svg

Only nontrivial motions can be computed in this way, so you don’t need to worry about approximating a trivial motion here.

Typically, only the origin is fixed during the animation sequence. If a (directed) edge is provided in the method animate() via the keyword fixed_pair, then it is possible to pin the first vertex of fixed_pair to the origin and the second vertex to the vector from the origin to the placement of the second vertex. Alternatively, this vector can be specified using the keyword fixed_direction.

F = frameworks.Path(5)
motion = ApproximateMotion(F, 147, chosen_flex=1, fixed_pair=[0,4], fixed_direction=[0,1])
motion.animate()
../../_images/70ebdb937a5e83920bbdb15f3ce6c77f5899ee29dd2b8a80216ebacfe01cc301.svg