refactor image rendering script
This commit is contained in:
parent
d9337616db
commit
6ddfa44cf9
@ -1,389 +1,367 @@
|
|||||||
|
import itertools
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Iterable
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from numpy.typing import NDArray
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
root3 = 0.5 - (3**0.5) / 2j
|
root3 = 0.5 - (3**0.5) / 2j
|
||||||
triangle_coords = lambda i: (i[0] + i[1] * root3.real, i[1] * root3.imag)
|
embed_triangular = lambda i: (i[0] + i[1] * root3.real, i[1] * root3.imag)
|
||||||
|
|
||||||
|
|
||||||
def hex_positions(n):
|
def plot_triangular(plottype="plot"):
|
||||||
|
"""
|
||||||
|
Plot an iterable of coordinates in a triangular grid using the member `plottype` of `pyplot`.
|
||||||
|
Coordinates are in the form `(x, y)`.
|
||||||
|
Extra arguments are passed to the plotting method.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def ret(coords: Iterable[tuple[int, int] | NDArray], *args, **kwargs):
|
||||||
|
getattr(plt, plottype)(
|
||||||
|
*list(zip(*map(embed_triangular, coords))), *args, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def hex_positions(n: int, offset: int = 0) -> list[tuple[int, int]]:
|
||||||
|
"""
|
||||||
|
List of coordinates which, in a triangular lattice, form the vertices of hexagons.
|
||||||
|
|
||||||
|
The points (1, 1), (3, 0), and (0, 3) are all at the center of hexagons,
|
||||||
|
so linear combinations of these are NOT part of the grid.
|
||||||
|
"""
|
||||||
coordinates = [
|
coordinates = [
|
||||||
(i, j) for i in range(n) for j in range(n) if i + j < n and (i - j) % 3
|
(i + offset, j + offset)
|
||||||
|
for i in range(n)
|
||||||
|
for j in range(n)
|
||||||
|
if i + j < n and (i - j) % 3 != 0
|
||||||
]
|
]
|
||||||
drawing = [(i + j * root3.real, j * root3.imag) for (i, j) in coordinates]
|
return coordinates
|
||||||
return list(zip(*drawing))
|
|
||||||
|
|
||||||
|
|
||||||
def hex_lines(n):
|
def draw_hex_lines(n: int, offset: int = 0):
|
||||||
# vertices of hexagons in rightmost third of the the upper half plane
|
# vertices of hexagons in rightmost third of the the upper half plane
|
||||||
coordinates = [
|
hex_coordinates = hex_positions(n, offset)
|
||||||
(i, j) for i in range(n) for j in range(n) if i + j < n and (i - j) % 3
|
|
||||||
]
|
|
||||||
# find connections between a vertex and its (up to 3) neighbors
|
# find connections between a vertex and its (up to 3) neighbors
|
||||||
lines = [
|
lines = [
|
||||||
filter(
|
list(
|
||||||
lambda x: x[1] in coordinates,
|
itertools.chain.from_iterable(
|
||||||
[[(i, j), (i + 1, j)], [(i, j), (i, j + 1)], [(i, j), (i + 1, j - 1)]],
|
zip(
|
||||||
|
# the point being considered
|
||||||
|
itertools.repeat((i, j)),
|
||||||
|
# its neighbors which exist in the grid
|
||||||
|
filter(
|
||||||
|
lambda x: x in hex_coordinates,
|
||||||
|
[
|
||||||
|
(i + 1, j),
|
||||||
|
(i, j + 1),
|
||||||
|
(i + 1, j - 1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
for (i, j) in coordinates
|
for i, j in hex_coordinates
|
||||||
]
|
]
|
||||||
for line in lines:
|
for line in lines:
|
||||||
for unfiltered in line:
|
# draw lines between connected points
|
||||||
plt.plot(*list(zip(*map(triangle_coords, unfiltered))), "ko-")
|
plot_triangular("plot")(line, "ko-")
|
||||||
# flat_drawing = [map(triangle_coords, unzip) for line in lines for unzip in line]
|
|
||||||
# return list(zip(*flat_drawing))
|
|
||||||
# for i in flat_drawing:
|
|
||||||
# plt.plot(*list(zip(*i)), "k")
|
|
||||||
|
|
||||||
|
|
||||||
def triangular_grid(n, show_hexes=False):
|
def draw_triangular_grid(n: int, offset: int = 0, show_hexes: bool = False):
|
||||||
coordinates = [(i, j) for i in range(n) for j in range(n) if i + j < n]
|
plot_triangular("triplot")(
|
||||||
drawing = [(i + j * root3.real, j * root3.imag) for (i, j) in coordinates]
|
[(i + offset, j + offset) for i in range(n) for j in range(n) if i + j < n],
|
||||||
# plt.plot(*list(zip(*drawing)), "o")
|
"-",
|
||||||
plt.triplot(*list(zip(*drawing)), "-", color="0.7", lw=0.75)
|
color="0.7",
|
||||||
|
lw=0.75,
|
||||||
|
)
|
||||||
if show_hexes:
|
if show_hexes:
|
||||||
# plt.plot(*hex_positions(n), "ok")
|
draw_hex_lines(n, offset=offset)
|
||||||
hex_lines(n)
|
|
||||||
plt.gca().axis("off")
|
plt.gca().axis("off")
|
||||||
plt.xlim((-2, (1920 / 1080) * plt.ylim()[1]))
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
class Triangle:
|
||||||
def color_at_hex_coordinates(coord):
|
def __init__(
|
||||||
draw = None
|
self,
|
||||||
if min(coord) == 0: #class 1
|
left: tuple[int, int] | NDArray,
|
||||||
#(0,1) = (1,0) => (2,1), (1,2), (2, 2)
|
right: tuple[int, int] | NDArray,
|
||||||
#(0,2) = (2,0) => (3,2), (2,3), (3, 3)
|
top: tuple[int, int] | NDArray,
|
||||||
big = max(coord)
|
):
|
||||||
draw = [(big, big+1), (big+1, big), (big+1, big+1)]
|
self.left = np.array(left)
|
||||||
#plt.fill([big, big+1, big+1], [big, big, big+1],"r")
|
self.right = np.array(right)
|
||||||
elif (coord[0] == coord[1]): #class 2
|
self.top = np.array(top)
|
||||||
#(1,1) => (2,0) |+| (1,1)
|
|
||||||
#(2,2) => (3,1) |+| (1,1)
|
|
||||||
#(n,n) => (n+1,n-1) |+| (1,1)
|
|
||||||
big = coord[0]
|
|
||||||
draw = [(big+1, big-1), (big+1, big), (big+2, big-1)]
|
|
||||||
#plt.fill([big+1, big+2, big+1], [big-1, big-1, big],"r")
|
|
||||||
else:
|
|
||||||
#choose one enantiomer
|
|
||||||
#(2,1) => [(3, 1), (3, 2), (4, 1)]
|
|
||||||
#(3,1) => [(4, 2), (3, 2), (4, 1)]
|
|
||||||
#(a,b) => [(a+1, b), (a+1, b+1), (a+2, b)]
|
|
||||||
a,b = coord
|
|
||||||
draw = [(a+1, b), (a+1, b+1), (a+2, b)]
|
|
||||||
|
|
||||||
plt.fill(*list(zip(*map(triangle_coords, draw))), "r")
|
def __iter__(self):
|
||||||
"""
|
yield self.left
|
||||||
|
yield self.right
|
||||||
|
yield self.top
|
||||||
|
yield self.left
|
||||||
|
|
||||||
|
|
||||||
def identify_triangles(coord, offset=0, point=True, fill_all=False, path=False):
|
def draw_class_i(a: int, fill_all: bool = False):
|
||||||
# (a,b) specifies coordinates to the center of a hexagon
|
"""
|
||||||
# (a,a) is the first hexagon for turning
|
Plot a Class I Goldberg-Coxeter sector with parameter (a, 0)
|
||||||
# (2b, -b) is the length of the path after the 60 degree turn, meaning
|
"""
|
||||||
# (a+2b, a-b) is the center of the hexagon
|
origin = Triangle(
|
||||||
a, b = coord
|
left=(0, 0),
|
||||||
if a != b and min(coord) > 0 and offset == 0:
|
right=(1, 0),
|
||||||
offset = a - b
|
top=(0, 1),
|
||||||
# origin
|
)
|
||||||
plt.fill(
|
plot_triangular("fill")(origin, "r")
|
||||||
*list(
|
|
||||||
zip(
|
terminal = Triangle(
|
||||||
*map(
|
right=(a, a),
|
||||||
triangle_coords,
|
left=(a - 1, a),
|
||||||
[(offset, offset), (offset + 1, offset), (offset, offset + 1)],
|
top=(a, a - 1), # actually the bottom
|
||||||
)
|
)
|
||||||
)
|
plot_triangular("fill")(terminal, "b")
|
||||||
),
|
|
||||||
"r",
|
bottom_sector = Triangle(
|
||||||
|
left=origin.left,
|
||||||
|
right=(a, 0),
|
||||||
|
top=(0, a),
|
||||||
|
)
|
||||||
|
top_sector = Triangle(
|
||||||
|
left=(0, a),
|
||||||
|
right=terminal.right,
|
||||||
|
top=(a, 0),
|
||||||
)
|
)
|
||||||
|
|
||||||
# control point
|
# outline sector
|
||||||
if point:
|
plot_triangular("plot")(
|
||||||
plt.plot(*triangle_coords((a + offset, b + offset)), "bo")
|
[
|
||||||
|
origin.top,
|
||||||
|
origin.right,
|
||||||
|
bottom_sector.right,
|
||||||
|
terminal.top,
|
||||||
|
terminal.left,
|
||||||
|
bottom_sector.top,
|
||||||
|
origin.top,
|
||||||
|
],
|
||||||
|
color="0.25",
|
||||||
|
lw=2,
|
||||||
|
)
|
||||||
|
|
||||||
c, d = (a - offset + 2 * (b + offset), a - b + offset)
|
if fill_all:
|
||||||
if min(coord) == 0:
|
plot_triangular("fill")(bottom_sector, "r")
|
||||||
# upside-down triangle
|
plot_triangular("fill")(top_sector, "b")
|
||||||
triangle = [(c, d), (c - 1, d), (c, d - 1)]
|
|
||||||
# terminal
|
|
||||||
plt.fill(*list(zip(*map(triangle_coords, triangle))), "b")
|
|
||||||
|
|
||||||
if fill_all:
|
|
||||||
plt.fill(
|
|
||||||
*list(
|
|
||||||
zip(
|
|
||||||
*map(
|
|
||||||
triangle_coords,
|
|
||||||
[
|
|
||||||
(offset, offset),
|
|
||||||
(offset + a, offset),
|
|
||||||
(offset, offset + a),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"r",
|
|
||||||
)
|
|
||||||
plt.fill(
|
|
||||||
*list(
|
|
||||||
zip(
|
|
||||||
*map(
|
|
||||||
triangle_coords,
|
|
||||||
[
|
|
||||||
(offset, offset + a),
|
|
||||||
(offset + a, offset),
|
|
||||||
(offset + a, offset + a),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"b",
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
triangle = [(c, d), (c - 1, d), (c - 1, d + 1)]
|
|
||||||
# terminal
|
|
||||||
plt.fill(*list(zip(*map(triangle_coords, triangle))), "b")
|
|
||||||
# alternate terminal
|
|
||||||
c, d = (b - a + offset, b - offset + 2 * (a + offset))
|
|
||||||
triangle2 = [(c, d), (c, d - 1), (c + 1, d - 1)]
|
|
||||||
plt.fill(*list(zip(*map(triangle_coords, triangle2))), "g")
|
|
||||||
|
|
||||||
# lines connecting triangles
|
def draw_trapezoids(a: int):
|
||||||
plt.plot(
|
"""Draw trapezoidal regions in a Class II Goldberg-Coxeter sector"""
|
||||||
*list(
|
plot_triangular("fill")(
|
||||||
zip(
|
[(0, 0), (0, a), (a, a), (2 * a, 0)],
|
||||||
*map(
|
"r",
|
||||||
triangle_coords,
|
)
|
||||||
[
|
plot_triangular("fill")(
|
||||||
(offset + 1, offset),
|
[(0, a), (a, a), (a, 2 * a), (0, 3 * a)],
|
||||||
triangle[1],
|
"g",
|
||||||
triangle[2],
|
)
|
||||||
triangle2[2],
|
plot_triangular("fill")(
|
||||||
triangle2[1],
|
[(a, a), (a, 2 * a), (3 * a, 0), (2 * a, 0)],
|
||||||
(offset, offset + 1),
|
"b",
|
||||||
(offset + 1, offset),
|
)
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
color="0.25",
|
|
||||||
lw=2,
|
|
||||||
)
|
|
||||||
|
|
||||||
if fill_all and a == b:
|
|
||||||
# trapezoids
|
|
||||||
plt.fill(
|
|
||||||
*list(
|
|
||||||
zip(
|
|
||||||
*map(
|
|
||||||
triangle_coords,
|
|
||||||
[
|
|
||||||
(offset, offset),
|
|
||||||
(offset, offset + a),
|
|
||||||
(offset + a, offset + a),
|
|
||||||
(offset + 2 * a, offset),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"r",
|
|
||||||
)
|
|
||||||
plt.fill(
|
|
||||||
*list(
|
|
||||||
zip(
|
|
||||||
*map(
|
|
||||||
triangle_coords,
|
|
||||||
[
|
|
||||||
(offset, offset + a),
|
|
||||||
(offset + a, offset + a),
|
|
||||||
(offset + a, offset + 2 * a),
|
|
||||||
(offset, offset + 3 * a),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"g",
|
|
||||||
)
|
|
||||||
plt.fill(
|
|
||||||
*list(
|
|
||||||
zip(
|
|
||||||
*map(
|
|
||||||
triangle_coords,
|
|
||||||
[
|
|
||||||
(offset + a, offset + a),
|
|
||||||
(offset + a, offset + 2 * a),
|
|
||||||
(offset + 3 * a, offset),
|
|
||||||
(offset + 2 * a, offset),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"b",
|
|
||||||
)
|
|
||||||
|
|
||||||
elif fill_all == 1:
|
def draw_classes_ii_iii(parameter: tuple[int, int], fill_all: int):
|
||||||
plt.fill(
|
"""
|
||||||
*list(
|
Plot a Class II or III Goldberg-Coxeter sector with parameter (a, b)
|
||||||
zip(
|
|
||||||
*map(
|
|
||||||
triangle_coords,
|
|
||||||
[
|
|
||||||
(offset + 1, offset),
|
|
||||||
triangle[1],
|
|
||||||
triangle[2],
|
|
||||||
triangle2[2],
|
|
||||||
triangle2[1],
|
|
||||||
(offset, offset + 1),
|
|
||||||
(offset + 1, offset),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
color="0.4",
|
|
||||||
)
|
|
||||||
|
|
||||||
elif fill_all == 2:
|
Parameters where the second term is larger are NOT plotted correctly by fill_all.
|
||||||
# dark gray interior
|
"""
|
||||||
plt.fill(
|
# (a, b) specifies coordinates to the center of a hexagon
|
||||||
*list(
|
a, b = parameter
|
||||||
zip(
|
# (a, a) is the hexagon we turn at,
|
||||||
*map(
|
# (2b, -b) is the length of the path after the 60 degree turn, so
|
||||||
triangle_coords,
|
# (a+2b, a-b) is the center of the hexagon
|
||||||
[
|
w = a + 2 * b - 1
|
||||||
(offset + 1, offset),
|
l = a - b
|
||||||
triangle[1],
|
|
||||||
triangle[2],
|
# origin
|
||||||
triangle2[2],
|
origin = Triangle(
|
||||||
triangle2[1],
|
left=(0, 0),
|
||||||
(offset, offset + 1),
|
right=(1, 0),
|
||||||
(offset + 1, offset),
|
top=(0, 1),
|
||||||
],
|
)
|
||||||
)
|
plot_triangular("fill")(origin, "r")
|
||||||
)
|
|
||||||
),
|
# terminal triangle #1
|
||||||
|
terminal1 = Triangle(right=(w + 1, l), left=(w, l), top=(w, l + 1))
|
||||||
|
plot_triangular("fill")(terminal1, "b")
|
||||||
|
|
||||||
|
# terminal triangle #2
|
||||||
|
terminal2 = Triangle(top=(-l, w + l + 1), left=(-l, w + l), right=(-l + 1, w + l))
|
||||||
|
plot_triangular("fill")(terminal2, "g")
|
||||||
|
|
||||||
|
# lines connecting triangles
|
||||||
|
plot_triangular("plot")(
|
||||||
|
[
|
||||||
|
origin.top,
|
||||||
|
origin.right,
|
||||||
|
terminal1.left,
|
||||||
|
terminal1.top,
|
||||||
|
terminal2.right,
|
||||||
|
terminal2.left,
|
||||||
|
origin.top,
|
||||||
|
],
|
||||||
|
color="0.25",
|
||||||
|
lw=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
if fill_all:
|
||||||
|
if a == b:
|
||||||
|
draw_trapezoids(a)
|
||||||
|
else:
|
||||||
|
plot_triangular("fill")(
|
||||||
|
[
|
||||||
|
origin.top,
|
||||||
|
origin.right,
|
||||||
|
terminal1.left,
|
||||||
|
terminal1.top,
|
||||||
|
terminal2.right,
|
||||||
|
terminal2.left,
|
||||||
|
origin.top,
|
||||||
|
],
|
||||||
color="0.4",
|
color="0.4",
|
||||||
)
|
)
|
||||||
|
|
||||||
# lower parallelogram
|
# lower parallelogram
|
||||||
plt.fill(
|
plot_triangular("fill")(
|
||||||
*list(
|
[
|
||||||
zip(
|
origin.right,
|
||||||
*map(
|
(1, l),
|
||||||
triangle_coords,
|
terminal1.left,
|
||||||
[
|
terminal1.left + (0, -l),
|
||||||
(offset + 1, offset),
|
origin.right,
|
||||||
(offset + 1, offset + offset),
|
],
|
||||||
triangle[1],
|
|
||||||
(lambda x, y: (x, y - offset))(*triangle[1]),
|
|
||||||
(offset + 1, offset),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
color="xkcd:light red",
|
color="xkcd:light red",
|
||||||
)
|
)
|
||||||
|
|
||||||
# upper right parallelogram
|
# upper right parallelogram
|
||||||
plt.fill(
|
plot_triangular("fill")(
|
||||||
*list(
|
[
|
||||||
zip(
|
terminal1.top,
|
||||||
*map(
|
terminal1.top + (-l, 0),
|
||||||
triangle_coords,
|
terminal2.right,
|
||||||
[
|
terminal2.right + (l, 0),
|
||||||
triangle[2],
|
terminal1.top,
|
||||||
(lambda x, y: (x - offset, y))(*triangle[2]),
|
],
|
||||||
triangle2[2],
|
|
||||||
(lambda x, y: (x + offset, y))(*triangle2[2]),
|
|
||||||
triangle[2],
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
color="xkcd:light blue",
|
color="xkcd:light blue",
|
||||||
)
|
)
|
||||||
|
|
||||||
# upper left parallelogram
|
# upper left parallelogram
|
||||||
plt.fill(
|
plot_triangular("fill")(
|
||||||
*list(
|
[
|
||||||
zip(
|
terminal2.left,
|
||||||
*map(
|
terminal2.left + (l, -l),
|
||||||
triangle_coords,
|
origin.top,
|
||||||
[
|
origin.top + (-l, l),
|
||||||
triangle2[1],
|
terminal2.left,
|
||||||
(lambda x, y: (x + offset, y - offset))(*triangle2[1]),
|
],
|
||||||
(offset, offset + 1),
|
|
||||||
(0, offset + 1 + offset),
|
|
||||||
triangle2[1],
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
color="xkcd:light green",
|
color="xkcd:light green",
|
||||||
)
|
)
|
||||||
|
|
||||||
# center triangle
|
# center triangle
|
||||||
plt.fill(
|
plot_triangular("fill")(
|
||||||
*list(
|
[
|
||||||
zip(
|
(0, a - b),
|
||||||
*map(
|
(3 * b, a - b),
|
||||||
triangle_coords,
|
(0, a + 2 * b),
|
||||||
[
|
(0, a - b),
|
||||||
(offset, offset + offset),
|
],
|
||||||
(lambda x, y: (x - offset + 1, y - 1))(*triangle[2]),
|
|
||||||
(lambda x, y: (x + offset, y - offset + 1))(
|
|
||||||
*triangle2[1]
|
|
||||||
),
|
|
||||||
(offset, offset + offset),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
color="0.8",
|
color="0.8",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def draw_path(a: int, b: int):
|
||||||
|
plot_triangular("plot")(
|
||||||
|
[(i, i) for i in range(a + 1)],
|
||||||
|
marker="o",
|
||||||
|
color="xkcd:light red",
|
||||||
|
mfc="k",
|
||||||
|
lw=3,
|
||||||
|
)
|
||||||
|
plt.text(
|
||||||
|
*embed_triangular((a / 2 - 1, a / 2 + 1.5)),
|
||||||
|
f"a = {a}",
|
||||||
|
bbox={
|
||||||
|
"facecolor": "xkcd:light red",
|
||||||
|
"pad": 6,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
plot_triangular("plot")(
|
||||||
|
[(a + 2 * i, a - i) for i in range(b + 1)],
|
||||||
|
marker="o",
|
||||||
|
color="xkcd:light blue",
|
||||||
|
mfc="k",
|
||||||
|
lw=3,
|
||||||
|
)
|
||||||
|
plt.text(
|
||||||
|
*embed_triangular((a + b, a - b / 2 + 0.75)),
|
||||||
|
f"b = {b}",
|
||||||
|
bbox={
|
||||||
|
"facecolor": "xkcd:light blue",
|
||||||
|
"pad": 6,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def recenter_axes(a: int, b: int):
|
||||||
|
minx, maxx = plt.xlim()
|
||||||
|
miny, maxy = plt.ylim()
|
||||||
|
xspan = maxx - minx
|
||||||
|
yspan = maxy - miny
|
||||||
|
|
||||||
|
extent_x = a + 2*b + (a - b) * root3.real # rightward extent due to blue triangle
|
||||||
|
if a > b and min(a, b) != 0:
|
||||||
|
extent_x += -(a-b) + (1 + a-b) * root3.real # leftward extent due to green parallelogram
|
||||||
|
|
||||||
|
extent_y = (2 * max(a, b) + min(a, b)) * root3.imag
|
||||||
|
|
||||||
|
if min(a, b) == 0 or (extent_x * yspan / xspan) > extent_y:
|
||||||
|
span_diff = extent_x * yspan / xspan - extent_y
|
||||||
|
plt.xlim(-0.1, extent_x + 0.1)
|
||||||
|
plt.ylim(span_diff / 2, (extent_x + 0.2) * yspan / xspan + span_diff / 2)
|
||||||
|
else:
|
||||||
|
span_diff = extent_y * xspan / yspan - extent_x
|
||||||
|
# the figure extends below the y axis if a < b
|
||||||
|
if a >= b:
|
||||||
|
plt.ylim(-0.1, extent_y + 0.1)
|
||||||
|
else:
|
||||||
|
plt.ylim(
|
||||||
|
-extent_y / (2 * a + 1) - 0.1, extent_y * (1 - (1 / (2 * a + 1))) + 0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
plt.xlim(-span_diff / 2, (extent_y + 0.2) * xspan / yspan - span_diff / 2)
|
||||||
|
|
||||||
|
|
||||||
|
def draw_sector(parameter: tuple[int, int], fill_all: bool = False, path: bool = False):
|
||||||
|
"""
|
||||||
|
Draw a sector from the Goldberg-Coxeter construction with a certain `parameter`.
|
||||||
|
`offset` will translate the figure to the point `(offset, offset)` in a triangular plane.
|
||||||
|
`fill_all` controls whether the sector should be filled.
|
||||||
|
`path` controls whether to label the path described by `parameter`
|
||||||
|
"""
|
||||||
|
draw_triangular_grid(50, offset=-10, show_hexes=True)
|
||||||
|
# (a, b) specifies coordinates to the center of a hexagon
|
||||||
|
a, b = parameter
|
||||||
|
|
||||||
|
if min(parameter) == 0:
|
||||||
|
draw_class_i(max(parameter), fill_all)
|
||||||
|
else:
|
||||||
|
draw_classes_ii_iii(parameter, fill_all)
|
||||||
|
|
||||||
if path:
|
if path:
|
||||||
plt.plot(
|
draw_path(*parameter)
|
||||||
*list(
|
|
||||||
zip(
|
|
||||||
*map(
|
|
||||||
lambda x: triangle_coords((offset + x, offset + x)),
|
|
||||||
range(a + 1),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
marker="o",
|
|
||||||
color="xkcd:light red",
|
|
||||||
mfc="k",
|
|
||||||
lw=3,
|
|
||||||
)
|
|
||||||
plt.text(
|
|
||||||
*triangle_coords((offset + a / 2 - 1, offset + a / 2 + 1.5)),
|
|
||||||
f"a = {a}",
|
|
||||||
bbox={"facecolor": "xkcd:light red", "pad": 6},
|
|
||||||
)
|
|
||||||
|
|
||||||
plt.plot(
|
recenter_axes(*parameter)
|
||||||
*list(
|
|
||||||
zip(
|
|
||||||
*map(
|
|
||||||
lambda x: triangle_coords((offset + a + 2 * x, offset + a - x)),
|
|
||||||
range(b + 1),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
marker="o",
|
|
||||||
color="xkcd:light blue",
|
|
||||||
mfc="k",
|
|
||||||
lw=3,
|
|
||||||
)
|
|
||||||
plt.text(
|
|
||||||
*triangle_coords((offset + a + b, offset + a - b / 2 + 0.75)),
|
|
||||||
f"b = {b}",
|
|
||||||
bbox={"facecolor": "xkcd:light blue", "pad": 6},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
# if __name__ == "__main__":
|
||||||
triangular_grid(24, True)
|
# draw_triangular_grid(24, True)
|
||||||
# identify_triangles((4,2), point=False, path=True)
|
# # draw_sector((4,2), point=False, path=True)
|
||||||
identify_triangles((4, 2), offset=5, point=False, path=True)
|
# draw_sector((4, 2), offset=5, point=False, path=True)
|
||||||
plt.show()
|
# plt.show()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user