The Old Map Renderer, Explained

After reading this, you will understand how a plain GeoJSON boundary becomes a parchment map with hatched shores, why the hatching is the single most important trick, and how to feed the tool clean data so the result reads as genuinely old rather than merely brown.

What the tool does and one example

The Old Map Renderer takes geographic outlines and draws them the way a copper-plate engraver would have in the 1600s. You give it a polygon: the coast of an island, a lake, a county line, or a shape you draw by hand. It returns a single raster image with ink-colored outlines, hatched shorelines that fade into the sea, a faint graticule (the grid of latitude and longitude lines), and a compass rose.

Suppose you have a GeoJSON polygon for a small island, say a ring of 40 coordinate pairs spanning about 0.3 degrees of longitude and 0.2 degrees of latitude. Dropped straight into a modern viewer, that polygon is a flat gray blob with a crisp vector edge. The same polygon through this tool comes back on a cream field, its edge broken up by tiny random offsets so it looks hand-inked, with four or five parallel strokes hugging the coast on the water side, each fainter than the last. That fading band of strokes is what your eye reads as "sea near land", and it is the difference between a map that looks old and a map that looks like a clip-art continent tinted sepia.

When to use it, and when not

Use it when you want a decorative or illustrative map and you already have the geometry. Good inputs include a country or region boundary from a public dataset, a hiking area you have traced, a fictional coastline for a game, or a lake outline for a book plate. The output is a poster or an illustration, not a navigation aid.

Do not use it when position accuracy matters. The tool deliberately adds random jitter to every outline, so a point that was at exactly -4.1830, 55.9000 may render two or three pixels off. That is invisible on a poster and fatal on a survey. It is also not a projection engine in the cartographic sense: it draws your coordinates on a flat canvas, so very large areas (a whole hemisphere) will look stretched near the top and bottom.

If your goal is to read coordinates off the finished image, stop. The jitter and the flat drawing both destroy sub-pixel accuracy. Keep the source GeoJSON and treat the render as artwork only.

The geometry behind the hatching

The visual heart of the tool is the offset. Given the coastline polygon, the renderer builds a series of curves that sit a fixed distance out to sea, then draws short strokes along them. Each offset ring is pushed outward by a step, and each is drawn with less ink than the one before.

o_i = i \cdot d, \quad i = 1, 2, \dots, n

Here o_i is the distance of the i-th hatching ring from the coast, d is the spacing between rings (the hatching density control sets this), and n is the number of rings. If d = 3 pixels and n = 5, the rings sit at 3, 6, 9, 12 and 15 pixels out.

The opacity of each ring falls off so the band fades into the open water. A simple linear fade sets the ink for ring i as:

\alpha_i = \alpha_0 \left(1 - \frac{i}{n+1}\right)

\alpha_0 is the darkest opacity (the ring touching the coast), and n is the ring count again. With \alpha_0 = 0.8 and n = 5, the five rings get opacities 0.667, 0.533, 0.4, 0.267 and 0.133. The last ring is barely visible, which is exactly the effect the engravers wanted: the hatching should dissolve, not stop dead.

The jitter that fakes a hand

A vector edge is too perfect. To break it, each point on every stroke is nudged by a small random amount before it is drawn.

p' = p + (\epsilon_x, \epsilon_y), \quad \epsilon \sim \text{Uniform}(-j, +j)

p is the original point, p' is the drawn point, and j is the jitter amplitude in pixels. If j = 1.5, every coordinate moves somewhere in a 3-by-3 pixel box, uniformly. The average displacement magnitude for uniform jitter of amplitude j is about 0.52 \cdot j, so at j = 1.5 the typical point moves roughly 0.78 pixels. Small, but enough to kill the machine-straight look.

The random draws come from a fixed seed per render. That is what makes the tool reproducible: the same GeoJSON with the same settings gives you the same wobble every time, so you can re-export a poster and get a pixel-identical file.

Reproducing the demo

