This is a supplementary material to the submission Computing animations of linkages with rotational symmetry to Computational Geometry: Media Exposition - Zürich, Switzerland - June 23-26, 2020 by Sean Dewar, Georg Grasegger and Jan Legerský.

The submission contains a video of rotationally symmetric motions of bar-and-joint frameworks and this notebook. We illustrate how such motions can be created using SageMath package FlexRiLog (https://github.com/Legersky/flexrilog, https://doi.org/10.5281/zenodo.3078757 ).

A cell is executed with Shift+Enter or pressing Run button.

In [ ]:
import sys
sys.path.insert(0, "..") #this is necessary if flexrilog is not installed, only downloaded
from flexrilog import CnSymmetricFlexRiGraph, FlexRiGraph, GraphMotion, CnSymmetricNACcoloring


# A 5-fold rotationally symmetric graph¶

We consider the graph given by the following list of edges:

In [ ]:
edges = [(0, 1), (0, 2), (0, 4), (0, 14), (1, 2), (1, 11), (1, 12), (1, 15),
(1, 18), (1, 23), (1, 24), (2, 3), (2, 7), (3, 4), (3, 5), (3, 7),
(4, 5), (4, 14), (4, 15), (4, 16), (4, 17), (4, 20), (5, 6), (5, 10),
(6, 7), (6, 8), (6, 10), (7, 8), (7, 17), (7, 18), (7, 19), (7, 22),
(8, 9), (8, 13), (9, 10), (9, 11), (9, 13), (10, 11), (10, 19),
(10, 20), (10, 21), (10, 24), (11, 12), (12, 13), (12, 14), (13, 14),
(13, 16), (13, 21), (13, 22), (13, 23), (15, 16), (15, 18), (16, 23),
(17, 18), (17, 20), (19, 20), (19, 22), (21, 22), (21, 24), (23, 24)]
G5 = Graph(edges);
G5.plot()


The graph G5 is $C_n$-symmetric for $n=5$:

In [ ]:
omega5 = [[(0, 3, 6, 9, 12),
(1, 4, 7, 10, 13),
(2, 5, 8, 11, 14),
(15, 17, 19, 21, 23),
(16, 18, 20, 22, 24)]]
G5 = CnSymmetricFlexRiGraph(G5,
PermutationGroup(omega5),
pos={
0:[1,0],
1:[2.5,0],
2:[4,1.5],
15:[4,5],
16:[6,2]
}
)
G5.plot()


The graph G5 has three $C_5$-symmetric NAC-colorings:

In [ ]:
G5.show_all_NAC_colorings(ncols=1)


We consider the last NAC-coloring:

In [ ]:
delta5 = G5.NAC_colorings()[-1]
delta5.plot()


The construction in Theorem 2 yields a $C_5$-symmetric motion:

In [ ]:
M5 = GraphMotion.CnSymmetricGridConstruction(G5, delta5)
M5.animation_SVG(edge_partition='NAC', fileName='AnimationPentaRotation', totalTime=20, vertex_labels=False)


One can play with the choice of $a_i$'s and $b_j$'. There is only one orbit of red components and one orbit of blue components (and no partially invariant ones), so $a_i$'s and $b_j$' are determined each by one point:

In [ ]:
M5ab = GraphMotion.CnSymmetricGridConstruction(G5,
delta5,
a_base=[[2,2]], # a different point can be chosen here
b_base=[[1,0]]  # or here
)
M5ab.animation_SVG(edge_partition='NAC', fileName='AnimationPentaRotation_different_a_b',
totalTime=20, vertex_labels=False)


# A 3-fold rotationally symmetric graph¶

We consider the graph given by the following list of edges:

In [ ]:
edges3 = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 5), (1, 6), (2, 7), (2, 8),
(3, 4), (3, 9), (3, 10), (4, 11), (4, 12), (5, 6), (5, 7), (5, 13),
(6, 14), (6, 15), (7, 8), (7, 13), (8, 16), (8, 17), (9, 10), (9, 14),
(9, 18), (10, 12), (10, 20), (11, 12), (11, 16), (11, 19), (12, 20),
(13, 21), (13, 22), (14, 15), (14, 18), (15, 23), (15, 24), (16, 17),
(16, 19), (17, 25), (17, 26), (18, 23), (18, 27), (19, 25), (19, 28),
(20, 29), (20, 30), (21, 22), (21, 24), (21, 31), (22, 26), (22, 32),
(23, 24), (23, 27), (24, 31), (25, 26), (25, 28), (26, 32), (27, 29),
(27, 33), (28, 30), (28, 34), (29, 30), (29, 33), (30, 34), (31, 32),
(31, 35), (32, 35), (33, 34), (33, 35), (34, 35)]
G3 = Graph(edges3);
G3.plot()


The graph G3 is $C_n$-symmetric for $n=3$:

