initial commit of BRouter Version 0.98

This commit is contained in:
Arndt Brenschede 2014-01-18 15:29:05 +01:00
parent e4ae2b37d3
commit 91e62f1164
120 changed files with 15382 additions and 0 deletions

View file

@ -0,0 +1,166 @@
/**
* common base class for the map-filters
*
* @author ab
*/
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
public abstract class MapCreatorBase implements WayListener, NodeListener, RelationListener
{
private DataOutputStream[] tileOutStreams;
protected File outTileDir;
protected HashMap<String,String> tags;
public void putTag( String key, String value )
{
if ( tags == null ) tags = new HashMap<String,String>();
tags.put( key, value );
}
public String getTag( String key )
{
return tags == null ? null : tags.get( key );
}
public HashMap<String,String> getTagsOrNull()
{
return tags;
}
public void setTags( HashMap<String,String> tags )
{
this.tags = tags;
}
protected static long readId( DataInputStream is) throws IOException
{
int offset = is.readByte();
if ( offset == 32 ) return -1;
long i = is.readInt();
i = i << 5;
return i | offset;
}
protected static void writeId( DataOutputStream o, long id ) throws IOException
{
if ( id == -1 )
{
o.writeByte( 32 );
return;
}
int offset = (int)( id & 0x1f );
int i = (int)( id >> 5 );
o.writeByte( offset );
o.writeInt( i );
}
protected static File[] sortBySizeAsc( File[] files )
{
int n = files.length;
long[] sizes = new long[n];
File[] sorted = new File[n];
for( int i=0; i<n; i++ ) sizes[i] = files[i].length();
for(int nf=0; nf<n; nf++)
{
int idx = -1;
long min = -1;
for( int i=0; i<n; i++ )
{
if ( sizes[i] != -1 && ( idx == -1 || sizes[i] < min ) )
{
min = sizes[i];
idx = i;
}
}
sizes[idx] = -1;
sorted[nf] = files[idx];
}
return sorted;
}
protected File fileFromTemplate( File template, File dir, String suffix )
{
String filename = template.getName();
filename = filename.substring( 0, filename.length() - 3 ) + suffix;
return new File( dir, filename );
}
protected DataInputStream createInStream( File inFile ) throws IOException
{
return new DataInputStream( new BufferedInputStream ( new FileInputStream( inFile ) ) );
}
protected DataOutputStream createOutStream( File outFile ) throws IOException
{
return new DataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) );
}
protected DataOutputStream getOutStreamForTile( int tileIndex ) throws Exception
{
if ( tileOutStreams == null )
{
tileOutStreams = new DataOutputStream[64];
}
if ( tileOutStreams[tileIndex] == null )
{
tileOutStreams[tileIndex] = createOutStream( new File( outTileDir, getNameForTile( tileIndex ) ) );
}
return tileOutStreams[tileIndex];
}
protected String getNameForTile( int tileIndex )
{
throw new IllegalArgumentException( "getNameForTile not implemented" );
}
protected void closeTileOutStreams() throws Exception
{
if ( tileOutStreams == null )
{
return;
}
for( int tileIndex=0; tileIndex<tileOutStreams.length; tileIndex++ )
{
if ( tileOutStreams[tileIndex] != null ) tileOutStreams[tileIndex].close();
tileOutStreams[tileIndex] = null;
}
}
// interface dummys
@Override
public void nodeFileStart( File nodefile ) throws Exception {}
@Override
public void nextNode( NodeData n ) throws Exception {}
@Override
public void nodeFileEnd( File nodefile ) throws Exception {}
@Override
public void wayFileStart( File wayfile ) throws Exception {}
@Override
public void nextWay( WayData data ) throws Exception {}
@Override
public void wayFileEnd( File wayfile ) throws Exception {}
@Override
public void nextRelation( RelationData data ) throws Exception {}
}

View file

@ -0,0 +1,87 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
/**
* NodeCutter does 1 step in map-processing:
*
* - cuts the 45*30 node tiles into 5*5 pieces
*
* @author ab
*/
public class NodeCutter extends MapCreatorBase
{
private int lonoffset;
private int latoffset;
public static void main(String[] args) throws Exception
{
System.out.println("*** NodeCutter: Cut big node-tiles into 5x5 tiles");
if (args.length != 2)
{
System.out.println("usage: java NodeCutter <node-tiles-in> <node-tiles-out>" );
return;
}
new NodeCutter().process( new File( args[0] ), new File( args[1] ) );
}
public void process( File nodeTilesIn, File nodeTilesOut ) throws Exception
{
this.outTileDir = nodeTilesOut;
new NodeIterator( this, true ).processDir( nodeTilesIn, ".tlf" );
}
@Override
public void nodeFileStart( File nodefile ) throws Exception
{
lonoffset = -1;
latoffset = -1;
}
@Override
public void nextNode( NodeData n ) throws Exception
{
n.writeTo( getOutStreamForTile( getTileIndex( n.ilon, n.ilat ) ) );
}
@Override
public void nodeFileEnd( File nodeFile ) throws Exception
{
closeTileOutStreams();
}
private int getTileIndex( int ilon, int ilat )
{
int lonoff = (ilon / 45000000 ) * 45;
int latoff = (ilat / 30000000 ) * 30;
if ( lonoffset == -1 ) lonoffset = lonoff;
if ( latoffset == -1 ) latoffset = latoff;
if ( lonoff != lonoffset || latoff != latoffset )
throw new IllegalArgumentException( "inconsistent node: " + ilon + " " + ilat );
int lon = (ilon / 5000000) % 9;
int lat = (ilat / 5000000) % 6;
if ( lon < 0 || lon > 8 || lat < 0 || lat > 5 ) throw new IllegalArgumentException( "illegal pos: " + ilon + "," + ilat );
return lon*6 + lat;
}
protected String getNameForTile( int tileIndex )
{
int lon = (tileIndex / 6 ) * 5 + lonoffset - 180;
int lat = (tileIndex % 6 ) * 5 + latoffset - 90;
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
return slon + "_" + slat + ".n5d";
}
}

View file

@ -0,0 +1,55 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import btools.util.*;
/**
* Container for node data on the preprocessor level
*
* @author ab
*/
public class NodeData extends MapCreatorBase
{
public long nid;
public int ilon;
public int ilat;
public long description;
public short selev = Short.MIN_VALUE;
public NodeData( long id, double lon, double lat )
{
nid = id;
ilat = (int)( ( lat + 90. )*1000000. + 0.5);
ilon = (int)( ( lon + 180. )*1000000. + 0.5);
}
public NodeData( DataInputStream dis ) throws Exception
{
nid = readId( dis );
ilon = dis.readInt();
ilat = dis.readInt();
int mode = dis.readByte();
if ( ( mode & 1 ) != 0 ) description = dis.readLong();
if ( ( mode & 2 ) != 0 ) selev = dis.readShort();
}
public void writeTo( DataOutputStream dos ) throws Exception
{
writeId( dos, nid );
dos.writeInt( ilon );
dos.writeInt( ilat );
int mode = ( description == 0L ? 0 : 1 ) | ( selev == Short.MIN_VALUE ? 0 : 2 );
dos.writeByte( (byte)mode );
if ( ( mode & 1 ) != 0 ) dos.writeLong( description );
if ( ( mode & 2 ) != 0 ) dos.writeShort( selev );
}
}

View file

@ -0,0 +1,86 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import btools.util.*;
/**
* NodeFilter does 1 step in map-processing:
*
* - filters out unused nodes according to the way file
*
* @author ab
*/
public class NodeFilter extends MapCreatorBase
{
private DataOutputStream nodesOutStream;
private File nodeTilesOut;
protected DenseLongMap nodebitmap;
public static void main(String[] args) throws Exception
{
System.out.println("*** NodeFilter: Filter way related nodes");
if (args.length != 3)
{
System.out.println("usage: java NodeFilter <node-tiles-in> <way-file-in> <node-tiles-out>" );
return;
}
new NodeFilter().process( new File( args[0] ), new File( args[1] ), new File( args[2] ) );
}
public void process( File nodeTilesIn, File wayFileIn, File nodeTilesOut ) throws Exception
{
this.nodeTilesOut = nodeTilesOut;
// read the wayfile into a bitmap of used nodes
nodebitmap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap( 1 ) : new TinyDenseLongMap();
new WayIterator( this, false ).processFile( wayFileIn );
// finally filter all node files
new NodeIterator( this, true ).processDir( nodeTilesIn, ".tls" );
}
@Override
public void nextWay( WayData data ) throws Exception
{
int nnodes = data.nodes.size();
for (int i=0; i<nnodes; i++ )
{
nodebitmap.put( data.nodes.get(i), 0 );
}
}
@Override
public void nodeFileStart( File nodefile ) throws Exception
{
String filename = nodefile.getName();
filename = filename.substring( 0, filename.length() - 3 ) + "tlf";
File outfile = new File( nodeTilesOut, filename );
nodesOutStream = new DataOutputStream( new BufferedOutputStream ( new FileOutputStream( outfile ) ) );
}
@Override
public void nextNode( NodeData n ) throws Exception
{
// check if node passes bitmap
if ( nodebitmap.getInt( n.nid ) == 0 ) // 0 -> bit set, -1 -> unset
{
n.writeTo( nodesOutStream );
}
}
@Override
public void nodeFileEnd( File nodeFile ) throws Exception
{
nodesOutStream.close();
}
}

View file

