# Gallery

The following examples are a bit more involved and showcase the kind of drawings that can be done with Tesserax in the academic domain.

## Sorting

```{python}
from tesserax import Canvas, Square, Arrow, Group, Shape
from tesserax.layout import RowLayout

def create_pointer(target_shape: Shape, label_offset=40):
    """Helper to create a pointer arrow below a shape."""
    # We use the bottom anchor of the target shape
    base = target_shape.anchor("bottom")
    # Start the arrow lower down (dy) and point up to the shape
    tail = base.dy(label_offset)
    head = base.dy(5) # Stop 5px short of the shape
    return Arrow(tail, head)

with Canvas() as canvas:
    elements: list[Shape] = []

    # 1. The Array (Memory Strip)
    # We use a Row layout to pack squares automatically
    with RowLayout(gap=0) as array:
        for i in range(8):
            # Highlight the pivot (last element) with a different style
            is_pivot = (i == 7)
            s = Square(
                size=40,
                stroke="red" if is_pivot else "black",
                fill="#ffebeb" if is_pivot else "white"
            )
            elements.append(s)

    # 2. The Pointers (i and j)
    # We access the specific elements after the layout has settled
    ptr_i = create_pointer(elements[2]) # Pointing to index 2
    ptr_j = create_pointer(elements[5]) # Pointing to index 5

    # 3. Pivot Label (Curved arrow from top)
    pivot_shape = elements[-1]
    pivot_top = pivot_shape.anchor("top")

    # Create a visual indicator for the pivot
    pivot_arrow = Arrow(
        pivot_top.d(20, -30), # Top-right offset
        pivot_top.dy(-5)
    )

canvas.fit(padding=20).display()
```

## Automaton

This example uses a force layout to draw a simple graph that represents an automaton.

```{python}
import math
from tesserax import Canvas, Circle, Arrow
from tesserax.layout import HierarchicalLayout
from tesserax.core import Point

def get_boundary_point(center: Point, target: Point, radius: float) -> Point:
    """Calculates a point on the circle's boundary facing the target."""
    dx = target.x - center.x
    dy = target.y - center.y
    dist = math.sqrt(dx*dx + dy*dy)
    if dist == 0: return center

    # Normalize and scale by radius
    return Point(
        center.x + (dx / dist) * radius,
        center.y + (dy / dist) * radius
    )

with Canvas() as canvas:
    states: list[Shape] = []
    radius = 20

    # 1. Define the Graph Structure
    with HierarchicalLayout(orientation="horizontal") as graph:
        # Create 5 states
        for i in range(4):
            states.append(Circle(r=radius))

        # Connect them (Topology)
        # q0 -> q1 -> q2
        graph.connect(states[0], states[1])
        graph.connect(states[0], states[2])
        # q2 -> q0 (cycle)
        graph.connect(states[2], states[0])
        # q2 -> q3 -> q4
        graph.connect(states[2], states[3])
        # Set the root
        graph.root(states[0])

    # 2. Draw Transitions (Visuals)
    # We define edges manually to ensure directionality (ForceLayout is undirected)
    transitions = [(0, 1), (1, 2), (2, 0), (2, 3)]

    for i, j in transitions:
        src = states[i].anchor("center")
        dst = states[j].anchor("center")

        # Calculate points on the boundary of the circles
        p1 = get_boundary_point(src, dst, radius)
        p2 = get_boundary_point(dst, src, radius)
        Arrow(p1, p2)

    # 3. Add a "Start" arrow pointing to q0
    start_node = states[0].anchor("center")
    start_entry = get_boundary_point(start_node, start_node.dx(-100), radius)
    Arrow(start_entry.dx(-40), start_entry)

canvas.fit(padding=10).display()
```

## Stack

A simple illustration of a call stack.

```{python}
# examples/stack.py
from tesserax import Canvas, Rect, Arrow, Group
from tesserax.layout import ColumnLayout

with Canvas() as canvas:
    with ColumnLayout(align="middle", gap=2) as stack:
        # Stack frames
        for i in range(4):
            # Top frame is active (different color)
            stroke = "blue" if i == 0 else "black"
            Rect(100, 30, stroke=stroke)

    # Add a "Stack Pointer"
    top_frame = stack.shapes[0]
    sp_arrow = Arrow(
        top_frame.anchor("left").dx(-40),
        top_frame.anchor("left").dx(-5)
    )

canvas.fit(padding=20).display()
```

## Neural Networks

The following is a more complicated example showing how to visualize typical neural network operations like a convolution.

```{python}
from tesserax import Canvas, Square, Text, Arrow, Group, Shape
from tesserax.layout import GridLayout, RowLayout


def create_matrix(rows, cols, text, data=None, highlight_region=None, cell_size=40):
    """
    Creates a grid of squares with optional text and highlighting.
    """
    with GridLayout(cols=cols, gap=2) as grid:
        for r in range(rows):
            for c in range(cols):
                val = data[r][c] if data else 0

                # Determine styling based on the highlighted region
                is_active = False
                if highlight_region:
                    r_start, c_start, r_end, c_end = highlight_region
                    if r_start <= r <= r_end and c_start <= c <= c_end:
                        is_active = True

                # Visuals
                color = "#e3f2fd" if is_active else "white"
                stroke = "#1565c0" if is_active else "black"

                # A Group holding the box and the number
                with Group() as cell:
                    box = Square(cell_size, fill=color, stroke=stroke)
                    label = Text(str(val), size=14, font="monospace")

                cell.align()

    t = Text(text, size=16, anchor="middle")
    t.align_to(grid, anchor="bottom", other_anchor="top").translated(0, -10)

    # Return the group with these two elements
    return grid + t


with Canvas() as canvas:
    # Data Setup (Dummy Values)
    input_data = [[1 if i == j else 0 for j in range(5)] for i in range(5)]
    kernel_data = [[1, 0, 1], [0, 1, 0], [1, 0, 1]]
    output_data = [[2, 1, 2], [1, 3, 1], [2, 1, 2]]

    # We put three matrices in a row with the corresponding texts in between
    with RowLayout(gap=20):
        input_grid = create_matrix(
            5, 5, "Input (5x5)", input_data, highlight_region=(0, 0, 2, 2)
        )
        math_op = Text("∗", size=30)
        kernel_grid = create_matrix(
            3, 3, "Kernel (3x3)", kernel_data, highlight_region=(0, 0, 2, 2)
        )
        math_eq = Text("=", size=30)
        output_grid = create_matrix(
            3, 3, "Result (3x3)", output_data, highlight_region=(0, 0, 0, 0)
        )

canvas.fit(padding=40).display()
```
