package btools.mapsplitter; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import btools.util.DenseLongMap; import btools.util.TinyDenseLongMap; /** * TileSplitter splits a tile into pieces */ public class TileSplitter extends MapCreatorBase { private NodeData templateNode = new NodeData( 0, 0, 0 ); private DenseLongMap nodeIndexMap; private DenseLongMap bigWayMemberMap; private DenseLongMap wayIndexMap; private DenseLongMap bigRelMemberMap; private DenseLongMap relIndexMap; private Map nodeMap; private List thisLevelNodes; private Map thisLevelNodesIndexes; private List thisLevelWays; private Map thisLevelWaysIndexes; private int level; private int baseLon; private int baseLat; private int nodeCount = 0; private String typeSuffix; private boolean inPassLoop; private int pass; // 1 == build tileIndexMap, 2 == collect this-level-nodes, 3 == output nodes private File inTileDir; public static void main(String[] args) throws Exception { System.out.println("*** TileSplitter: cut tiles into 16 pieces"); if (args.length != 1) { System.out.println("usage: java TileSplitter " ); return; } new TileSplitter().process( new File( args[0] ) ); } public void process( File tileDir) throws Exception { for( int level = 0; level < 12; level += 2 ) { process( tileDir, level ); } } public void process( File tileDir, int level ) throws Exception { System.out.println("processing level: " + level ); inTileDir = new File( tileDir, "" + (level) ); outTileDir = new File( tileDir, "" + (level+2) ); outTileDir.mkdirs(); this.level = level; // *** initialize 3-pass processing of nodes, ways and relations inPassLoop = false; new NodeIterator( this ).processDir( inTileDir, ".ntl" ); } @Override public void nodeFileStart( File nodeFile ) throws Exception { if ( !inPassLoop ) { inPassLoop = true; pass = 1; new NodeIterator( this ).processFile( nodeFile ); pass = 2; new NodeIterator( this ).processFile( nodeFile ); pass = 3; new NodeIterator( this ).processFile( nodeFile ); pass = 4; inPassLoop = false; } System.out.println( "nodeFileStart pass=" + pass ); if ( pass == 1 ) { getBaseTileFromName( nodeFile.getName() ); nodeIndexMap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap() : new TinyDenseLongMap(); } else if ( pass == 2 ) { } else if ( pass == 3 ) { nodeMap = new HashMap(); thisLevelNodes = new ArrayList(); } else // nodePass = 4 { NodeData.sortByGeoId( thisLevelNodes ); thisLevelNodesIndexes = new HashMap(); int idx = 0; for( NodeData n : thisLevelNodes ) { thisLevelNodesIndexes.put( Long.valueOf( n.nid ), Integer.valueOf( idx++ ) ); } thisLevelNodes = null; } typeSuffix = "ntl"; } private void getBaseTileFromName( String name ) { System.out.println( "getBaseTileFromName: " + name ); int idx1 = name.indexOf( '_' ); int idx2 = name.indexOf( '.' ); baseLon = Integer.parseInt( name.substring( 0, idx1 ) ); baseLat = Integer.parseInt( name.substring( idx1+1, idx2 ) ); } @Override public void nextNode( NodeData n ) throws Exception { int tidx = getTileIndex( n ); if ( pass == 1 ) { nodeCount++; nodeIndexMap.put( n.nid, tidx ); } else if ( pass == 2 ) { } else { boolean usedHere = bigWayMemberMap.getInt( n.nid ) == 0; if ( usedHere ) // if used on this level... { // if no level yet, this is it if ( n.zoom == -1 ) { n.zoom = level; } } if ( pass == 3 ) { if ( n.zoom != -1 ) { n.calcGeoId(); nodeMap.put( n,n ); if ( n.zoom == level ) { thisLevelNodes.add( n ); } } } else // pass == 4 { // add the index if ( n.zoom == level ) { n.nativeIndex = thisLevelNodesIndexes.get( Long.valueOf( n.nid ) ); } if ( usedHere ) { n.writeTo( getOutStreamForTile( 16 ) ); } n.writeTo( getOutStreamForTile( tidx ) ); // write to subtile } } } @Override public void nodeFileEnd( File nodeFile ) throws Exception { System.out.println( "nodeFileEnd pass=" + pass ); closeTileOutStreams(); File parentNodes = new File( outTileDir, getNameForTile( 16 ) ); // read corresponding way-file if ( pass == 2 ) { bigWayMemberMap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap() : new TinyDenseLongMap(); } String name = nodeFile.getName(); String wayfilename = name.substring( 0, name.length()-3 ) + "wtl"; File wayfile = new File( inTileDir, wayfilename ); if ( wayfile.exists() ) { new WayIterator( this ).processFile( wayfile ); } // read corresponding relation-file if ( pass == 1 ) { bigRelMemberMap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap() : new TinyDenseLongMap(); } String relfilename = name.substring( 0, name.length()-3 ) + "rtl"; File relfile = new File( inTileDir, relfilename ); if ( relfile.exists() ) { new RelationIterator( this ).processFile( relfile ); } if ( pass == 4 ) { nodeFile.delete(); if ( parentNodes.exists() ) { parentNodes.renameTo( nodeFile ); } else if ( nodeCount > 0 ) { nodeFile.createNewFile(); // create even empty to signal existence of childs } } } @Override public void wayFileStart( File wayFile ) throws Exception { System.out.println( "wayFileStart pass=" + pass ); if ( pass == 1 ) { wayIndexMap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap() : new TinyDenseLongMap(); } else if ( pass == 3 ) { thisLevelWays = new ArrayList(); } else if ( pass == 4 ) { WayData.sortByStartNode( thisLevelWays ); thisLevelWaysIndexes = new HashMap(); int idx = 0; for( WayData w : thisLevelWays ) { thisLevelWaysIndexes.put( Long.valueOf( w.wid ), Integer.valueOf( idx++ ) ); } thisLevelWays = null; } typeSuffix = "wtl"; } @Override public void nextWay( WayData w ) throws Exception { int widx = getTileIndex( w ); if ( widx == -1 ) { System.out.println( "************ invalid way: " + w.wid ); return; } if ( pass == 1 ) { wayIndexMap.put( w.wid, widx ); } else // pass >= 2 { boolean usedHere = bigRelMemberMap.getInt( w.wid ) == 0; if ( usedHere || widx == 16 ) { // if no level yet, this is it if ( w.zoom == -1 ) { w.zoom = level; } if ( pass == 2 ) { int nnodes = w.nodes.size(); for (int i=0; i> ( 26 - level ) ) & 3; int idxLat = ( n.ilat >> ( 26 - level ) ) & 3; return 4 * idxLon + idxLat; } private int getTileIndex( WayData w ) { int nnodes = w.nodes.size(); int wayTileIndex = 16; // determine the tile-index for each node for (int i=0; i> 2); int idxLat = baseLat * 4 + (tileIndex & 3); return idxLon + "_" + idxLat + "." + typeSuffix; } }