@ -0,0 +1,76 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import btools.util.*;
/**
* Iterate over a singe nodefile or a directory
* of nodetiles and feed the nodes to the callback listener
*
* @author ab
*/
public class NodeIterator extends MapCreatorBase
{
private NodeListener listener;
private boolean delete;
public NodeIterator( NodeListener nodeListener, boolean deleteAfterReading )
{
listener = nodeListener;
delete = deleteAfterReading;
}
public void processDir( File indir, String inSuffix ) throws Exception
{
if ( !indir.isDirectory() )
{
throw new IllegalArgumentException( "not a directory: " + indir );
}
File[] af = sortBySizeAsc( indir.listFiles() );
for( int i=0; i<af.length; i++ )
{
File nodefile = af[i];
if ( nodefile.getName().endsWith( inSuffix ) )
{
processFile( nodefile );
}
}
}
public void processFile(File nodefile) throws Exception
{
System.out.println( "*** NodeIterator reading: " + nodefile );
listener.nodeFileStart( nodefile );
DataInputStream di = new DataInputStream( new BufferedInputStream ( new FileInputStream( nodefile ) ) );
try
{
for(;;)
{
NodeData n = new NodeData( di );
listener.nextNode( n );
}
}
catch( EOFException eof )
{
di.close();
}
listener.nodeFileEnd( nodefile );
if ( delete && "true".equals( System.getProperty( "deletetmpfiles" ) ))
{
nodefile.delete();
}
}
}

View file

@ -0,0 +1,17 @@
package btools.mapcreator;
import java.io.File;
/**
* Callbacklistener for NodeIterator
*
* @author ab
*/
public interface NodeListener
{
void nodeFileStart( File nodefile ) throws Exception;
void nextNode( NodeData data ) throws Exception;
void nodeFileEnd( File nodefile ) throws Exception;
}

View file

@ -0,0 +1,205 @@
/**
* This program
* - reads an *.osm from stdin
* - writes 45*30 degree node tiles + a way file + a rel file
*
* @author ab
*/
package btools.mapcreator;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.zip.GZIPInputStream;
import btools.expressions.BExpressionContext;
public class OsmCutter extends MapCreatorBase
{
private long recordCnt;
private long nodesParsed;
private long waysParsed;
private long relsParsed;
private long changesetsParsed;
private DataOutputStream wayDos;
private DataOutputStream cyclewayDos;
public static void main(String[] args) throws Exception
{
System.out.println("*** OsmCutter: cut an osm map in node-tiles + a way file");
if (args.length != 4 && args.length != 5)
{
System.out.println("usage: bzip2 -dc <map> | java OsmCutter <lookup-file> <out-tile-dir> <out-way-file> <out-rel-file>");
System.out.println("or : java OsmCutter <lookup-file> <out-tile-dir> <out-way-file> <out-rel-file> <inputfile>");
return;
}
new OsmCutter().process(
new File( args[0] )
, new File( args[1] )
, new File( args[2] )
, new File( args[3] )
, args.length > 4 ? new File( args[4] ) : null );
}
private BExpressionContext _expctxWay;
private BExpressionContext _expctxNode;
public void process (File lookupFile, File outTileDir, File wayFile, File relFile, File mapFile) throws Exception
{
if ( !lookupFile.exists() )
{
throw new IllegalArgumentException( "lookup-file: " + lookupFile + " does not exist" );
}
_expctxWay = new BExpressionContext("way");
_expctxWay.readMetaData( lookupFile );
_expctxNode = new BExpressionContext("node");
_expctxNode.readMetaData( lookupFile );
this.outTileDir = outTileDir;
if ( !outTileDir.isDirectory() ) throw new RuntimeException( "out tile directory " + outTileDir + " does not exist" );
wayDos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( wayFile ) ) );
cyclewayDos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( relFile ) ) );
// read the osm map into memory
long t0 = System.currentTimeMillis();
new OsmParser().readMap( mapFile, this, this, this );
long t1 = System.currentTimeMillis();
System.out.println( "parsing time (ms) =" + (t1-t0) );
// close all files
closeTileOutStreams();
wayDos.close();
cyclewayDos.close();
/* System.out.println( "-------- way-statistics -------- " );
_expctxWay.dumpStatistics();
System.out.println( "-------- node-statistics -------- " );
_expctxNode.dumpStatistics();
*/
System.out.println( statsLine() );
}
private void checkStats()
{
if ( (++recordCnt % 100000) == 0 ) System.out.println( statsLine() );
}
private String statsLine()
{
return "records read: " + recordCnt + " nodes=" + nodesParsed + " ways=" + waysParsed + " rels=" + relsParsed + " changesets=" + changesetsParsed;
}
@Override
public void nextNode( NodeData n ) throws Exception
{
nodesParsed++;
checkStats();
if ( n.getTagsOrNull() != null )
{
int[] lookupData = _expctxNode.createNewLookupData();
for( String key : n.getTagsOrNull().keySet() )
{
String value = n.getTag( key );
_expctxNode.addLookupValue( key, value, lookupData );
}
n.description = _expctxNode.encode(lookupData);
}
// write node to file
int tileIndex = getTileIndex( n.ilon, n.ilat );
if ( tileIndex >= 0 )
{
DataOutputStream dos = getOutStreamForTile( tileIndex );
n.writeTo( dos );
}
}
@Override
public void nextWay( WayData w ) throws Exception
{
waysParsed++;
checkStats();
// filter out non-highway ways
if ( w.getTag( "highway" ) == null )
{
// ... but eventually fake a ferry tag
if ( "ferry".equals( w.getTag( "route" ) ) )
{
w.putTag( "highway", "ferry" );
}
else
{
return;
}
}
// encode tags
if ( w.getTagsOrNull() != null )
{
int[] lookupData = _expctxWay.createNewLookupData();
for( String key : w.getTagsOrNull().keySet() )
{
String value = w.getTag( key );
_expctxWay.addLookupValue( key, value, lookupData );
}
w.description = _expctxWay.encode(lookupData);
}
w.writeTo( wayDos );
}
@Override
public void nextRelation( RelationData r ) throws Exception
{
relsParsed++;
checkStats();
// filter out non-cycle relations
if ( ! "bicycle".equals( r.getTag( "route" ) ) )
{
return;
}
for ( int i=0; i<r.ways.size();i++ )
{
long wid = r.ways.get(i);
writeId( cyclewayDos, wid );
}
}
private int getTileIndex( int ilon, int ilat )
{
int lon = ilon / 45000000;
int lat = ilat / 30000000;
if ( lon < 0 || lon > 7 || lat < 0 || lat > 5 )
{
System.out.println( "warning: ignoring illegal pos: " + ilon + "," + ilat );
return -1;
}
return lon*6 + lat;
}
protected String getNameForTile( int tileIndex )
{
int lon = (tileIndex / 6 ) * 45 - 180;
int lat = (tileIndex % 6 ) * 30 - 90;
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
return slon + "_" + slat + ".tls";
}
}

View file

@ -0,0 +1,29 @@
/**
* Container for link between two Osm nodes (pre-pocessor version)
*
* @author ab
*/
package btools.mapcreator;
public final class OsmLinkP
{
/**
* The description bitmap is mainly the way description
* used to calculate the costfactor
*/
public long descriptionBitmap;
/**
* The target is either the next link or the target node
*/
public OsmNodeP targetNode;
public OsmLinkP next;
public boolean counterLinkWritten( )
{
return descriptionBitmap == 0L;
}
}

View file

@ -0,0 +1,243 @@
/**
* Container for an osm node (pre-pocessor version)
*
* @author ab
*/
package btools.mapcreator;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class OsmNodeP implements Comparable<OsmNodeP>
{
public static final int EXTERNAL_BITMASK = 0x80;
public static final int FIRSTFORWAY_BITMASK = 0x40;
public static final int TRANSFERNODE_BITMASK = 0x20;
public static final int WRITEDESC_BITMASK = 0x10;
public static final int SKIPDETAILS_BITMASK = 0x08;
public static final int NODEDESC_BITMASK = 0x04;
/**
* The latitude
*/
public int ilat;
/**
* The longitude
*/
public int ilon;
/**
* The links to other nodes
*/
public OsmLinkP firstlink = null;
/**
* The elevation
*/
public short selev;
public boolean isBorder = false;
public byte wayAndBits = -1; // use for bridge/tunnel logic
// interface OsmPos
public int getILat()
{
return ilat;
}
public int getILon()
{
return ilon;
}
public short getSElev()
{
// if all bridge or all tunnel, elevation=no-data
return (wayAndBits & 24) == 0 ? selev : Short.MIN_VALUE;
}
public double getElev()
{
return selev / 4.;
}
public void addLink( OsmLinkP link )
{
if ( firstlink != null ) link.next = firstlink;
firstlink = link;
}
public long getNodeDecsription()
{
return 0L;
}
public void writeNodeData( DataOutputStream os ) throws IOException
{
int lonIdx = ilon/62500;
int latIdx = ilat/62500;
// buffer the body to first calc size
ByteArrayOutputStream bos = new ByteArrayOutputStream( );
DataOutputStream os2 = new DataOutputStream( bos );
os2.writeShort( getSElev() );
int nlinks = 0;
// hack: write node-desc as link tag (copy cycleway-bits)
long nodeDescription = getNodeDecsription();
for( OsmLinkP link0 = firstlink; link0 != null; link0 = link0.next )
{
nlinks++;
OsmLinkP link = link0;
OsmNodeP origin = this;
int skipDetailBit = link0.counterLinkWritten() ? SKIPDETAILS_BITMASK : 0;
// first pass just to see if that link is consistent
while( link != null )
{
OsmNodeP target = link.targetNode;
if ( !target.isTransferNode() )
{
break;
}
// next link is the one (of two), does does'nt point back
for( link = target.firstlink; link != null; link = link.next )
{
if ( link.targetNode != origin ) break;
}
origin = target;
}
if ( link == null ) continue; // dead end
if ( skipDetailBit == 0)
{
link = link0;
}
origin = this;
long lastDescription = 0;
while( link != null )
{
OsmNodeP target = link.targetNode;
int tranferbit = target.isTransferNode() ? TRANSFERNODE_BITMASK : 0;
int writedescbit = link.descriptionBitmap != lastDescription ? WRITEDESC_BITMASK : 0;
int nodedescbit = nodeDescription != 0L ? NODEDESC_BITMASK : 0;
if ( skipDetailBit != 0 )
{
writedescbit = 0;
}
int targetLonIdx = target.ilon/62500;
int targetLatIdx = target.ilat/62500;
if ( targetLonIdx == lonIdx && targetLatIdx == latIdx )
{
// reduced position for internal target
os2.writeByte( tranferbit | writedescbit | nodedescbit | skipDetailBit );
os2.writeShort( (short)(target.ilon - lonIdx*62500 - 31250) );
os2.writeShort( (short)(target.ilat - latIdx*62500 - 31250) );
}
else
{
// full position for external target
os2.writeByte( tranferbit | writedescbit | nodedescbit | skipDetailBit | EXTERNAL_BITMASK );
os2.writeInt( target.ilon );
os2.writeInt( target.ilat );
}
if ( writedescbit != 0 )
{
os2.writeLong( link.descriptionBitmap );
}
if ( nodedescbit != 0 )
{
os2.writeLong( nodeDescription );
nodeDescription = 0L;
}
lastDescription = link.descriptionBitmap;
if ( tranferbit == 0)
{
target.markLinkWritten( origin );
break;
}
os2.writeShort( target.getSElev() );
// next link is the one (of two), does does'nt point back
for( link = target.firstlink; link != null; link = link.next )
{
if ( link.targetNode != origin ) break;
}
if ( link == null ) throw new RuntimeException( "follow-up link not found for transfer-node!" );
origin = target;
}
}
// calculate the body size
int bodySize = bos.size();
os.writeShort( (short)(ilon - lonIdx*62500 - 31250) );
os.writeShort( (short)(ilat - latIdx*62500 - 31250) );
os.writeInt( bodySize );
bos.writeTo( os );
}
public String toString2()
{
return (ilon-180000000) + "_" + (ilat-90000000) + "_" + (selev/4);
}
public long getIdFromPos()
{
return ((long)ilon)<<32 | ilat;
}
public boolean isTransferNode()
{
return (!isBorder) && _linkCnt() == 2;
}
private int _linkCnt()
{
int cnt = 0;
for( OsmLinkP link = firstlink; link != null; link = link.next )
{
cnt++;
}
return cnt;
}
// mark the link to the given node as written,
// don't want to write the counter-direction
// in full details
public void markLinkWritten( OsmNodeP t )
{
for( OsmLinkP link = firstlink; link != null; link = link.next )
{
if ( link.targetNode == t) link.descriptionBitmap = 0L;
}
}
/**
* Compares two OsmNodes for position ordering.
*
* @return -1,0,1 depending an comparson result
*/
public int compareTo( OsmNodeP n )
{
long id1 = getIdFromPos();
long id2 = n.getIdFromPos();
if ( id1 < id2 ) return -1;
if ( id1 > id2 ) return 1;
return 0;
}
}

View file

@ -0,0 +1,39 @@
/**
* Container for an osm node with tags (pre-pocessor version)
*
* @author ab
*/
package btools.mapcreator;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class OsmNodePT extends OsmNodeP
{
public long descriptionBits;
public byte wayOrBits = 0; // used to propagate bike networks to nodes
public OsmNodePT()
{
}
public OsmNodePT( long descriptionBits )
{
this.descriptionBits = descriptionBits;
}
@Override
public long getNodeDecsription()
{
return descriptionBits | (long)( (wayOrBits & 6) >> 1 );
}
@Override
public boolean isTransferNode()
{
return false; // always have descriptionBits so never transfernode
}
}

View file

@ -0,0 +1,240 @@
package btools.mapcreator;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.zip.GZIPInputStream;
/**
* Parser for OSM data
*
* @author ab
*/
public class OsmParser extends MapCreatorBase
{
private BufferedReader _br;
private NodeListener nListener;
private WayListener wListener;
private RelationListener rListener;
public void readMap( File mapFile,
NodeListener nListener,
WayListener wListener,
RelationListener rListener ) throws Exception
{
this.nListener = nListener;
this.wListener = wListener;
this.rListener = rListener;
if ( mapFile == null )
{
_br = new BufferedReader(new InputStreamReader(System.in));
}
else
{
if ( mapFile.getName().endsWith( ".gz" ) )
{
_br = new BufferedReader(new InputStreamReader( new GZIPInputStream( new FileInputStream( mapFile ) ) ) );
}
else
{
_br = new BufferedReader(new InputStreamReader( new FileInputStream( mapFile ) ) );
}
}
for(;;)
{
String line = _br.readLine();
if ( line == null ) break;
if ( checkNode( line ) ) continue;
if ( checkWay( line ) ) continue;
if ( checkRelation( line ) ) continue;
if ( checkChangeset( line ) ) continue;
}
if ( mapFile != null )
{
_br.close();
}
}
private boolean checkNode( String line ) throws Exception
{
int idx0 = line.indexOf( "<node id=\"" );
if ( idx0 < 0 ) return false;
idx0 += 10;
int idx1 = line.indexOf( '"', idx0 );
long nodeId = Long.parseLong( line.substring( idx0, idx1 ) );
int idx2 = line.indexOf( " lat=\"" );
if ( idx2 < 0 ) return false;
idx2 += 6;
int idx3 = line.indexOf( '"', idx2 );
double lat = Double.parseDouble( line.substring( idx2, idx3 ) );
int idx4 = line.indexOf( " lon=\"" );
if ( idx4 < 0 ) return false;
idx4 += 6;
int idx5 = line.indexOf( '"', idx4 );
double lon = Double.parseDouble( line.substring( idx4, idx5 ) );
NodeData n = new NodeData( nodeId, lon, lat );
if ( !line.endsWith( "/>" ) )
{
// read additional tags
for(;;)
{
String l2 = _br.readLine();
if ( l2 == null ) return false;
int i2;
if ( (i2 = l2.indexOf( "<tag k=\"" )) >= 0 )
{ // property-tag
i2 += 8;
int ri2 = l2.indexOf( '"', i2 );
String key = l2.substring( i2, ri2 );
i2 = l2.indexOf( " v=\"", ri2 );
if ( i2 >= 0 )
{
i2 += 4;
int ri3 = l2.indexOf( '"', i2 );
String value = l2.substring( i2, ri3 );
n.putTag( key, value );
}
}
else if ( l2.indexOf( "</node>" ) >= 0 )
{ // end-tag
break;
}
}
}
nListener.nextNode( n );
return true;
}
private boolean checkWay( String line ) throws Exception
{
int idx0 = line.indexOf( "<way id=\"" );
if ( idx0 < 0 ) return false;
idx0 += 9;
int idx1 = line.indexOf( '"', idx0 );
long id = Long.parseLong( line.substring( idx0, idx1 ) );
WayData w = new WayData( id );
// read the nodes
for(;;)
{
String l2 = _br.readLine();
if ( l2 == null ) return false;
int i2;
if ( (i2 = l2.indexOf( "<nd ref=\"" )) >= 0 )
{ // node reference
i2 += 9;
int ri2 = l2.indexOf( '"', i2 );
long nid = Long.parseLong( l2.substring( i2, ri2 ) );
w.nodes.add( nid );
}
else if ( (i2 = l2.indexOf( "<tag k=\"" )) >= 0 )
{ // property-tag
i2 += 8;
int ri2 = l2.indexOf( '"', i2 );
String key = l2.substring( i2, ri2 );
i2 = l2.indexOf( " v=\"", ri2 );
if ( i2 >= 0 )
{
i2 += 4;
int ri3 = l2.indexOf( '"', i2 );
String value = l2.substring( i2, ri3 );
w.putTag( key, value );
}
}
else if ( l2.indexOf( "</way>" ) >= 0 )
{ // end-tag
break;
}
}
wListener.nextWay( w );
return true;
}
private boolean checkChangeset( String line ) throws Exception
{
int idx0 = line.indexOf( "<changeset id=\"" );
if ( idx0 < 0 ) return false;
if ( !line.endsWith( "/>" ) )
{
int loopcheck = 0;
for(;;)
{
String l2 = _br.readLine();
if ( l2.indexOf("</changeset>") >= 0 || ++loopcheck > 10000 ) break;
}
}
return true;
}
private boolean checkRelation( String line ) throws Exception
{
int idx0 = line.indexOf( "<relation id=\"" );
if ( idx0 < 0 ) return false;
idx0 += 14;
int idx1 = line.indexOf( '"', idx0 );
long rid = Long.parseLong( line.substring( idx0, idx1 ) );
RelationData r = new RelationData( rid );
// read the nodes
for(;;)
{
String l2 = _br.readLine();
if ( l2 == null ) return false;
int i2;
if ( (i2 = l2.indexOf( "<member type=\"way\" ref=\"" )) >= 0 )
{ // node reference
i2 += 24;
int ri2 = l2.indexOf( '"', i2 );
long wid = Long.parseLong( l2.substring( i2, ri2 ) );
r.ways.add( wid );
}
else if ( (i2 = l2.indexOf( "<tag k=\"" )) >= 0 )
{ // property-tag
i2 += 8;
int ri2 = l2.indexOf( '"', i2 );
String key = l2.substring( i2, ri2 );
i2 = l2.indexOf( " v=\"", ri2 );
if ( i2 >= 0 )
{
i2 += 4;
int ri3 = l2.indexOf( '"', i2 );
String value = l2.substring( i2, ri3 );
r.putTag( key, value );
}
}
else if ( l2.indexOf( "</relation>" ) >= 0 )
{ // end-tag
break;
}
}
rListener.nextRelation( r );
return true;
}
}

View file

@ -0,0 +1,203 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import btools.util.CompactLongSet;
import btools.util.CompactLongMap;
import btools.util.FrozenLongSet;
import btools.util.FrozenLongMap;
/**
* PosUnifier does 3 steps in map-processing:
*
* - unify positions
* - add srtm elevation data
* - make a bordernodes file containing net data
* from the bordernids-file just containing ids
*
* @author ab
*/
public class PosUnifier extends MapCreatorBase
{
private DataOutputStream nodesOutStream;
private DataOutputStream borderNodesOut;
private File nodeTilesOut;
private CompactLongSet positionSet;
private HashMap<String,SrtmData> srtmmap ;
private int lastStrmLonIdx;
private int lastStrmLatIdx;
private SrtmData lastSrtmData;
private String srtmdir;
private int totalLatSteps = 0;
private int totalLonSteps = 0;
private CompactLongSet borderNids;
public static void main(String[] args) throws Exception
{
System.out.println("*** PosUnifier: Unify position values and enhance elevation");
if (args.length != 5)
{
System.out.println("usage: java PosUnifier <node-tiles-in> <node-tiles-out> <bordernids-in> <bordernodes-out> <strm-data-dir>" );
return;
}
new PosUnifier().process( new File( args[0] ), new File( args[1] ), new File( args[2] ), new File( args[3] ), args[4] );
}
public void process( File nodeTilesIn, File nodeTilesOut, File bordernidsinfile, File bordernodesoutfile, String srtmdir ) throws Exception
{
this.nodeTilesOut = nodeTilesOut;
this.srtmdir = srtmdir;
// read border nids set
DataInputStream dis = createInStream( bordernidsinfile );
borderNids = new CompactLongSet();
try
{
for(;;)
{
long nid = readId( dis );
if ( !borderNids.contains( nid ) ) borderNids.fastAdd( nid );
}
}
catch( EOFException eof )
{
dis.close();
}
borderNids = new FrozenLongSet( borderNids );
// process all files
borderNodesOut = createOutStream( bordernodesoutfile );
new NodeIterator( this, true ).processDir( nodeTilesIn, ".n5d" );
borderNodesOut.close();
}
@Override
public void nodeFileStart( File nodefile ) throws Exception
{
resetSrtm();
nodesOutStream = createOutStream( fileFromTemplate( nodefile, nodeTilesOut, "u5d" ) );
positionSet = new CompactLongSet();
}
@Override
public void nextNode( NodeData n ) throws Exception
{
SrtmData srtm = srtmForNode( n.ilon, n.ilat );
n.selev = srtm == null ? Short.MIN_VALUE : srtm.getElevation( n.ilon, n.ilat);
findUniquePos( n );
n.writeTo( nodesOutStream );
if ( borderNids.contains( n.nid ) )
{
n.writeTo( borderNodesOut );
}
}
@Override
public void nodeFileEnd( File nodeFile ) throws Exception
{
nodesOutStream.close();
}
private void findUniquePos( NodeData n )
{
// fix the position for uniqueness
int lonmod = n.ilon % 1000000;
int londelta = lonmod < 500000 ? 1 : -1;
int latmod = n.ilat % 1000000;
int latdelta = latmod < 500000 ? 1 : -1;
for(int latsteps = 0; latsteps < 100; latsteps++)
{
for(int lonsteps = 0; lonsteps <= latsteps; lonsteps++)
{
int lon = n.ilon + lonsteps*londelta;
int lat = n.ilat + latsteps*latdelta;
long pid = ((long)lon)<<32 | lat; // id from position
if ( !positionSet.contains( pid ) )
{
totalLonSteps += lonsteps;
totalLatSteps += latsteps;
positionSet.fastAdd( pid );
n.ilon = lon;
n.ilat = lat;
return;
}
}
}
System.out.println( "*** WARNING: cannot unify position for: " + n.ilon + " " + n.ilat );
}
/**
* get the srtm data set for a position
* srtm coords are srtm_<srtmLon>_<srtmLat>
* where srtmLon = 180 + lon, srtmLat = 60 - lat
*/
private SrtmData srtmForNode( int ilon, int ilat ) throws Exception
{
int srtmLonIdx = (ilon+5000000)/5000000;
int srtmLatIdx = (154999999-ilat)/5000000;
if ( srtmLatIdx < 1 || srtmLatIdx > 24 || srtmLonIdx < 1 || srtmLonIdx > 72 )
{
return null;
}
if ( srtmLonIdx == lastStrmLonIdx && srtmLatIdx == lastStrmLatIdx )
{
return lastSrtmData;
}
lastStrmLonIdx = srtmLonIdx;
lastStrmLatIdx = srtmLatIdx;
StringBuilder sb = new StringBuilder( 16 );
sb.append( "srtm_" );
sb.append( (char)('0' + srtmLonIdx/10 ) ).append( (char)('0' + srtmLonIdx%10 ) ).append( '_' );
sb.append( (char)('0' + srtmLatIdx/10 ) ).append( (char)('0' + srtmLatIdx%10 ) ).append( ".zip" );
String filename = sb.toString();
lastSrtmData = srtmmap.get( filename );
if ( lastSrtmData == null && !srtmmap.containsKey( filename ) )
{
File f = new File( new File( srtmdir ), filename );
System.out.println( "reading: " + f + " ilon=" + ilon + " ilat=" + ilat );
if ( f.exists() )
{
try
{
lastSrtmData = new SrtmData( f );
}
catch( Exception e )
{
System.out.println( "**** ERROR reading " + f + " ****" );
}
}
srtmmap.put( filename, lastSrtmData );
}
return lastSrtmData;
}
private void resetSrtm()
{
srtmmap = new HashMap<String,SrtmData>();
lastStrmLonIdx = -1;
lastStrmLatIdx = -1;
lastSrtmData = null;
}
}

View file

@ -0,0 +1,37 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import btools.util.*;
/**
* Container for relation data on the preprocessor level
*
* @author ab
*/
public class RelationData extends MapCreatorBase
{
public long rid;
public long description;
public LongList ways;
public RelationData( long id )
{
rid = id;
ways = new LongList( 16 );
}
public RelationData( long id, LongList ways )
{
rid = id;
this.ways = ways;
}
}

View file

@ -0,0 +1,13 @@
package btools.mapcreator;
import java.io.File;
/**
* Callbacklistener for Relations
*
* @author ab
*/
public interface RelationListener
{
void nextRelation( RelationData data ) throws Exception;
}

View file

@ -0,0 +1,174 @@
/**
* This is a wrapper for a 5*5 degree srtm file in ascii/zip-format
*
* - filter out unused nodes according to the way file
* - enhance with SRTM elevation data
* - split further in smaller (5*5 degree) tiles
*
* @author ab
*/
package btools.mapcreator;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class SrtmData
{
public int ncols;
public int nrows;
public double xllcorner;
public double yllcorner;
public double cellsize;
public int nodata_value;
public short[] eval_array;
private double minlon;
private double maxlon;
private double minlat;
private double maxlat;
public void init()
{
minlon = xllcorner;
maxlon = minlon + cellsize*ncols;
minlat = yllcorner;
maxlat = minlat + cellsize*nrows;
}
private boolean missingData = false;
public short getElevation( int ilon, int ilat )
{
double lon = ilon / 1000000. - 180.;
double lat = ilat / 1000000. - 90.;
double dcol = (lon - minlon)/cellsize -0.5;
double drow = (lat - minlat)/cellsize -0.5;
int row = (int)drow;
int col = (int)dcol;
if ( col < 0 ) col = 0;
if ( col >= ncols-1 ) col = ncols - 2;
if ( row < 0 ) row = 0;
if ( row >= nrows-1 ) row = nrows - 2;
double wrow = drow-row;
double wcol = dcol-col;
missingData = false;
double eval = (1.-wrow)*(1.-wcol)*get(row ,col )
+ ( wrow)*(1.-wcol)*get(row+1,col )
+ (1.-wrow)*( wcol)*get(row ,col+1)
+ ( wrow)*( wcol)*get(row+1,col+1);
return missingData ? Short.MIN_VALUE : (short)(eval);
}
private short get( int r, int c )
{
short e = eval_array[r*ncols + c ];
if ( e == Short.MIN_VALUE ) missingData = true;
return e;
}
public SrtmData( File file ) throws Exception
{
ZipInputStream zis = new ZipInputStream( new FileInputStream( file ) );
try
{
for(;;)
{
ZipEntry ze = zis.getNextEntry();
if ( ze.getName().endsWith( ".asc" ) )
{
readFromStream( zis );
/* // test
int[] ca = new int[]{ 50477121, 8051915, // 181
50477742, 8047408, // 154
50477189, 8047308, // 159
};
for( int i=0; i<ca.length; i+=2 )
{
int lat=ca[i] + 90000000;
int lon=ca[i+1] + 180000000;
System.err.println( "lat=" + lat + " lon=" + lon + " elev=" + getElevation( lon, lat )/4. );
}
// end test
*/
return;
}
}
}
finally
{
zis.close();
}
}
public void readFromStream( InputStream is ) throws Exception
{
BufferedReader br = new BufferedReader(new InputStreamReader(is));
int linenr = 0;
for(;;)
{
linenr++;
if ( linenr <= 6 )
{
String line = br.readLine();
if ( linenr == 1 ) ncols = Integer.parseInt( line.substring(14) );
else if ( linenr == 2 ) nrows = Integer.parseInt( line.substring(14) );
else if ( linenr == 3 ) xllcorner = Double.parseDouble( line.substring(14) );
else if ( linenr == 4 ) yllcorner = Double.parseDouble( line.substring(14) );
else if ( linenr == 5 ) cellsize = Double.parseDouble( line.substring(14) );
else if ( linenr == 6 )
{
nodata_value = Integer.parseInt( line.substring(14) );
eval_array = new short[ncols * nrows];
}
}
else
{
int row = 0;
int col = 0;
int n = 0;
boolean negative = false;
for(;;)
{
int c = br.read();
if ( c < 0 ) break;
if ( c == ' ' )
{
if ( negative ) n = -n;
short val = n == nodata_value ? Short.MIN_VALUE : (short)(n*4);
if ( val < -1000 ) val = Short.MIN_VALUE;
eval_array[ (nrows-1-row)*ncols + col ] = val;
if (++col == ncols )
{
col = 0;
++row;
}
n = 0;
negative = false;
}
else if ( c >= '0' && c <= '9' )
{
n = 10*n + (c-'0');
}
else if ( c == '-' )
{
negative = true;
}
}
break;
}
}
init();
br.close();
}
}

