Skip to content

Repository files navigation

CartoGo: Artistic City Map Poster Generator

Generate beautiful, minimalist map posters for any city in the world. CartoGo is a high-performance Go implementation of the original City Map Poster Generator, designed for speed, reliability, and 1-to-1 aesthetic parity.

banner

Credits & Attribution

This project is a high-performance Go port of the City Map Poster Generator (Python) by Ankur Gupta.

The Go implementation aims to preserve the artistic vision and functionality of the original while providing the speed and safety of the Go language. All themes and artistic design choices are credited to the original author.

Overview

CartoGo leverages OpenStreetMap data to create high-resolution (300 DPI) artistic posters. It fetches geographic features like roads, water bodies, and parks, then renders them using a custom engine built on the gg library to match the sophisticated look of the original Matplotlib-based project.

Features

  • Blazing Fast Rendering: Go's concurrency and the gg library provide significant performance gains for high-resolution output.
  • 1-to-1 Parity: Every detail, from road hierarchy to font spacing and gradient fades, has been meticulously ported.
  • High-Fidelity Typography:
    • Automatic script detection (Latin vs. Non-Latin).
    • Elegant letter-spacing for Latin scripts.
    • Dynamic font scaling to prevent long city names from truncating.
  • Advanced Caching:
    • OSM Data: Cached using Go's binary gob format for near-instant re-renders.
    • Geocoding: Caches Nominatim results to respect rate limits.
  • Smart Data Fetching:
    • Bounding-box queries with automatic radius compensation for different aspect ratios.
    • Robust retry logic for Overpass API server timeouts.

Installation

Prerequisites

Setup

git clone <repository-url>cd CartoGo
go mod tidy
go build -o CartoGo.exe

Usage

Basic Example

./CartoGo.exe -city "Paris" -country "France"

Advanced Multilingual Example

./CartoGo.exe -city "Tokyo" -country "Japan" -display-city "東京" -display-country "日本" -theme japanese_ink

CLI Reference

Required Flags

FlagShortDescription
-city-cCity name for geocoding.
-country-CCountry name for geocoding.

Optional Flags

FlagDescriptionDefault
-themeTheme name (matches JSON file in themes/).terracotta
-distanceMap radius in meters from center.18000
-latitudeManual latitude override.0
-longitudeManual longitude override.0
-display-cityCustom city name to display on poster.
-display-countryCustom country name to display on poster.
-country-labelAlias for -display-country.
-widthPhysical width in inches.12
-heightPhysical height in inches.16
-all-themesGenerate a poster for every theme in themes/.false
-list-themesList available themes with descriptions.false

Guides

Resolution & Print Guide (300 DPI)

Use these values for -width and -height to target specific outputs:

TargetInches (-width / -height)Resolution (px)
Instagram Post3.6 x 3.61080 x 1080
Mobile Wallpaper3.6 x 6.41080 x 1920
A4 Print8.3 x 11.72490 x 3510
A3 Print11.7 x 16.53510 x 4950
Large Poster18.0 x 24.05400 x 7200

Distance Selection

Radius (-distance)Best for...
4,000 - 6,000mSmall/dense centers (Venice, Amsterdam, Old Town Prague)
8,000 - 12,000mMedium cities or focused downtowns (Barcelona, SF, Paris)
15,000 - 20,000mLarge metropolises and ring roads (Tokyo, London, NYC)

Themes

The generator comes with 17 built-in themes in the themes/ directory, each carefully designed for a specific aesthetic:

ThemeNameAesthetic
autumnAutumnBurnt oranges, deep reds, golden yellows - seasonal warmth
blueprintBlueprintClassic architectural blueprint - technical drawing aesthetic
contrast_zonesContrast ZonesStrong contrast showing urban density - darker in center, lighter at edges
copper_patinaCopper PatinaOxidized copper aesthetic - teal-green patina with copper accents
emeraldEmerald CityLush dark green aesthetic with mint accents
forestForestDeep greens and sage tones - organic botanical aesthetic
gradient_roadsGradient RoadsSmooth gradient from dark center to light edges with subtle features
japanese_inkJapanese InkTraditional ink wash inspired - minimalist with subtle red accent
midnight_blueMidnight BlueDeep navy background with gold/copper roads - luxury atlas aesthetic
monochrome_blueMonochrome BlueSingle blue color family with varying saturation - clean and cohesive
neon_cyberpunkNeon CyberpunkDark background with electric pink/cyan - bold night city vibes
noirNoirPure black background with white/gray roads - modern gallery aesthetic
oceanOceanVarious blues and teals - perfect for coastal cities
pastel_dreamPastel DreamSoft muted pastels with dusty blues and mauves - dreamy artistic aesthetic
sunsetSunsetWarm oranges and pinks on soft peach - dreamy golden hour aesthetic
terracottaTerracottaMediterranean warmth - burnt orange and clay tones on cream
warm_beigeWarm BeigeEarthy warm neutrals with sepia tones - vintage map aesthetic

Technical Architecture

1. Data Pipeline

  1. Geocoding: Uses geocoding.go to hit Nominatim API. Results are cached locally.
  2. Radius Compensation: Calculates compensatedDist = distance * (maxDim / minDim) / 4.0 to ensure the map fills the frame regardless of orientation.
  3. Data Fetching: osm.go builds a complex Overpass QL query to fetch ways and relations (multipolygons) for water and parks.
  4. Caching: Uses cache.go to store OverpassResponse structs in GOB format, reducing subsequent render times from minutes to milliseconds.

2. Rendering Engine (rendering.go)

  • Projection: Converts Lat/Lon to a local meter-based coordinate system using the Haversine-adjacent projection.
  • Z-Order Management:
    1. Background Fill
    2. Water Polygons
    3. Park Polygons
    4. Roads (Sorted by Priority: Motorway > Primary > Secondary > Residential)
    5. Top/Bottom Gradient Fades (NRGBA for pure transparency)
    6. Typography Layers
  • Typography Logic:
    • Script Detection: Uses unicode package to detect Latin script prevalence.
    • Points-to-Pixels: Multiplies point sizes by DPI / 72.0 to ensure physical sizes match Python's Matplotlib output.

Hacker's Guide

Adding a Custom Theme

Create a .json file in themes/:

{
"name": "My Custom Theme",
"description": "Subtle description",
"bg": "#FFFFFF",
"text": "#000000",
"gradient_color": "#FFFFFF",
"water": "#D5D5D5",
"parks": "#EFEFEF",
"road_motorway": "#000000",
"road_primary": "#222222",
"road_secondary": "#444444",
"road_tertiary": "#666666",
"road_residential": "#888888",
"road_default": "#666666"
}

Modifying Road Hierarchy

Adjust getRoadPriority and getRoadStyle in rendering.go to change how different OSM highway tags are weighted and colored.

Extending the Map

To add new features (e.g., railways, buildings):

  1. Update the Overpass query in osm.go.
  2. Add a rendering loop in renderPoster (before roads).
  3. Define a new color field in the Theme struct in themes.go.

License

This project is licensed under the MIT License. See the LICENSE file for the full text.

About

Generate beautiful, minimalist map posters for any city in the world. CartoGo is a high-performance Go implementation of the original City Map Poster Generator, designed for speed, reliability, and 1-to-1 aesthetic parity.

Topics

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages