r"""
Peano's space-filling curve
=================================

Peano's 1890 curve divides the square into a :math:`3 \times 3` grid,
visits the nine cells in a serpentine order, and repeats the pattern
inside each cell. The order-:math:`n` approximation visits every cell of
a :math:`3^n \times 3^n` grid exactly once, so in the limit the
continuous curve passes through every point of the square. Here the
approximations are generated by the standard L-system rewriting rules
for Peano's curve and drawn with turtle graphics.
"""

# %%
import matplotlib.pyplot as plt
import numpy as np

from mathematicskit.fractals_chaos import lsystem, turtle_path

rules = {"X": "XFYFX+F+YFXFY-F-XFYFX", "Y": "YFXFY-F-XFYFX+F+YFXFY"}

# %%
# The first three approximations
# ------------------------------

fig, axes = plt.subplots(1, 3, figsize=(12, 4.2))
for order, ax in zip((1, 2, 3), axes):
    step = 1.0 / 3**order
    (path,) = turtle_path(lsystem("X", rules, order), angle=90.0, step=step, heading=90.0)
    path = path - path.min(axis=0) + step / 2
    ax.plot(path[:, 0], path[:, 1], lw=1.2 if order < 3 else 0.8)
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 1)
    ax.set_aspect("equal")
    ax.set_xticks(np.linspace(0, 1, 4))
    ax.set_yticks(np.linspace(0, 1, 4))
    ax.grid(True, lw=0.4)
    ax.set_title(f"order {order}: {3**order}x{3**order} grid")

    cells = {tuple(v) for v in np.floor(path / step).astype(int)}
    print(f"order {order}: {len(path)} points, {len(cells)} distinct cells of {9**order}")
fig.tight_layout()