View file

@ -0,0 +1,127 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import btools.util.*;
/**
* WayCutter does 2 step in map-processing:
*
* - cut the way file into 45*30 - pieces
* - enrich ways with relation information
*
* @author ab
*/
public class WayCutter extends MapCreatorBase
{
private CompactLongSet cyclewayset;
private DenseLongMap tileIndexMap;
public static void main(String[] args) throws Exception
{
System.out.println("*** WayCutter: Soft-Cut way-data into tiles");
if (args.length != 4)
{
System.out.println("usage: java WayCutter <node-tiles-in> <way-file-in> <way-tiles-out> <relation-file>" );
return;
}
new WayCutter().process( new File( args[0] ), new File( args[1] ), new File( args[2] ), new File( args[3] ) );
}
public void process( File nodeTilesIn, File wayFileIn, File wayTilesOut, File relationFileIn ) throws Exception
{
this.outTileDir = wayTilesOut;
// *** read the relation file into a set (currently cycleway processing only)
cyclewayset = new CompactLongSet();
DataInputStream dis = createInStream( relationFileIn );
try
{
for(;;)
{
long wid = readId( dis );
if ( !cyclewayset.contains( wid ) ) cyclewayset.add( wid );
}
}
catch( EOFException eof )
{
dis.close();
}
System.out.println( "marked cycleways: " + cyclewayset.size() );
// *** read all nodes into tileIndexMap
tileIndexMap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap( 6 ) : new TinyDenseLongMap();
new NodeIterator( this, false ).processDir( nodeTilesIn, ".tlf" );
// *** finally process the way-file, cutting into pieces
new WayIterator( this, true ).processFile( wayFileIn );
closeTileOutStreams();
}
@Override
public void nextNode( NodeData n ) throws Exception
{
tileIndexMap.put( n.nid, getTileIndex( n.ilon, n.ilat ) );
}
@Override
public void nextWay( WayData data ) throws Exception
{
// propagate the cycleway-bit
if ( cyclewayset.contains( data.wid ) )
{
data.description |= 2;
}
long waytileset = 0;
int nnodes = data.nodes.size();
// determine the tile-index for each node
for (int i=0; i<nnodes; i++ )
{
int tileIndex = tileIndexMap.getInt( data.nodes.get(i) );
if ( tileIndex != -1 )
{
waytileset |= ( 1L << tileIndex );
}
}
// now write way to all tiles hit
for( int tileIndex=0; tileIndex<54; tileIndex++ )
{
if ( ( waytileset & ( 1L << tileIndex ) ) == 0 )
{
continue;
}
data.writeTo( getOutStreamForTile( tileIndex ) );
}
}
private int getTileIndex( int ilon, int ilat )
{
int lon = ilon / 45000000;
int lat = ilat / 30000000;
if ( lon < 0 || lon > 7 || lat < 0 || lat > 5 ) throw new IllegalArgumentException( "illegal pos: " + ilon + "," + ilat );
return lon*6 + lat;
}
protected String getNameForTile( int tileIndex )
{
int lon = (tileIndex / 6 ) * 45 - 180;
int lat = (tileIndex % 6 ) * 30 - 90;
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
return slon + "_" + slat + ".wtl";
}
}

View file

@ -0,0 +1,146 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import btools.util.*;
/**
* WayCutter5 does 2 step in map-processing:
*
* - cut the 45*30 way files into 5*5 pieces
* - create a file containing all border node ids
*
* @author ab
*/
public class WayCutter5 extends MapCreatorBase
{
private DataOutputStream borderNidsOutStream;
private DenseLongMap tileIndexMap;
private File nodeTilesIn;
private int lonoffset;
private int latoffset;
public static void main(String[] args) throws Exception
{
System.out.println("*** WayCutter5: Soft-Cut way-data into tiles");
if (args.length != 4)
{
System.out.println("usage: java WayCutter5 <node-tiles-in> <way-tiles-in> <way-tiles-out> <border-nids-out>" );
return;
}
new WayCutter5().process( new File( args[0] ), new File( args[1] ), new File( args[2] ), new File( args[3] ) );
}
public void process( File nodeTilesIn, File wayTilesIn, File wayTilesOut, File borderNidsOut ) throws Exception
{
this.nodeTilesIn = nodeTilesIn;
this.outTileDir = wayTilesOut;
borderNidsOutStream = createOutStream( borderNidsOut );
new WayIterator( this, true ).processDir( wayTilesIn, ".wtl" );
borderNidsOutStream.close();
}
@Override
public void wayFileStart( File wayfile ) throws Exception
{
// read corresponding node-file into tileIndexMap
String name = wayfile.getName();
String nodefilename = name.substring( 0, name.length()-3 ) + "tlf";
File nodefile = new File( nodeTilesIn, nodefilename );
tileIndexMap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap( 6 ) : new TinyDenseLongMap();
lonoffset = -1;
latoffset = -1;
new NodeIterator( this, false ).processFile( nodefile );
}
@Override
public void nextNode( NodeData n ) throws Exception
{
tileIndexMap.put( n.nid, getTileIndex( n.ilon, n.ilat ) );
}
@Override
public void nextWay( WayData data ) throws Exception
{
long waytileset = 0;
int nnodes = data.nodes.size();
int[] tiForNode = new int[nnodes];
// determine the tile-index for each node
for (int i=0; i<nnodes; i++ )
{
int tileIndex = tileIndexMap.getInt( data.nodes.get(i) );
if ( tileIndex != -1 )
{
waytileset |= ( 1L << tileIndex );
}
tiForNode[i] = tileIndex;
}
// now write way to all tiles hit
for( int tileIndex=0; tileIndex<54; tileIndex++ )
{
if ( ( waytileset & ( 1L << tileIndex ) ) == 0 )
{
continue;
}
data.writeTo( getOutStreamForTile( tileIndex ) );
}
// and write edge nodes to the border-nid file
for( int i=0; i < nnodes; i++ )
{
int ti = tiForNode[i];
if ( ti != -1 )
{
if ( ( i > 0 && tiForNode[i-1] != ti ) || (i+1 < nnodes && tiForNode[i+1] != ti ) )
{
writeId( borderNidsOutStream, data.nodes.get(i) );
}
}
}
}
@Override
public void wayFileEnd( File wayFile ) throws Exception
{
closeTileOutStreams();
}
private int getTileIndex( int ilon, int ilat )
{
int lonoff = (ilon / 45000000 ) * 45;
int latoff = (ilat / 30000000 ) * 30;
if ( lonoffset == -1 ) lonoffset = lonoff;
if ( latoffset == -1 ) latoffset = latoff;
if ( lonoff != lonoffset || latoff != latoffset )
throw new IllegalArgumentException( "inconsistent node: " + ilon + " " + ilat );
int lon = (ilon / 5000000) % 9;
int lat = (ilat / 5000000) % 6;
if ( lon < 0 || lon > 8 || lat < 0 || lat > 5 ) throw new IllegalArgumentException( "illegal pos: " + ilon + "," + ilat );
return lon*6 + lat;
}
protected String getNameForTile( int tileIndex )
{
int lon = (tileIndex / 6 ) * 5 + lonoffset - 180;
int lat = (tileIndex % 6 ) * 5 + latoffset - 90;
String slon = lon < 0 ? "W" + (-lon) : "E" + lon;
String slat = lat < 0 ? "S" + (-lat) : "N" + lat;
return slon + "_" + slat + ".wt5";
}
}

View file

@ -0,0 +1,62 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import btools.util.*;
/**
* Container for waydata on the preprocessor level
*
* @author ab
*/
public class WayData extends MapCreatorBase
{
public long wid;
public long description;
public LongList nodes;
public WayData( long id )
{
wid = id;
nodes = new LongList( 16 );
}
public WayData( long id, LongList nodes )
{
wid = id;
this.nodes = nodes;
}
public WayData( DataInputStream di ) throws Exception
{
nodes = new LongList( 16 );
wid = readId( di) ;
description = di.readLong();
for (;;)
{
long nid = readId( di );
if ( nid == -1 ) break;
nodes.add( nid );
}
}
public void writeTo( DataOutputStream dos ) throws Exception
{
writeId( dos, wid );
dos.writeLong( description );
int size = nodes.size();
for( int i=0; i < size; i++ )
{
writeId( dos, nodes.get( i ) );
}
writeId( dos, -1 ); // stopbyte
}
}

