This is a minimal example project that shows how to create custom maps with Planetiler.
Requirements:
brew install --cask temurinbrew install mavenbrew install nodenpm install -g tileserver-gl-light.osm.pbf fileFirst, make a copy of this example project. It contains:
com.onthegomap:planetiler-core main Planetiler dependencycom.onthegomap:planetiler-core test dependency for test utilitiesmaven-assembly-plugin build plugin configuration to create a single executable jar file from Maven’s package
goal commandpom.xml exists for the parent pom.xml to treat this as a child project, you can replace with standalone.pom.xml
or append --file standalone.pom.xml to every maven command to run as a standalone project.Then, create a new class that implements com.onthegomap.planetiler.Profile:
package com.onthegomap.planetiler.examples;
import com.onthegomap.planetiler.FeatureCollector;
import com.onthegomap.planetiler.Planetiler;
import com.onthegomap.planetiler.Profile;
import com.onthegomap.planetiler.reader.SourceFeature;
import java.nio.file.Path;
public class MyProfile implements Profile {
@Override
public String name() {
// name that shows up in the MBTiles metadata table
return "My Profile";
}
}
Then, implement the processFeature() method in your class (add the code before the last closing curly bracket)
that determines what vector tile features to emit for each source feature.
For example, to include a map of toilets from OpenStreetMap
at zoom level 12 and above:
@Override
public void processFeature(SourceFeature sourceFeature, FeatureCollector features) {
if (sourceFeature.isPoint() && sourceFeature.hasTag("amenity", "toilets")) {
features.point("toilets") // create a point in layer named "toilets"
.setMinZoom(12)
.setAttr("customers_only", sourceFeature.hasTag("access", "customers"))
.setAttr("indoor", sourceFeature.getBoolean("indoor"))
.setAttr("name", sourceFeature.getTag("name"))
.setAttr("operator", sourceFeature.getTag("operator"));
}
}
Next, add a main entrypoint that
uses Planetiler to define input sources
and default input/output paths:
public static void main(String... args) throws Exception {
Planetiler.create(args)
.setProfile(new MyProfile())
// if input.pbf not found, download Monaco from Geofabrik
.addOsmSource("osm", Path.of("data", "sources", "input.pbf"), "geofabrik:monaco")
.overwriteOutput("mbtiles", Path.of("data", "toilets.mbtiles"))
.run();
}
Then build the application into a single jar file with all dependencies included:
mvn clean package --file standalone.pom.xml
And run the application:
java -cp target/*-with-deps.jar com.onthegomap.planetiler.examples.MyProfile
Then, to inspect the tiles:
tileserver-gl-light --mbtiles data/toilets.mbtiles
Finally, open http://localhost:8080 to see your tiles.
Unit tests verify the logic for mapping source features to vector tile features, and integration tests run the entire profile end-to-end and ensure the output vector tiles contain features you expect. TestUtils contains utilities for unit and integration testing.
A basic unit test:
@Test
public void unitTest() {
var profile = new MyProfile();
var node = SimpleFeature.create(
TestUtils.newPoint(1, 2),
Map.of("amenity", "toilets")
);
List<FeatureCollector.Feature> mapFeatures = TestUtils.processSourceFeature(node, profile);
// Then inspect attributes of each of vector tile fetures emitted...
assertEquals(1, mapFeatures.length);
assertEquals(12, mapFeatures.get(0).getMinZoom());
}
A basic integration test:
@Test
public void integrationTest(@TempDir Path tmpDir) throws Exception {
Path mbtilesPath = tmpDir.resolve("output.mbtiles");
MyProfile.main(
"--osm_path=" + TestUtils.pathToResource("monaco-latest.osm.pbf"),
"--tmp=" + tmpDir,
"--mbtiles=" + mbtilesPath,
));
try (Mbtiles mbtiles = Mbtiles.newReadOnlyDatabase(mbtilesPath)) {
Map<String, String> metadata = mbtiles.metadata().getAll();
assertEquals("My Profile", metadata.get("name"));
// then inspect features in the emitted vector tiles
TestUtils.assertNumFeatures(mbtiles, "toilets", 14, Map.of(), GeoUtils.WORLD_LAT_LON_BOUNDS,
34, Point.class);
}
}
See ToiletsProfileTest for a complete unit and integration test.
Check out: