Skip to content

Repository files navigation

Inkline Maps

Inkline Maps renders local OpenStreetMap XML extracts into PNG and SVG images.

It runs offline and needs no tile server, network request, or runtime credential.

Value

Use one repeatable pipeline for local map previews and style experiments.

Change the plain-text style sheet without changing Kotlin code.

The sample extract shows water, roads, buildings, and labels.

The renderer assembles relation members into closed outer and inner rings.

The inner rings become holes in both PNG and SVG output.

Architecture

Part Responsibility
OSM parser Reads nodes, ways, relations, and tags with StAX.
Multipolygon assembler Joins relation way members into deterministic outer and inner rings.
Projection Maps coordinates with Web Mercator.
Style sheet Converts simple key-value rules into map colors and widths.
Renderer Draws ordered layers with Java2D or SVG elements.
Command line Selects input, style, and output paths.

The renderer draws water first, buildings second, roads third, and labels last.

The renderer uses even-odd fill rules to preserve multipolygon holes.

Setup

Install Java 17 or newer.

The wrapper downloads Gradle 9.2.1 when needed.

Windows:

.\gradlew.bat test

macOS or Linux:

bash gradlew test

Render a sample map

Run the PNG command:

.\gradlew.bat run --args="--input src/main/resources/samples/sample-city.osm --style src/main/resources/samples/inkline.style --output build/demo/sample-city.png"

Run the SVG command:

.\gradlew.bat run --args="--input src/main/resources/samples/sample-city.osm --style src/main/resources/samples/inkline.style --output build/demo/sample-city.svg"

Open the generated files under build/demo.

Sample output:

Rendered 25 nodes and 13 ways to .../build/demo/sample-city.png

Change the map look

Copy the sample style and edit its values.

canvas.background=#efe8d9
water.fill=#a8d5df
road.primary.stroke=#9b4f45
label.size=20

Render again with the edited style path.

The parser accepts #RRGGBB and #AARRGGBB colors.

Test status

The test suite covers XML parsing, relation assembly, projection math, style parsing, and PNG or SVG output.

Run all tests:

.\gradlew.bat test

The snapshot test compares rendered pixels with a committed PNG golden file.

The multipolygon tests check reversed way direction, inner rings, relation labels, and SVG fill rules.

Continuous integration

GitHub Actions runs tests and the Gradle build on pushes to main and pull requests.

Limitations

The parser supports nodes, ways, relations, and tags.

The assembler supports multipolygon relations with way members and outer or inner roles.

It ignores nested relations, relation types other than multipolygon, turn restrictions, and coastline assembly.

It skips incomplete outer rings instead of drawing partial geometry.

The renderer uses one viewport and one label layer.

It does not fetch tiles or geocode names.

Roadmap

Complete:

  • Parse multipolygon relations and their way members.
  • Assemble open member ways into outer and inner rings.
  • Render multipolygon holes in PNG and SVG output.

Remaining:

  • Add scale-aware label placement.
  • Add command options for viewport bounds.
  • Add more style selectors for land-use classes.

License

Apache License 2.0.

About

An offline map renderer written in Kotlin. It parses a bundled OpenStreetMap extract and applies a plain-text style sheet. It draws roads, water, buildings, and labels to PNG and SVG images. The renderer works fully offline and does not use tile serv

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages