Contents Prev: Building polygons from relations Next: Visualizing data: restaurant density

Applying geometric operations to polygons

Being able to convert OpenStreetMap elements to JTS geometries allows us to perform a lot of interesting geometric operations on them.

For example, here is the the borough 'Mitte' of Berlin:

It can be built using the following code. The output is available here.

  public static void main(String[] args)
      throws IOException, EntityNotFoundException
  {
    // String query =
    // "http://overpass-api.de/api/interpreter?data=(rel(16566);>;);out;";
    String query = "http://osmtestdata.topobyte.de/relation-16566.osm";
 
    // Open a stream
    InputStream input = new URL(query).openStream();
 
    OsmIterator iterator = new OsmXmlIterator(input, false);
    InMemoryMapDataSet data = MapDataSetLoader.read(iterator, falsefalse,
        true);
 
    TLongObjectMap<OsmRelation> relations = data.getRelations();
 
    if (relations.isEmpty()) {
      System.out.println("No relation found");
      return;
    }
 
    OsmRelation relation = relations.valueCollection().iterator().next();
 
    Geometry polygon = new GeometryBuilder().build(relation, data);
 
    Map<String, String> tags = OsmModelUtil.getTagsAsMap(relation);
    Map<String, Object> properties = new HashMap<>();
    for (String key : tags.keySet()) {
      properties.put(key, tags.get(key));
    }
 
    GeoJSONWriter writer = new GeoJSONWriter();
    org.wololo.geojson.Geometry g = writer.write(polygon);
    Feature feature = new Feature(g, properties);
 
    String json = feature.toString();
 
    System.out.println(GeoJsonHelper.prettyPrintFeature(json));
  }

Buffers

As a subclass of Geometry, the MultiPolygon implements the buffer() operation that produces an enlarged version of the polygon. As argument the operation accepts a distance that specifies how much larger the result will be.

    // Build the polygon from the relation
    RegionBuilder regionBuilder = new RegionBuilder();
    RegionBuilderResult region = regionBuilder.build(relation, data);
    MultiPolygon polygon = region.getMultiPolygon();
 
    // Create a buffer
    Geometry buffer = polygon.buffer(0.005);
 
    // Combine the polygon and its buffer into a GeometryCollection
    Geometry both = new GeometryFactory()
        .createGeometryCollection(new Geometry[] { polygon, buffer });
 
    // GeoJSON output
    Map<String, Object> properties = new HashMap<>();
    GeoJSONWriter writer = new GeoJSONWriter();
    org.wololo.geojson.Geometry g = writer.write(both);
    Feature feature = new Feature(g, properties);
 
    String json = feature.toString();
    System.out.println(GeoJsonHelper.prettyPrintFeature(json));

The above example used a positive distance for the buffer() operation. It is however also possible to supply negative values, producing a polygon that is smaller than the input.

    // Build the polygon from the relation
    RegionBuilder regionBuilder = new RegionBuilder();
    RegionBuilderResult region = regionBuilder.build(relation, data);
    MultiPolygon polygon = region.getMultiPolygon();
 
    // Create a buffer
    Geometry buffer = polygon.buffer(-0.005);
 
    // Combine the polygon and its buffer into a GeometryCollection
    GeometryCollection both = new GeometryFactory()
        .createGeometryCollection(new Geometry[] { polygon, buffer });
 
    // GeoJSON output
    Map<String, Object> properties = new HashMap<>();
    GeoJSONWriter writer = new GeoJSONWriter();
    org.wololo.geojson.Geometry g = writer.write(both);
    Feature feature = new Feature(g, properties);
 
    String json = feature.toString();
    System.out.println(GeoJsonHelper.prettyPrintFeature(json));

Set operations

The Geometry class offers more operations, most notably the set operations: intersection, union, difference and symmetric difference. For example we can subtract the original polygon from its buffer using the difference operation:

    // Build the polygon from the relation
    RegionBuilder regionBuilder = new RegionBuilder();
    RegionBuilderResult region = regionBuilder.build(relation, data);
    MultiPolygon polygon = region.getMultiPolygon();
 
    // Create a buffer
    Geometry buffer = polygon.buffer(0.005);
 
    // Compute the difference, buffer - polygon
    Geometry difference = buffer.difference(polygon);
 
    // GeoJSON output
    Map<String, Object> properties = new HashMap<>();
    GeoJSONWriter writer = new GeoJSONWriter();
    org.wololo.geojson.Geometry g = writer.write(difference);
    Feature feature = new Feature(g, properties);
 
    String json = feature.toString();
    System.out.println(GeoJsonHelper.prettyPrintFeature(json));
Contents Prev: Building polygons from relations Next: Visualizing data: restaurant density