View file

@ -0,0 +1,76 @@
package btools.mapcreator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import btools.util.*;
/**
* Iterate over a singe wayfile or a directory
* of waytiles and feed the ways to the callback listener
*
* @author ab
*/
public class WayIterator extends MapCreatorBase
{
private WayListener listener;
private boolean delete;
public WayIterator( WayListener wayListener, boolean deleteAfterReading )
{
listener = wayListener;
delete = deleteAfterReading;
}
public void processDir( File indir, String inSuffix ) throws Exception
{
if ( !indir.isDirectory() )
{
throw new IllegalArgumentException( "not a directory: " + indir );
}
File[] af = sortBySizeAsc( indir.listFiles() );
for( int i=0; i<af.length; i++ )
{
File wayfile = af[i];
if ( wayfile.getName().endsWith( inSuffix ) )
{
processFile( wayfile );
}
}
}
public void processFile(File wayfile) throws Exception
{
System.out.println( "*** WayIterator reading: " + wayfile );
listener.wayFileStart( wayfile );
DataInputStream di = new DataInputStream( new BufferedInputStream ( new FileInputStream( wayfile ) ) );
try
{
for(;;)
{
WayData w = new WayData( di );
listener.nextWay( w );
}
}
catch( EOFException eof )
{
di.close();
}
listener.wayFileEnd( wayfile );
if ( delete && "true".equals( System.getProperty( "deletetmpfiles" ) ))
{
wayfile.delete();
}
}
}

View file

@ -0,0 +1,289 @@
package btools.mapcreator;
import java.io.*;
import java.util.*;
import btools.util.*;
import btools.expressions.BExpressionContext;
/**
* WayLinker finally puts the pieces together
* to create the rd5 files. For each 5*5 tile,
* the corresponding nodefile and wayfile is read,
* plus the (global) bordernodes file, and an rd5
* is written
*
* @author ab
*/
public class WayLinker extends MapCreatorBase
{
private File nodeTilesIn;
private File dataTilesOut;
private File borderFileIn;
private String dataTilesSuffix;
private boolean readingBorder;
private CompactLongMap<OsmNodeP> nodesMap;
private List<OsmNodeP> nodesList;
private CompactLongSet borderSet;
private short lookupVersion;
private BExpressionContext expctxWay;
private int minLon;
private int minLat;
private void reset()
{
minLon = -1;
minLat = -1;
nodesMap = new CompactLongMap<OsmNodeP>();
borderSet = new CompactLongSet();
}
public static void main(String[] args) throws Exception
{
System.out.println("*** WayLinker: Format a regionof an OSM map for routing");
if (args.length != 7)
{
System.out.println("usage: java WayLinker <node-tiles-in> <way-tiles-in> <bordernodes> <lookup-file> <profile-file> <data-tiles-out> <data-tiles-suffix> ");
return;
}
new WayLinker().process( new File( args[0] ), new File( args[1] ), new File( args[2] ), new File( args[3] ), new File( args[4] ), new File( args[5] ), args[6] );
}
public void process( File nodeTilesIn, File wayTilesIn, File borderFileIn, File lookupFile, File profileFile, File dataTilesOut, String dataTilesSuffix ) throws Exception
{
this.nodeTilesIn = nodeTilesIn;
this.dataTilesOut = dataTilesOut;
this.borderFileIn = borderFileIn;
this.dataTilesSuffix = dataTilesSuffix;
// read lookup file to get the lookup-version
expctxWay = new BExpressionContext("way");
expctxWay.readMetaData( lookupFile );
lookupVersion = expctxWay.lookupVersion;
expctxWay.parseFile( profileFile, "global" );
// then process all segments
new WayIterator( this, true ).processDir( wayTilesIn, ".wt5" );
}
@Override
public void wayFileStart( File wayfile ) throws Exception
{
// process corresponding node-file, if any
File nodeFile = fileFromTemplate( wayfile, nodeTilesIn, "u5d" );
if ( nodeFile.exists() )
{
reset();
// read the border file
readingBorder = true;
new NodeIterator( this, false ).processFile( borderFileIn );
borderSet = new FrozenLongSet( borderSet );
// read this tile's nodes
readingBorder = false;
new NodeIterator( this, false ).processFile( nodeFile );
// freeze the nodes-map
FrozenLongMap<OsmNodeP> nodesMapFrozen = new FrozenLongMap<OsmNodeP>( nodesMap );
nodesMap = nodesMapFrozen;
nodesList = nodesMapFrozen.getValueList();
}
}
@Override
public void nextNode( NodeData data ) throws Exception
{
OsmNodeP n = data.description == 0L ? new OsmNodeP() : new OsmNodePT(data.description);
n.ilon = data.ilon;
n.ilat = data.ilat;
n.selev = data.selev;
n.isBorder = readingBorder;
if ( readingBorder || (!borderSet.contains( data.nid )) )
{
nodesMap.fastPut( data.nid, n );
}
if ( readingBorder )
{
borderSet.fastAdd( data.nid );
return;
}
// remember the segment coords
int min_lon = (n.ilon / 5000000 ) * 5000000;
int min_lat = (n.ilat / 5000000 ) * 5000000;
if ( minLon == -1 ) minLon = min_lon;
if ( minLat == -1 ) minLat = min_lat;
if ( minLat != min_lat || minLon != min_lon )
throw new IllegalArgumentException( "inconsistent node: " + n.ilon + " " + n.ilat );
}
@Override
public void nextWay( WayData way ) throws Exception
{
long description = way.description;
long reverseDescription = description | 1L; // (add reverse bit)
// filter according to profile
expctxWay.evaluate( description, null );
boolean ok = expctxWay.getCostfactor() < 10000.;
expctxWay.evaluate( reverseDescription, null );
ok |= expctxWay.getCostfactor() < 10000.;
if ( !ok ) return;
byte lowbyte = (byte)description;
OsmNodeP n1 = null;
OsmNodeP n2 = null;
for (int i=0; i<way.nodes.size(); i++)
{
long nid = way.nodes.get(i);
n1 = n2;
n2 = nodesMap.get( nid );
if ( n1 != null && n2 != null )
{
OsmLinkP l1 = new OsmLinkP();
l1.targetNode = n2;
l1.descriptionBitmap = description;
n1.addLink( l1 );
OsmLinkP l2 = new OsmLinkP();
l2.targetNode = n1;
l2.descriptionBitmap = reverseDescription;
n2.addLink( l2 );
}
if ( n2 != null )
{
n2.wayAndBits &= lowbyte;
if ( n2 instanceof OsmNodePT ) ((OsmNodePT)n2).wayOrBits |= lowbyte;
}
}
}
@Override
public void wayFileEnd( File wayfile ) throws Exception
{
nodesMap = null;
borderSet = null;
int maxLon = minLon + 5000000;
int maxLat = minLat + 5000000;
// write segment data to individual files
{
int nLonSegs = (maxLon - minLon)/1000000;
int nLatSegs = (maxLat - minLat)/1000000;
// sort the nodes into segments
LazyArrayOfLists<OsmNodeP> seglists = new LazyArrayOfLists<OsmNodeP>(nLonSegs*nLatSegs);
for( OsmNodeP n : nodesList )
{
if ( n == null || n.firstlink == null || n.isTransferNode() ) continue;
if ( n.ilon < minLon || n.ilon >= maxLon
|| n.ilat < minLat || n.ilat >= maxLat ) continue;
int lonIdx = (n.ilon-minLon)/1000000;
int latIdx = (n.ilat-minLat)/1000000;
int tileIndex = lonIdx * nLatSegs + latIdx;
seglists.getList(tileIndex).add( n );
}
nodesList = null;
seglists.trimAll();
// open the output file
File outfile = fileFromTemplate( wayfile, dataTilesOut, dataTilesSuffix );
DataOutputStream os = createOutStream( outfile );
// write 5*5 index dummy
long[] fileIndex = new long[25];
for( int i55=0; i55<25; i55++)
{
os.writeLong( 0 );
}
long filepos = 200L;
// sort further in 1/80-degree squares
for( int lonIdx = 0; lonIdx < nLonSegs; lonIdx++ )
{
for( int latIdx = 0; latIdx < nLatSegs; latIdx++ )
{
int tileIndex = lonIdx * nLatSegs + latIdx;
if ( seglists.getSize(tileIndex) > 0 )
{
List<OsmNodeP> nlist = seglists.getList(tileIndex);
LazyArrayOfLists<OsmNodeP> subs = new LazyArrayOfLists<OsmNodeP>(6400);
byte[][] subByteArrays = new byte[6400][];
for( int ni=0; ni<nlist.size(); ni++ )
{
OsmNodeP n = nlist.get(ni);
int subLonIdx = (n.ilon - minLon) / 12500 - 80*lonIdx;
int subLatIdx = (n.ilat - minLat) / 12500 - 80*latIdx;
int si = subLatIdx*80 + subLonIdx;
subs.getList(si).add( n );
}
subs.trimAll();
int[] posIdx = new int[6400];
int pos = 25600;
for( int si=0; si<6400; si++)
{
List<OsmNodeP> subList = subs.getList(si);
if ( subList.size() > 0 )
{
Collections.sort( subList );
ByteArrayOutputStream bos = new ByteArrayOutputStream( );
DataOutputStream dos = new DataOutputStream( bos );
dos.writeInt( subList.size() );
for( int ni=0; ni<subList.size(); ni++ )
{
OsmNodeP n = subList.get(ni);
n.writeNodeData( dos );
}
dos.close();
byte[] subBytes = bos.toByteArray();
pos += subBytes.length;
subByteArrays[si] = subBytes;
}
posIdx[si] = pos;
}
for( int si=0; si<6400; si++)
{
os.writeInt( posIdx[si] );
}
for( int si=0; si<6400; si++)
{
if ( subByteArrays[si] != null )
{
os.write( subByteArrays[si] );
}
}
filepos += pos;
}
fileIndex[ tileIndex ] = filepos;
}
}
os.close();
// re-open random-access to write file-index
RandomAccessFile ra = new RandomAccessFile( outfile, "rw" );
long versionPrefix = lookupVersion;
versionPrefix <<= 48;
for( int i55=0; i55<25; i55++)
{
ra.writeLong( fileIndex[i55] | versionPrefix );
}
ra.close();
}
}
}

View file

@ -0,0 +1,17 @@
package btools.mapcreator;
import java.io.File;
/**
* Callbacklistener for WayIterator
*
* @author ab
*/
public interface WayListener
{
void wayFileStart( File wayfile ) throws Exception;
void nextWay( WayData data ) throws Exception;
void wayFileEnd( File wayfile ) throws Exception;
}

View file

@ -0,0 +1,70 @@
package btools.mapcreator;
import java.util.Random;
import java.util.HashMap;
import org.junit.Assert;
import org.junit.Test;
import java.net.URL;
import java.io.File;
public class MapcreatorTest
{
@Test
public void mapcreatorTest() throws Exception
{
URL mapurl = this.getClass().getResource( "/dreieich.osm.gz" );
Assert.assertTrue( "test-osm-map dreieich.osm not found", mapurl != null );
File mapfile = new File(mapurl.getFile());
File workingDir = mapfile.getParentFile();
File tmpdir = new File( workingDir, "tmp" );
tmpdir.mkdir();
// run OsmCutter
File nodetiles = new File( tmpdir, "nodetiles" );
nodetiles.mkdir();
File lookupFile = new File( workingDir, "lookups.dat" );
File wayFile = new File( tmpdir, "ways.dat" );
File relFile = new File( tmpdir, "cycleways.dat" );
new OsmCutter().process( lookupFile, nodetiles, wayFile, relFile, mapfile );
// run NodeFilter
File ftiles = new File( tmpdir, "ftiles" );
ftiles.mkdir();
new NodeFilter().process( nodetiles, wayFile, ftiles );
// run WayCutter
File waytiles = new File( tmpdir, "waytiles" );
waytiles.mkdir();
new WayCutter().process( ftiles, wayFile, waytiles, relFile );
// run WayCutter5
File waytiles55 = new File( tmpdir, "waytiles55" );
File bordernids = new File( tmpdir, "bordernids.dat" );
waytiles55.mkdir();
new WayCutter5().process( ftiles, waytiles, waytiles55, bordernids );
// run NodeCutter
File nodes55 = new File( tmpdir, "nodes55" );
nodes55.mkdir();
new NodeCutter().process( ftiles, nodes55 );
// run PosUnifier
File unodes55 = new File( tmpdir, "unodes55" );
File bordernodes = new File( tmpdir, "bordernodes.dat" );
unodes55.mkdir();
new PosUnifier().process( nodes55, unodes55, bordernids, bordernodes, "/private-backup/srtm" );
// run WayLinker
File segments = new File( tmpdir, "segments" );
segments.mkdir();
File profileAllFile = new File( workingDir, "all.brf" );
new WayLinker().process( unodes55, waytiles55, bordernodes, lookupFile, profileAllFile, segments, "rd5" );
// run WayLinker, car subset
File carsubset = new File( segments, "carsubset" );
carsubset.mkdir();
File profileCarFile = new File( workingDir, "car-test.brf" );
new WayLinker().process( unodes55, waytiles55, bordernodes, lookupFile, profileCarFile, carsubset, "cd5" );
}
}

View file

@ -0,0 +1,70 @@
package btools.mapcreator;
import java.util.Random;
import java.util.HashMap;
import org.junit.Assert;
import org.junit.Test;
import java.net.URL;
import java.io.File;
public class MapcreatorTest
{
@Test
public void mapcreatorTest() throws Exception
{
URL mapurl = this.getClass().getResource( "/dreieich.osm.gz" );
Assert.assertTrue( "test-osm-map dreieich.osm not found", mapurl != null );
File mapfile = new File(mapurl.getFile());
File workingDir = mapfile.getParentFile();
File tmpdir = new File( workingDir, "tmp" );
tmpdir.mkdir();
// run OsmCutter
File nodetiles = new File( tmpdir, "nodetiles" );
nodetiles.mkdir();
File lookupFile = new File( workingDir, "lookups.dat" );
File wayFile = new File( tmpdir, "ways.dat" );
File relFile = new File( tmpdir, "cycleways.dat" );
new OsmCutter().process( lookupFile, nodetiles, wayFile, relFile, mapfile );
// run NodeFilter
File ftiles = new File( tmpdir, "ftiles" );
ftiles.mkdir();
new NodeFilter().process( nodetiles, wayFile, ftiles );
// run WayCutter
File waytiles = new File( tmpdir, "waytiles" );
waytiles.mkdir();
new WayCutter().process( ftiles, wayFile, waytiles, relFile );
// run WayCutter5
File waytiles55 = new File( tmpdir, "waytiles55" );
File bordernids = new File( tmpdir, "bordernids.dat" );
waytiles55.mkdir();
new WayCutter5().process( ftiles, waytiles, waytiles55, bordernids );
// run NodeCutter
File nodes55 = new File( tmpdir, "nodes55" );
nodes55.mkdir();
new NodeCutter().process( ftiles, nodes55 );
// run PosUnifier
File unodes55 = new File( tmpdir, "unodes55" );
File bordernodes = new File( tmpdir, "bordernodes.dat" );
unodes55.mkdir();
new PosUnifier().process( nodes55, unodes55, bordernids, bordernodes, "/private-backup/srtm" );
// run WayLinker
File segments = new File( tmpdir, "segments" );
segments.mkdir();
File profileAllFile = new File( workingDir, "all.brf" );
new WayLinker().process( unodes55, waytiles55, bordernodes, lookupFile, segments, "rd5" );
// run WayLinker, car subset
File carsubset = new File( segments, "carsubset" );
carsubset.mkdir();
File profileCarFile = new File( workingDir, "car-test.brf" );
new WayLinker().process( unodes55, waytiles55, bordernodes, lookupFile, carsubset, "cd5" );
}
}

View file

@ -0,0 +1,18 @@
---context:global # following code refers to global config
# the elevation parameters
assign downhillcost 0
assign downhillcutoff 1.5
assign uphillcost 0
assign uphillcutoff 1.5
---context:way # following code refers to way-tags
assign turncost 0
assign initialcost 0
assign costfactor 1
---context:node # following code refers to node tags
assign initialcost 0

View file

@ -0,0 +1,11 @@
---context:global # following code refers to global config
---context:way # following code refers to way-tags
assign turncost 0
assign initialcost 0
assign costfactor 1
---context:node # following code refers to node tags
assign initialcost 0

View file

@ -0,0 +1,107 @@
#
# Car-Routing is experimantal !!!
#
# DO NOT USE FOR ACTUAL NAVIGATION
#
# Turn restrictions are missing, leading to wrong routes
#
---context:global
assign downhillcost 0
assign downhillcutoff 0
assign uphillcost 0
assign uphillcutoff 0
assign validForCars 1
---context:way # following code refers to way-tags
assign turncost 200
assign initialcost switch highway=ferry 20000 0
#
# calculate logical car access
#
assign caraccess
switch motorcar=
switch motor_vehicle=
switch vehicle=
switch access=
switch or highway=motorway highway=motorway_link 1
switch or highway=trunk highway=trunk_link 1
switch or highway=primary highway=primary_link 1
switch or highway=secondary highway=secondary_link 1
switch or highway=tertiary highway=tertiary_link 1
switch highway=unclassified 1
switch highway=ferry 1
switch or highway=residential highway=living_street 1
switch highway=service 1
0
or access=yes or access=designated access=destination
or vehicle=yes or vehicle=designated vehicle=destination
or motor_vehicle=yes or motor_vehicle=designated motor_vehicle=destination
or motorcar=yes or motorcar=designated motorcar=destination
assign accesspenalty
switch caraccess
0
10000
assign onewaypenalty
switch switch reversedirection=yes
switch oneway=
junction=roundabout
or oneway=yes or oneway=true oneway=1
oneway=-1
10000
0.0
assign ispaved or surface=paved or surface=asphalt or surface=concrete surface=paving_stones
assign costfactor
add max onewaypenalty accesspenalty
switch or highway=motorway highway=motorway_link 1
switch or highway=trunk highway=trunk_link 1
switch or highway=primary highway=primary_link switch maxspeed=30 2.0 switch maxspeed=50 1.5 1.2
switch or highway=secondary highway=secondary_link 1.3
switch or highway=tertiary highway=tertiary_link 1.4
switch highway=unclassified 1.5
switch highway=ferry 5.67
switch highway=bridleway 5
switch or highway=residential highway=living_street 2
switch highway=service 2
switch or highway=track or highway=road highway=path
switch tracktype=grade1 5
switch ispaved 5
30
10000
---context:node # following code refers to node tags
#
# calculate logical car access to nodes
#
assign caraccess
switch motorcar=
switch motor_vehicle=
switch vehicle=
switch access=
switch barrier=gate 0
switch barrier=bollard 0
switch barrier=lift_gate 0
switch barrier=cycle_barrier 0
1
or access=yes or access=designated access=destination
or vehicle=yes or vehicle=designated vehicle=destination
or motor_vehicle=yes or motor_vehicle=designated motor_vehicle=destination
or motorcar=yes or motorcar=designated motorcar=destination
assign initialcost
switch caraccess
0
1000000

