Generating Atlas Page Grids with Guaranteed Overlap

Derive the sheet overlap from the longest rendered label in the coverage rather than choosing a round number, because the overlap’s job is to guarantee that a feature crossing a boundary is fully readable on at least one page — and the length of its label is what determines whether that is true.

Core Algorithm and Workflow

A page grid is a lattice of sheet-sized rectangles over the coverage, stepped by less than a full sheet so that neighbours share a band. Three decisions make it correct:

The overlap floor. A feature whose label extends past a sheet edge is clipped there. If the neighbouring sheet’s extent begins exactly where the first ended, the label is clipped on that sheet too, and the feature is named nowhere. The overlap must therefore exceed the longest label’s ground extent — measured, not estimated.

Which cells to keep. Testing each cell against the coverage geometry rather than its bounding box removes the blank pages. On a coastal or irregular coverage this routinely removes a fifth of the volume.

The containment proof. Once the grid exists, assert it: every labelled point feature, together with its label box, must be fully inside at least one sheet. This is a cheap check and it converts the overlap from an assumption into a verified property.

The label that is readable on neither sheet Two pairs of adjacent sheets. In the first, the overlap is 2 millimetres and a long place name crossing the boundary is clipped on the left sheet and clipped on the right sheet, so it is fully readable on neither. In the second, the overlap is 9 millimetres, derived from the measured label extent, and the name appears complete on the right-hand sheet. overlap 2 mm — too small Kirkby L y Lonsdale clipped on both — readable on neither overlap 9 mm — derived Kirkby L Kirkby Lonsdale complete on the right-hand sheet overlap floor = longest label extent × 1.5, converted to ground units at the atlas scale The left-hand case passes every per-sheet check: each sheet clips at its own edge correctly. Only a cross-sheet assertion can see that the feature is named on neither page.
Two millimetres feels like a reasonable overlap when looking at one sheet. It is chosen by thinking about the map rather than about the longest place name in the dataset.

Production-Ready Python Implementation

from shapely.geometry import box


def overlap_floor(max_label_mm: float, scale_denominator: float,
                  safety: float = 1.5) -> float:
    """Ground-unit overlap guaranteeing the longest label fits on a neighbour."""
    if max_label_mm <= 0 or scale_denominator <= 0:
        raise ValueError("label extent and scale must be positive")
    return (max_label_mm / 1000.0) * scale_denominator * safety


def page_grid(coverage, sheet_w: float, sheet_h: float, overlap: float) -> list:
    """Regular lattice of sheet extents over a coverage polygon.

    Cells that do not intersect the coverage are dropped, so a coastal atlas
    does not print pages of open sea.
    """
    if overlap <= 0:
        raise ValueError("overlap must be positive; a zero overlap loses features")
    if overlap * 2 >= min(sheet_w, sheet_h):
        raise ValueError("overlap consumes the sheet — check the units")

    step_x, step_y = sheet_w - overlap, sheet_h - overlap
    minx, miny, maxx, maxy = coverage.bounds

    cells, y = [], miny
    while y < maxy:
        x = minx
        while x < maxx:
            cell = box(x, y, x + sheet_w, y + sheet_h)
            if cell.intersects(coverage):
                cells.append(cell)
            x += step_x
        y += step_y
    return cells


def assert_containment(cells, labelled_points, label_box_size: float) -> list:
    """Return features that no single sheet fully contains, label included."""
    orphans = []
    for pt in labelled_points:
        halo = pt.buffer(label_box_size / 2, cap_style=3)   # square envelope
        if not any(cell.contains(halo) for cell in cells):
            orphans.append(pt)
    return orphans

assert_containment deliberately takes point features only. A river or a motorway cannot be contained by one sheet and does not need to be — a line is continuous across an overlap by construction. Applying the assertion to every geometry type turns a useful check into one that always fails, and a check that always fails is quickly disabled.

Performance Tuning and Cartographic Best Practices

  • Measure the label extent with the real font. A character count times an average advance is wrong by a factor of two on strings full of capitals or narrow letters. Use the same font metrics the renderer will use — the approach set out in Typography Rules for Maps.
  • Treat the floor as a floor. Overlap costs pages: ten per cent on both axes is roughly twenty per cent more sheets, and every extra sheet is print cost and render time. Exceeding the derived floor buys nothing.
  • Prepare the coverage geometry once. The intersection test runs per cell, so simplify the coverage to the sheet scale and build a prepared geometry before the loop; on a detailed national outline this is the difference between seconds and minutes.
  • Recompute per scale in a mixed-scale atlas. The overlap floor is a ground distance derived from a page distance at a specific scale. An atlas with 1:25 000 town sheets and 1:100 000 rural sheets needs two floors.
  • Emit the page count before rendering. The overlap changes it, and a stakeholder discovering the volume grew from 380 to 460 pages after the render is a much worse conversation than before.
What each additional millimetre of overlap costs in pages Page count plotted against overlap as a fraction of sheet width, for a fixed coverage. At zero overlap the atlas is 342 pages, at the derived floor of 4 per cent it is 371, and at 15 per cent it is 474. The region beyond the floor is shaded and labelled as cost without benefit, since containment is already guaranteed at the floor. 300 400 500 pages overlap as a fraction of sheet width 0% 5% 10% 15% cost without benefit — containment already holds derived floor 371 pages A generous 15% overlap adds a hundred pages to the print run and guarantees nothing extra.
The curve is roughly linear in each axis and therefore quadratic overall, which is why an overlap chosen for comfort rather than from measurement is expensive.

Integration and Next Steps

The grid this produces is the input to sheet numbering and to the neighbour stamps described in Atlas and Map Series Automation, and the extent it assigns each sheet feeds the frame sizing from Map Layout and Composition Automation — which means a change to the legend changes the frame, which changes the sheet ground size, which changes the grid. Compute in that order, and treat the page count as an output of the whole chain rather than something set at the start.

Why the page count is the last thing decided, not the first A dependency chain. Legend content determines the marginalia width, which determines the map frame size, which with the atlas scale determines the sheet ground size, which with the overlap floor determines the page grid and therefore the page count. A note records that adding one legend class can move the page count. legend content frame size sheet ground size grid and page count overlap floor Adding one legend class narrows the frame, shrinks the sheet's ground coverage, and can add pages. Setting the page count first and working backwards inverts a chain that only runs one way.
Everything upstream of the page count is a content decision. That is why a promised page count made before the legend is final is a promise about something not yet determined.

Frequently Asked Questions

Why can the overlap not just be a round number like 5 mm?

Because what has to be guaranteed is a ground distance, and a page distance converts to a different ground distance at every scale. Five millimetres is 125 metres at 1:25 000 and 500 metres at 1:100 000. In a single-scale atlas a page-distance constant is workable once it has been derived from the longest label rather than chosen; in a mixed-scale atlas the ground overlap must be recomputed per scale, or the coarse sheets will drop features the fine sheets keep.

Does more overlap ever hurt?

In two ways. It costs pages — ten per cent on both axes is roughly twenty per cent more sheets, which is print cost, render time and binding thickness. And it increases the number of features appearing on more than one sheet, which increases the work the cross-sheet consistency pass has to do and the number of places an inconsistency can show. The derived floor is a floor; exceeding it does not make containment more guaranteed than guaranteed.

What about features larger than one sheet?

They cannot be contained and the assertion must not treat that as failure. A motorway or a river crosses many sheets by nature, and the property that matters for a linear feature is continuity across the boundary, which any positive overlap provides. Restrict the containment check to labelled point features and small polygons — those are the ones that can genuinely be lost between pages, and the ones the overlap exists to protect.

Should the grid follow the coverage shape or a regular lattice?

A regular lattice with empty cells dropped. A grid that follows the coverage outline produces sheets at irregular positions, which makes neighbour references awkward to compute and page numbering arbitrary to justify. The lattice keeps both trivial — a sheet’s neighbours are its lattice neighbours — and dropping cells that miss the coverage removes the only real cost, which is printing pages of empty sea.


Back to Atlas and Map Series Automation