Click the demo button. It renders with the field defaults, so you can follow the numbers below on your own screen. Assume the defaults are hatching spacing d = 3 px, ring count n = 5, base opacity \alpha_0 = 0.8, and jitter j = 1.5 px.

  1. The coastline polygon is read and its vertices are jittered by up to 1.5 px each, giving the inked-by-hand edge.
  2. Five offset rings are computed at 3, 6, 9, 12 and 15 px seaward of the coast.
  3. Each ring is stroked with opacity 0.667, 0.533, 0.4, 0.267, 0.133 from inner to outer.
  4. The parchment fill, graticule and compass rose are drawn underneath and around, and the whole canvas is exported as PNG.

If you count the shore strokes on the demo output, you should see five bands, the outermost one only just perceptible against the sea fill. That matches the fade table exactly.

The five default rings and their opacities. The band fades linearly to near zero, so it dissolves into the sea rather than ending abruptly.

With ring count n = 5 and base opacity 0.8, the rings fade as 0.667, 0.533, 0.4, 0.267, 0.133. Raising the ring count to 10 halves the spacing between opacity steps and widens the shaded band; lowering it to 3 gives a thick, hard-edged shore.

Reading and tuning the result

The controls trade three qualities against each other: age, legibility and ink weight.

Sepia depth
How brown the parchment and ink are. Higher depth reads as older but reduces contrast, so fine labels get harder to see.
Edge staining
Darkening and mottling toward the paper edges, mimicking handling and damp. Heavy staining can swallow coastline near the margins, so keep your subject centered.
Hatching density
The spacing d and ring count n. Dense hatching (small d, large n) suits detailed coasts; a rugged fjord needs finer strokes than a smooth atoll.
Sea fill
The decorative tint or texture behind the hatching. A strong fill competes with the outermost, faintest rings, so if the fade looks like it stops early, lighten the sea rather than adding more rings.

Common mistakes

The most frequent problem is feeding the tool the wrong geometry. A GeoJSON FeatureCollection full of points (cities, say) has no polygon to hatch, so you get labels floating on blank parchment. The tool wants closed rings: Polygon or MultiPolygon, or a LineString you close yourself.

The second is coordinate order. GeoJSON stores positions as [longitude, latitude], not [latitude, longitude]. If your map comes out rotated or mirrored, your pairs are almost certainly swapped. A point meant for 55.9 N, 4.2 W must appear as [-4.2, 55.9].

The third is scale. A polygon with only four vertices for a whole coastline gives a blocky shape that jitter cannot rescue. Give the renderer enough vertices that the natural coastline shape is already present, then let the jitter add the tremor.

Validate and preview your GeoJSON in the plain viewer first. If it shows the right shape there, the render will use the same coordinates, just dressed up.

Related tools on this site

Prepare and check your data before you render. The GeoJSON & CSV Map Viewer confirms your geometry is valid and correctly oriented. If your coordinates arrived as DMS strings or UTM, the Coordinate Converter turns them into the decimal degrees the renderer expects. For map-making curiosity beyond decoration, the Great Circle vs Rhumb Line tool explains why old straight-bearing routes curve on a globe, and the Antipode Finder is a fun way to pick a spot on the far side of the Earth to render next.

Frequently asked questions

Does my GeoJSON get uploaded anywhere?

No. Everything renders on a canvas in your browser. The file is read locally and never sent to a server.

Why does the same input always produce the same map?

The random jitter uses a fixed seed per render. Identical input plus identical settings gives an identical PNG, so you can re-export and get the same file byte for byte.

Can I make a map of a fictional place?

Yes. Draw a coastline with the built-in pen, or write your own GeoJSON polygon with made-up coordinates. The tool does not check that the geometry corresponds to a real location.

What resolution is the export?

It exports a high-resolution PNG suitable for posters and print. If a printed edge looks soft, increase the canvas size before exporting rather than scaling the PNG up afterward, which only blurs the ink.

My coast has no hatching. What happened?

You almost certainly gave it points or an unclosed line instead of a polygon. Close the ring or convert to a Polygon, then the offset rings have an edge to follow.