geomotif.motifs.symmetry
¶
Point sets defined by a symmetry group and a rule about their distances.
Every other motif in this catalog says where its points are. This one says what has to be true of them -- that they fall into the orbits of a cyclic or dihedral group, and that neighbouring points sit the same distance apart -- and then solves for an arrangement that satisfies it.
The question it exists to answer is the one that sounds trivial and is not:
fifteen points, five-fold symmetry, every neighbour the same distance from the
last. Fifteen is not a multiple of ten, so the dihedral group D5 cannot
build it out of generic ten-point orbits alone; it needs one of those and one
five-point orbit sitting on the mirror lines. Which orbits are available, and
which counts they can add up to, is arithmetic the motif does for you --
:class:SymmetricPointSet refuses a count it cannot arrange and names the
nearest two it can.
Symmetry is preserved by construction rather than by the solver: relaxation moves one representative point per orbit, and the group carries the rest along. No amount of iteration can drift the figure off its own symmetry, and the result is exactly reproducible without a random seed anywhere.
.. warning::
This module is **experimental** -- the one place in the library where a
motif is solved for rather than evaluated. Its parameters and its output
may change in a minor release; see the API policy.
Classes:
| Name | Description |
|---|---|
SymmetricPointSet |
Points arranged by a symmetry group, spaced by iterative relaxation. |
SymmetricPointSet
dataclass
¶
SymmetricPointSet(count: int = 15, group: str = 'D5', radius: float = 120.0, relax: int = 200, connect: Connection = 'equal-distance', neighbors: int = 3, tolerance: float = 0.08, center: Point = (0.0, 0.0), *, merge: bool = False, show_nodes: bool = True)
Bases: SegmentMotif
Points arranged by a symmetry group, spaced by iterative relaxation.
The points are laid out in orbits -- sets the group carries onto
themselves. Under Cn an orbit holds n points; under Dn a
general orbit holds 2n and one sitting on the mirror lines holds
n. A single point at the center is fixed by either group, so a count
that is one more than a multiple of n gets one.
That is the whole constraint on count: it must be a multiple of the
group's order, or one more than one. Anything else cannot be arranged
symmetrically at all, and is refused with the nearest two counts that can.
Relaxation then equalizes the distances. Each orbit contributes one representative point, which is pushed away from neighbours closer than the mean nearest-neighbour distance and pulled toward those further away; the group replicates whatever it does. Because only representatives move, the figure cannot drift off its symmetry, and no random numbers are involved anywhere -- the same parameters always give the same points.
The relaxation is local, so it finds an even arrangement rather than
proving one. Most counts come out exactly equal; a few settle for a figure
that is well spread but not uniform, usually where two orbits of the same
size want the same radius. Raising relax does not rescue those -- they
are settled, not unfinished. This is the part of the motif that is still
experimental.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
count
|
int
|
How many points to place. |
15
|
group
|
str
|
|
'D5'
|
radius
|
float
|
Radius of the outermost point. The relaxed figure is scaled to this, so it is a size rather than a constraint on the solution. |
120.0
|
relax
|
int
|
Relaxation iterations. Zero returns the seeded rings untouched, which is worth looking at to see what the relaxation is doing. |
200
|
connect
|
('none', 'nearest', 'equal-distance', 'all-pairs')
|
What to draw between the points:
|
"none"
|
neighbors
|
int
|
How many neighbours each point is relaxed against, and how many
|
3
|
tolerance
|
float
|
How far above the shortest distance a pair may be and still count as equal, as a fraction of it. Relaxation converges rather than lands, so this is never zero. |
0.08
|
center
|
(float, float)
|
Middle of the figure. |
(0.0, 0.0)
|
Examples:
Methods:
| Name | Description |
|---|---|
orbit_sizes |
Return how many points each orbit holds, innermost first. |
orbit_sizes
¶
Return how many points each orbit holds, innermost first.