GeoDesk for Java

From OpenStreetMap Wiki
Jump to navigation Jump to search
GeoDesk for Java
v · d 
Author: Clarisma / GeoDesk contributors
License: Apache License 2.0
Version: 2.0.0 (2025-09-29)
Language:
java
Website: https://docs.geodesk.com/java
Source code: https://github.com/clarisma/geodesk

Java SDK for querying and analyzing OpenStreetMap data stored in Geo-Object Libraries (GOLs)

Features
Feature Value
Map Display
?
Routing
?
Navigating
?
Tracking
?
Monitoring
?
Editing
?
Rendering
?
Accessibility
?

GeoDesk for Java is an open-source Java library for fast querying and analysis of OpenStreetMap data. It is part of the GeoDesk toolkit and provides a Java API for working with Geo-Object Libraries (GOLs) — compact spatial databases designed specifically for OSM data.

GeoDesk for Java is also available for Python and for C++.

Overview

GeoDesk for Java allows developers to build geospatial applications on Java 16 or above. It works directly with GOL files (no server process required) and provides a rich set of spatial query capabilities. Key characteristics include:

  • Compact storage — GOL files are only 20% to 50% larger than OSM-PBF source data, less than a tenth of the storage consumed by a traditional SQL-based database.
  • Fast queries — typically 50 times faster than SQL.
  • Intuitive API — queries return Java objects. Quickly discover tags, way-nodes and relation members. Get a feature's geometry, measure its length/area.
  • Full relation support — unlike traditional geospatial databases, GeoDesk natively handles relations, a unique and powerful aspect of OSM data.
  • JTS integration — features can be converted to JTS (Java Topology Suite) geometries for advanced geometric operations such as buffer, union, simplify, convex hulls, and more.
  • Automatic tile downloading — feature libraries can be configured to automatically fetch missing tiles from a remote repository as they are needed by queries.
  • Thread-safe — the FeatureLibrary object is thread-safe and can be shared across multiple threads. GOL files can also be shared among multiple processes.
  • Modest hardware requirements — any 64-bit system with Java 16+ will run GeoDesk.

System Requirements

  • Java 16 or above
  • 64-bit system running Windows, macOS or Linux
  • The GOL Tool is required to create or manage GOL files

Installation

Stable releases are available on Maven Central. Add the following dependency to your project's POM:

<dependency>
    <groupId>com.geodesk</groupId>
    <artifactId>geodesk</artifactId>
    <version>2.0.0</version>
</dependency>

Alternatively, build the latest version from source:

git clone https://github.com/clarisma/geodesk.git
cd geodesk
mvn install

You also need the GOL Tool to build or manage GOL files. See the GOL Tool download page for installation instructions.

Getting Started

Creating a GOL

Before using GeoDesk for Java, you need a Geo-Object Library (GOL) containing OSM data. You can create one from any .osm.pbf file using the GOL Tool:

gol build germany germany-latest.osm.pbf

Country and regional extracts can be downloaded from sites such as GeoFabrik or BBBike. Alternatively, you can download pre-made data tiles from a Geo-Object Bundle (e.g. from Open Planet Data) using the gol load command.

Opening a Feature Library

import com.geodesk.feature.*;
import com.geodesk.geom.*;

FeatureLibrary germany = new FeatureLibrary("germany.gol");

The FeatureLibrary itself implements the Features interface, representing all features in the GOL.

To automatically download missing tiles as they are needed by queries, specify a repository URL:

FeatureLibrary world = new FeatureLibrary(
    "world.gol", "https://data.geodesk.com/world");

When you are done querying, close the library to release its resources:

germany.close();

Querying Features

Features can be filtered using GOQL (Geo-Object Query Language), a concise query syntax similar to MapCSS:

Features restaurants = germany.select("na[amenity=restaurant]");  // Nodes and areas
Features hydrants = germany.nodes("[emergency=fire_hydrant]");    // Only nodes
Features highways = germany.ways("[highway]");                    // Only ways
Features routes = germany.relations("[route=bicycle]");           // Only relations

The type selectors are: n (nodes), w (ways, excluding areas), a (areas, which can be ways or relations), r (relations, excluding areas), and * (any type).

Bounding Box Queries

Features can be restricted to a bounding box using the in() method:

Box bbox = Box.ofWSEN(8.42, 53.75, 9.07, 53.98);
    // West, South, East, North as longitude/latitude