In [ ]:
omega3 = [[(0, 6, 9),
(1, 14, 3),
(2, 15, 10),
(4, 5, 18),
(7, 23, 12),
(8, 24, 20),
(13, 27, 11),
(16, 21, 29),
(19, 22, 33),
(17, 31, 30),
(25, 32, 34),
(26, 35, 28)]]
G3 = CnSymmetricFlexRiGraph(G3,
PermutationGroup(omega3),
pos={
0:[5,7],
1:[4,0],
2:[7,5],
4:[6,-3],
7:[8,8],
8:[10,-2],
13:[12,12],
16:[14,5],
19:[14,-12],
17:[18,1],
25:[20,-5],
26:[22,3],
}
)
G3.plot()


The graph G3 has 21 $C_3$-symmetric NAC-colorings:

In [ ]:
print(len(G3.NAC_colorings()))


We pick this one:

In [ ]:
delta3 = CnSymmetricNACcoloring(G3,
[[{5, 7}, {26, 22}, {5, 13}, {1, 2}, {27, 23}, {18, 27}, {29, 30}, {24, 31},
{33, 35}, {9, 10}, {9, 3}, {13, 7}, {11, 4}, {10, 3}, {20, 30}, {32, 22},
{11, 12}, {24, 21}, {0, 2}, {33, 34}, {14, 15}, {20, 29}, {0, 1}, {21, 31},
{19, 28}, {4, 12}, {25, 28}, {18, 23}, {6, 15}, {8, 16}, {25, 19}, {34, 35},
{6, 14}, {8, 17}, {32, 26}, {16, 17}],
[{17, 25}, {5, 6}, {1, 5}, {8, 2}, {33, 27}, {13, 22}, {18, 14}, {12, 20},
{8, 7}, {34, 28}, {35, 31}, {16, 19}, {3, 4}, {1, 6}, {13, 21}, {28, 30},
{10, 12}, {33, 29}, {9, 14}, {10, 20}, {0, 4}, {15, 23}, {25, 26}, {27, 29},
{32, 35}, {2, 7}, {16, 11}, {11, 19}, {32, 31}, {21, 22}, {34, 30}, {24, 23},
{9, 18}, {24, 15}, {17, 26}, {0, 3}]])
delta3.plot()


The construction in Theorem 2 yields a $C_3$-symmetric motion:

In [ ]:
M3 = GraphMotion.CnSymmetricGridConstruction(G3, delta3)
M3.animation_SVG(edge_partition='NAC',
fileName='AnimationTruncatedOctahedralLineGraph_FlexRiLoG',
totalTime=20,
vertex_labels=False)


One can play with the choice of $a_i$'s and $b_j$'. There are four orbits of red components and four orbits of blue components (and no partially invariant ones), so $a_i$'s and $b_j$' are determined each by four points:

In [ ]:
M3ab = GraphMotion.CnSymmetricGridConstruction(G3,
delta3,
a_base=[[0,1],[0,2],[3,0],[4,0]],   # different points can be chosen here
b_base=[[2,0], [3,1], [1,0], [4,0]] # or here
)
M3ab.animation_SVG(edge_partition='NAC',
fileName='AnimationTruncatedOctahedralLineGraph_FlexRiLoG_different_a_b',
totalTime=20,
vertex_labels=False)


Taking another NAC-coloring of G3, we obtain a different motion:

In [ ]:
delta3b = CnSymmetricNACcoloring(G3,
[[{5, 7}, {17, 25}, {1, 2}, {27, 23}, {18, 27}, {33, 27}, {13, 22}, {34, 30}, {9, 10},
{5, 13}, {11, 12}, {13, 7}, {11, 4}, {35, 31}, {10, 3}, {16, 19}, {9, 3}, {17, 26},
{0, 2}, {13, 21}, {14, 15}, {0, 1}, {33, 29}, {4, 12}, {25, 26}, {27, 29}, {32, 35},
{18, 23}, {6, 15}, {16, 11}, {11, 19}, {32, 31}, {21, 22}, {34, 28}, {28, 30}, {6, 14}],
[{26, 22}, {5, 6}, {1, 5}, {8, 2}, {9, 18}, {18, 14}, {20, 29}, {33, 35}, {29, 30},
{24, 31}, {12, 20}, {24, 23}, {20, 30}, {10, 20}, {32, 22}, {3, 4}, {24, 21}, {1, 6},
{33, 34}, {10, 12}, {9, 14}, {21, 31}, {19, 28}, {0, 4}, {15, 23}, {25, 28}, {0, 3},
{2, 7}, {8, 16}, {24, 15}, {25, 19}, {8, 7}, {34, 35}, {8, 17}, {32, 26}, {16, 17}]
])

M3anotherNAC = GraphMotion.CnSymmetricGridConstruction(G3, delta3b)
M3anotherNAC.animation_SVG(edge_partition='NAC',
fileName='AnimationTruncatedOctahedralLineGraph_FlexRiLoG_anotherNAC',
totalTime=20,
vertex_labels=False)

In [ ]: