[GIS] How to split a 20 km² OSM file

openstreetmaposm2worldsplitting

I want to create a 3D model of an OSM map using osm2world. Osm2World can render maps of large regions, for example, there is a 3D map of Austria and Germany (generated from OSM).

I want to do something similar for a smaller region.

Since osm2world cannot handle large maps, I need to

  1. split the original map into smaller maps,
  2. transform the smaller maps to several OBJ files and
  3. combine these OBJ files into one big OBJ file of the entire region.

In order to split the maps, I downloaded splitter-r311 and tried to transform the original map into a small maps with minimum possible number of nodes using following call:

java -Xmx1G -jar splitter.jar --output=xml --output-dir=results --max-nodes=1000 
input\RU-PRI.osm > splitter.log

This attempt failed. splitter.log contains following entries:

Warning: No solution found for partition (42.1875,130.341796875) to (48.6474609375,139.21875) with 541.648 nodes
Final solution has 0 tile(s) and a rating of 9223372036854775807. The smallest node count is 9223372036854775807, the worst aspect ratio is near -1.0
Failed to calculate areas.
Sorry. Cannot split the file without creating huge, almost empty, tiles.
Please specify a bounding polygon with the --polygon-file parameter.
Time finished: Sun Oct 06 00:42:21 MSK 2013
Total time taken: 2779s

What can I do in order to convert the original map into partial maps small enough to be processed by osm2world? Can I modify the input file to make it more osm2world-friendly?

I tried to run splitter with --max-nodes=16000, but got OutOfMemoryErrors when I tried to use them in osm2world.

I tried to use MapSplit, but it didn't work due to OutOfMemoryError, either.

Update 1 (13.10.2013 12:12 MSK):

1) I found out that the original file I wanted to convert was too large. Therefore, instead of the original file, I now use a smaller file 03-artyom.osm.

2) When trying to convert this file to OBJ, I had several errors. In order to fix them, I modified the code of OSM2World. Below is the diff and here is the modified source code:

diff --git a/src/org/osm2world/core/math/JTSConversionUtil.java b/src/org/osm2world/core/math/JTSConversionUtil.java
index 81f6fa2..f498a9b 100644
--- a/src/org/osm2world/core/math/JTSConversionUtil.java
+++ b/src/org/osm2world/core/math/JTSConversionUtil.java
@@ -89,7 +89,14 @@ public class JTSConversionUtil {
            }
        }

-       return new PolygonWithHolesXZ(outerPolygon, holes);
+       final PolygonWithHolesXZ polygonWithHolesXZ = new PolygonWithHolesXZ(outerPolygon, holes);
+       
+       if (polygonWithHolesXZ.getArea() == 0.0)
+       {
+           return null;
+       }
+       
+       return polygonWithHolesXZ;

    }

@@ -112,7 +119,12 @@ public class JTSConversionUtil {

        if (geometry instanceof Polygon) {
            if (geometry.getNumPoints() > 2) {
-               result.add(polygonXZFromJTSPolygon((Polygon)geometry));
+               final PolygonWithHolesXZ polygonXZFromJTSPolygon = 
+                       polygonXZFromJTSPolygon((Polygon)geometry);
+               if (polygonXZFromJTSPolygon != null)
+               {
+                   result.add(polygonXZFromJTSPolygon);                    
+               }
            }
        } else if (geometry instanceof GeometryCollection) {
            GeometryCollection collection = (GeometryCollection)geometry;
diff --git a/src/org/osm2world/core/math/SimplePolygonXZ.java b/src/org/osm2world/core/math/SimplePolygonXZ.java
index 5a9dfa5..8d889d0 100644
--- a/src/org/osm2world/core/math/SimplePolygonXZ.java
+++ b/src/org/osm2world/core/math/SimplePolygonXZ.java
@@ -41,7 +41,7 @@ public class SimplePolygonXZ extends PolygonXZ {
        this.area = Math.abs(signedArea);
        this.clockwise = signedArea < 0;

-       assertNonzeroArea();
+       // assertNonzeroArea();
    }

    public List<LineSegmentXZ> getSegments() {
diff --git a/src/org/osm2world/core/math/algorithms/Poly2TriTriangulationUtil.java b/src/org/osm2world/core/math/algorithms/Poly2TriTriangulationUtil.java
index 7d2c352..abfb629 100644
--- a/src/org/osm2world/core/math/algorithms/Poly2TriTriangulationUtil.java
+++ b/src/org/osm2world/core/math/algorithms/Poly2TriTriangulationUtil.java
@@ -6,6 +6,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;

@@ -107,7 +108,16 @@ public final class Poly2TriTriangulationUtil {

        /* run triangulation */

-       Poly2Tri.triangulate(triangulationPolygon);
+       try
+       {
+           Poly2Tri.triangulate(triangulationPolygon);         
+       }
+       catch (NullPointerException exception)
+       {
+           // exception.printStackTrace();
+           
+           return new LinkedList<TriangleXZ>();
+       }

        /* convert the result to the desired format */

3) Now, when I run OSM2World (java org.osm2world.console.OSM2World --input D:\dev\osm2world\primorie\josm-manual\output\03-artyom.osm --output D:\dev\osm2world\primorie\josm-manual\output\04-artyom.osm.obj), I get following errors:

[main] WARN org.poly2tri.triangulation.delaunay.sweep.DTSweep - Skipping edge: Point on constrained edge not supported yet
Exception in thread "main" java.lang.StackOverflowError
    at org.poly2tri.triangulation.TriangulationUtil.orient2d(TriangulationUtil.java:195)
    at org.poly2tri.triangulation.delaunay.sweep.DTSweep.edgeEvent(DTSweep.java:573)
    at org.poly2tri.triangulation.delaunay.sweep.DTSweep.edgeEvent(DTSweep.java:626)
    at org.poly2tri.triangulation.delaunay.sweep.DTSweep.edgeEvent(DTSweep.java:604)
    at org.poly2tri.triangulation.delaunay.sweep.DTSweep.edgeEvent(DTSweep.java:604)
    at org.poly2tri.triangulation.delaunay.sweep.DTSweep.edgeEvent(DTSweep.java:626)
    at org.poly2tri.triangulation.delaunay.sweep.DTSweep.edgeEvent(DTSweep.java:583)
    at org.poly2tri.triangulation.delaunay.sweep.DTSweep.edgeEvent(DTSweep.java:583)
    at org.poly2tri.triangulation.delaunay.sweep.DTSweep.edgeEvent(DTSweep.java:626)
    at org.poly2tri.triangulation.delaunay.sweep.DTSweep.edgeEvent(DTSweep.java:604)

Best Answer

The splitter programme is specifically designed for creating Garmin map tiles. These map tiles have to follow certain rules for tile size, which are not necessary for your needs.

A better try would be osmconvert: http://wiki.openstreetmap.org/wiki/Osmconvert

which can split your input file by lat/long boundaries.