Features subset = germany.select("na[tourism=hotel]").in(bbox);

Spatial Queries

Features can be filtered spatially using methods like within(), intersecting(), containing(), crossing(), touching(), and maxMetersFrom():

// Find all museums within a city
Features parisMuseums = museums.within(paris);

// Find bus stops within 500 meters of a restaurant
Features nearbyStops = features.select("n[highway=bus_stop]")
    .maxMetersFrom(500, restaurant);

// Find railway bridges crossing a river
Features bridges = features.select("w[railway][bridge]")
    .crossing(mississippi);

// Find the administrative area containing a given point
Features areas = features.select(
    "a[boundary=administrative][admin_level <= 6]")
    .containingLonLat(-117.25, 32.99);

Spatial filters accept Feature, JTS Geometry, and PreparedGeometry objects.

Filters can be combined:

roads.ways("[bridge]").in(bbox).crossing(rhineRiver)

Working with Features

Each Feature object represents an OSM element (node, way, or relation). Feature objects are obtained via queries.

Tags

Tags are accessed using dedicated methods:

String name = feature.stringValue("name");    // empty string if absent
int speed = feature.intValue("maxspeed");     // 0 if absent or non-numeric
double height = feature.doubleValue("height");

if (feature.hasTag("highway")) { ... }
if (feature.hasTag("shop", "bakery")) { ... }

All tags can be retrieved and iterated:

Tags tags = feature.tags();
while (tags.next())
{
    String key = tags.key();
    String value = tags.stringValue();
}

// Or convert to a Map
Map<String, Object> tagMap = feature.tags().toMap();

Properties

Features expose the following key properties:

  • type() — returns a FeatureType enum (NODE, WAY, or RELATION)
  • id() — the feature's numeric OSM ID (long)
  • isNode(), isWay(), isRelation(), isArea() — type tests
  • lon(), lat() — WGS-84 coordinates (degrees)
  • x(), y() — Mercator-projected coordinates
  • bounds() — the bounding box (a Box)
  • area() — area in square meters (for polygonal features)
  • length() — length in meters (for lineal features)
  • toGeometry() — creates a JTS geometry (Point, LineString, Polygon, MultiPolygon, or GeometryCollection)

Related Features

  • nodes() — the nodes of a way (with optional GOQL filter)
  • members() — the members of a relation (with optional GOQL filter)
  • parents() — relations containing this feature, or ways to which a node belongs
  • role() — the role of a feature within a relation (if obtained via a member query)

These queries can be inverted using the topological filter methods nodesOf(), membersOf(), and parentsOf() on feature collections.

belongsTo(feature) checks whether a feature is a member of a specific relation or a node of a specific way, and belongsToRelation() checks whether a feature is a member of any relation.

Feature Collections

Feature collections implement the Features interface and behave like Java Collection classes, supporting size(), isEmpty(), contains(), toArray(), and iteration. Additional methods include:

// Iterate
for (Feature street : streets) { ... }

// Convert to a list
List<Feature> list = streets.toList();

// Get the first feature (or null if empty)
Feature city = france.select("n[place=city][name=Paris]").first();

// Count
int n = restaurants.size();

Feature collections are lightweight and lazy — features are only fetched when iterated or when a terminal operation such as toList() is called.

Example Code

Find all pubs in Zurich and print their names:

import com.geodesk.feature.*;
import com.geodesk.geom.*;

public class PubsExample
{
    public static void main(String[] args)
    {
        FeatureLibrary switzerland = new FeatureLibrary("switzerland.gol");

        for (Feature pub : switzerland
            .select("na[amenity=pub]")
            .in(Box.ofWSEN(8.53, 47.36, 8.55, 47.38)))
        {
            System.out.println(pub.stringValue("name"));
        }

        switzerland.close();
    }
}

Find all movie theaters within 500 meters of a given point:

Features cinemas = features.select("na[amenity=cinema]")
    .maxMetersFromLonLat(500, myLon, myLat);

Count the number of entrances of a building:

int numberOfEntrances = building.nodes("[entrance]").size();

Discover bus routes traversing a street:

for (Feature route : street.parents("[route=bus]"))
{
    System.out.printf("- %s from %s to %s%n",
        route.stringValue("ref"),
        route.stringValue("from"),
        route.stringValue("to"));
}

More examples can be found on GitHub.

Documentation

Full documentation is available at docs.geodesk.com/java, covering:

See Also

External Links