Binary file not shown.

View file

@ -0,0 +1,317 @@
---lookupversion:2
---context:way
highway;0001731794 track
highway;0001457935 residential
highway;0000968516 service
highway;0000756237 footway
highway;0000521566 path
highway;0000261772 unclassified
highway;0000220315 secondary
highway;0000207585 tertiary
highway;0000103445 steps
highway;0000102114 primary
highway;0000094484 cycleway
highway;0000090388 living_street
highway;0000035041 motorway
highway;0000029965 pedestrian
highway;0000026875 motorway_link
highway;0000015054 trunk
highway;0000014604 primary_link
highway;0000012211 road
highway;0000011822 trunk_link
highway;0000005882 construction
highway;0000005425 bridleway
highway;0000005180 secondary_link
highway;0000003360 platform
highway;0000002616 proposed abandoned
highway;0000001374 tertiary_link
highway;0000000760 ferry
highway;0000000541 raceway
highway;0000000346 rest_area
highway;0000000300 bus_stop
highway;0000000184 services
tracktype;0000356503 grade2
tracktype;0000353482 grade3
tracktype;0000281625 grade1
tracktype;0000245193 grade4
tracktype;0000179135 grade5
surface;0000363915 asphalt
surface;0000303589 paved
surface;0000196783 gravel
surface;0000137371 ground
surface;0000128215 grass
surface;0000092748 unpaved
surface;0000086579 paving_stones
surface;0000066111 cobblestone
surface;0000042061 dirt
surface;0000026551 concrete
surface;0000025631 compacted
surface;0000019861 sand
surface;0000009400 pebblestone
surface;0000003197 fine_gravel
maxspeed;0000402224 30
maxspeed;0000224685 50
maxspeed;0000045177 100
maxspeed;0000037529 70
maxspeed;0000014237 none
maxspeed;0000014022 60
maxspeed;0000011530 80
maxspeed;0000009951 10
maxspeed;0000008056 20
maxspeed;0000005772 120
maxspeed;0000003165 40
maxspeed;0000002987 7
maxspeed;0000002826 signals
maxspeed;0000001933 130
service;0000221481 parking_aisle
service;0000157110 driveway
lit;0000132495 yes
lanes;0000098207 2
lanes;0000042192 1
lanes;0000018533 3
lanes;0000004577 4
lanes;0000000448 5
lanes;0000000318 1.5
access;0000044859 yes permissive
access;0000008452 designated official
access;0000028727 destination customers
access;0000076985 agricultural forestry
access;0000116270 private
access;0000028044 no
foot;0000339384 yes allowed Yes
foot;0000125339 designated official
foot;0000018945 no
foot;0000001562 private
foot;0000000279 destination
foot;0000008172 permissive
bicycle;0000302789 yes allowed permissive
bicycle;0000108056 designated official
bicycle;0000000265 destination
bicycle;0000003593 dismount
bicycle;0000001426 private
bicycle;0000070179 no
motorcar;0000010111 yes permissive
motorcar;0000001537 designated official
motorcar;0000007102 destination
motorcar;0000016706 agricultural forestry agriculture
motorcar;0000002178 private
motorcar;0000077771 no
motor_vehicle;0000013813 yes permissive
motor_vehicle;0000002098 designated official
motor_vehicle;0000009792 destination
motor_vehicle;0000019301 agricultural forestry
motor_vehicle;0000006563 private
motor_vehicle;0000025491 no
motorcycle;0000005750 yes permissive
motorcycle;0000001158 designated official
motorcycle;0000005805 destination
motorcycle;0000012401 agricultural forestry
motorcycle;0000001180 private
motorcycle;0000053955 no
vehicle;0000000505 yes permissive
vehicle;0000000027 designated
vehicle;0000007582 destination
vehicle;0000004357 agricultural forestry
vehicle;0000001155 private
vehicle;0000006487 no
cycleway;0000033575 track
cycleway;0000012829 no
cycleway;0000011604 lane
cycleway;0000008938 opposite
cycleway;0000001503 none
cycleway;0000001146 right
cycleway;0000001031 opposite_track
cycleway;0000001029 yes
cycleway;0000000856 opposite_lane
cycleway;0000000675 both
cycleway;0000000665 left
cycleway;0000000521 shared
cycleway;0000000383 street
cycleway;0000000176 segregated
mtb:scale;0000043968 0
mtb:scale;0000019705 1
mtb:scale;0000006436 2
mtb:scale;0000002702 3
mtb:scale;0000001083 4
mtb:scale;0000000329 5
sac_scale;0000049626 hiking
sac_scale;0000007933 mountain_hiking
sac_scale;0000001160 demanding_mountain_hiking
sac_scale;0000000523 yes
sac_scale;0000000364 alpine_hiking
sac_scale;0000000117 demanding_alpine_hiking
noexit;0000058492 yes
motorroad;0000019250 yes
oneway;0000330245 yes
oneway;0000075148 no
oneway;0000003679 -1
oneway;0000000001 true
oneway;0000000001 1
junction;0000015929 roundabout
bridge;0000182649 yes viaduct true suspension
tunnel;0000031626 yes
lcn;0000018999 yes
longdistancecycleway;0000000001 yes
reversedirection;0000000001 yes
---context:node
highway;0000100947 turning_circle
highway;0000067645 traffic_signals
highway;0000047209 crossing
highway;0000037164 bus_stop
highway;0000006577 motorway_junction
highway;0000003811 stop
highway;0000002331 mini_roundabout
highway;0000001789 milestone
highway;0000001692 passing_place
highway;0000001289 give_way
highway;0000001092 emergency_access_point
highway;0000000683 speed_camera
highway;0000000672 steps
highway;0000000658 incline_steep
highway;0000000620 elevator
highway;0000000506 street_lamp
highway;0000000490 ford
highway;0000000458 incline
highway;0000000135 rest_area
highway;0000000105 path
highway;0000000098 emergency_bay
highway;0000000096 road
highway;0000000087 platform
highway;0000000074 services
highway;0000000058 track
highway;0000000055 service
highway;0000000054 footway
highway;0000000053 traffic_calming
highway;0000000046 toll_bridge
highway;0000000037 city_entry
barrier;0000076979 gate
barrier;0000069308 bollard
barrier;0000028131 lift_gate
barrier;0000017332 cycle_barrier
barrier;0000005693 entrance
barrier;0000002885 block
barrier;0000001065 kissing_gate
barrier;0000000828 cattle_grid
barrier;0000000602 stile
barrier;0000000561 turnstile
barrier;0000000512 no
barrier;0000000463 fence
barrier;0000000417 bump_gate
barrier;0000000324 sally_port
barrier;0000000283 yes
barrier;0000000283 hampshire_gate
barrier;0000000236 swing_gate
barrier;0000000203 chain
barrier;0000000181 toll_booth
barrier;0000000180 door
barrier;0000000104 chicane
barrier;0000000096 tree
barrier;0000000087 border_control
barrier;0000000077 log
barrier;0000000076 traffic_crossing_pole
barrier;0000000063 wall
barrier;0000000060 fallen_tree
barrier;0000000052 stone
barrier;0000000048 ditch
barrier;0000000031 spikes
access;0000001309 yes permissive
access;0000000118 designated official
access;0000000405 destination customers
access;0000000276 agricultural forestry
access;0000008574 private
access;0000002145 no
foot;0000080681 yes permissive
foot;0000000326 designated official
foot;0000000023 destination
foot;0000000156 private
foot;0000009170 no
bicycle;0000076717 yes permissive
bicycle;0000000406 designated official
bicycle;0000000018 destination
bicycle;0000000081 dismount
bicycle;0000000051 private
bicycle;0000016121 no
motorcar;0000005785 yes permissive
motorcar;0000000026 designated official
motorcar;0000000080 destination
motorcar;0000000112 agricultural forestry
motorcar;0000000171 private
motorcar;0000001817 no
motor_vehicle;0000000066 yes permissive
motor_vehicle;0000000000 designated official
motor_vehicle;0000000030 destination
motor_vehicle;0000000073 agricultural forestry
motor_vehicle;0000000136 private
motor_vehicle;0000000469 no
motorcycle;0000004515 yes permissive
motorcycle;0000000007 designated official
motorcycle;0000000054 destination
motorcycle;0000000027 agricultural forestry
motorcycle;0000000063 private
motorcycle;0000001637 no
vehicle;0000000058 yes permissive
vehicle;0000000000 designated
vehicle;0000000081 destination
vehicle;0000000038 agricultural forestry
vehicle;0000000041 private
vehicle;0000000271 no
crossing;0000032485 traffic_signals
crossing;0000014300 uncontrolled
crossing;0000005086 island
crossing;0000001565 unmarked
crossing;0000001066 no
crossing;0000000333 zebra
railway;0000034039 level_crossing
railway;0000010175 crossing
noexit;0000043010 yes
entrance;0000015094 yes
entrance;0000007079 main
entrance;0000000554 service
entrance;0000000169 emergency
entrance;0000000063 exit
entrance;0000000008 private
lcn;0000018999 yes
longdistancecycleway;0000000001 yes