package btools.memrouter; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; import btools.expressions.BExpressionContextWay; import btools.expressions.BExpressionMetaData; import btools.mapaccess.OsmPos; import btools.mapcreator.MapCreatorBase; import btools.mapcreator.NodeData; import btools.mapcreator.NodeIterator; import btools.mapcreator.WayData; import btools.mapcreator.WayIterator; import btools.util.ByteArrayUnifier; import btools.util.CompactLongMap; import btools.util.FrozenLongMap; import btools.util.LazyArrayOfLists; /** * GraphLoader loads the routing graph from * the nodes+way files (much like mapcreator.WayLinker) * * @author ab */ public class GraphLoader extends MapCreatorBase { private CompactLongMap nodesMap; private Map stationMap; private BExpressionContextWay expctxWay; private ByteArrayUnifier abUnifier; private int currentTile; private long linksLoaded = 0L; private long nodesLoaded = 0L; private static final int MAXTILES = 2592; private List> seglistsArray = new ArrayList>(2592); public static void main(String[] args) throws Exception { System.out.println("*** GraphLoader: load a routing graph in memory"); if (args.length != 5) { System.out.println("usage: java GraphLoader "); return; } BExpressionMetaData meta = new BExpressionMetaData(); // read lookup + profile for lookup-version + access-filter BExpressionContextWay expctxWay = new BExpressionContextWay(meta); File lookupFile = new File( args[2] ); File profileFile = new File( args[3] ); meta.readMetaData( lookupFile ); expctxWay.parseFile( profileFile, "global" ); GraphLoader graph = new GraphLoader(); File[] fahrplanFiles = new File[2]; fahrplanFiles[0] = new File( args[4] ); fahrplanFiles[1] = new File( args[5] ); graph.process( new File( args[0] ), new File( args[1] ), fahrplanFiles, expctxWay ); } public void process( File nodeTilesIn, File wayTilesIn, File[] fahrplanFiles, BExpressionContextWay expctxWay ) throws Exception { this.expctxWay = expctxWay; seglistsArray = new ArrayList>(MAXTILES); for( int i=0; i < MAXTILES; i++ ) { seglistsArray.add( null ); } abUnifier = new ByteArrayUnifier( 16384, false ); nodesMap = new CompactLongMap(); // read all nodes new NodeIterator( this, false ).processDir( nodeTilesIn, ".u5d" ); // freeze the nodes-map nodesMap = new FrozenLongMap( nodesMap ); // trim the list array for( int i=0; i nodes = new ArrayList(); nodes.addAll( subListForPos( ilon-6125, ilat-6125 ) ); nodes.addAll( subListForPos( ilon-6125, ilat+6125 ) ); nodes.addAll( subListForPos( ilon+6125, ilat-6125 ) ); nodes.addAll( subListForPos( ilon+6125, ilat+6125 ) ); int mindist = Integer.MAX_VALUE; OsmNodeP bestmatch = null; for( OsmNodeP node : nodes ) { if ( transitonly ) { StationNode sn = getStationNode( node ); if ( sn != null ) { int dist = pos.calcDistance( sn ); if ( dist < mindist ) { mindist = dist; bestmatch = sn; } } continue; } int dist = pos.calcDistance( node ); if ( dist < mindist ) { if ( wayCtx == null || hasRoutableLinks(node, wayCtx) ) { mindist = dist; bestmatch = node; } } } return bestmatch; } private StationNode getStationNode( OsmNodeP node ) { for( OsmLinkP link = node.getFirstLink(); link != null; link = link.getNext( node ) ) { OsmNodeP tn = link.getTarget( node ); if ( tn instanceof StationNode ) { return (StationNode)tn; } } return null; } public OsmNodeP matchStationForPosition( OsmPos pos ) { int mindist = Integer.MAX_VALUE; OsmNodeP bestmatch = null; for( OsmNodeP node : stationMap.values() ) { int dist = pos.calcDistance( node ); if ( dist < mindist ) { mindist = dist; bestmatch = node; } } return bestmatch; } private boolean hasRoutableLinks( OsmNodeP node, BExpressionContextWay wayCtx ) { for( OsmLinkP link = node.getFirstLink(); link != null; link = link.getNext( node ) ) { if ( link.isWayLink() ) { wayCtx.evaluate( false, link.descriptionBitmap ); if ( wayCtx.getCostfactor() < 10000.f ) { return true; } } } return false; } @Override public void nodeFileStart( File nodefile ) throws Exception { currentTile = tileForFilename( nodefile.getName() ); seglistsArray.set(currentTile, new LazyArrayOfLists(160000) ); System.out.println( "nodes currentTile=" + currentTile ); } @Override public void nextNode( NodeData data ) throws Exception { OsmNodeP n = data.description == null ? new OsmNodeP() : new OsmNodePT(data.description); n.ilon = data.ilon; n.ilat = data.ilat; n.selev = data.selev; // add to the map nodesMap.fastPut( data.nid, n ); // add also to the list array subListForPos( n.ilon, n.ilat ).add( n ); nodesLoaded++; } @Override public boolean wayFileStart( File wayfile ) throws Exception { currentTile = tileForFilename( wayfile.getName() ); System.out.println( "ways currentTile=" + currentTile ); return true; } @Override public void nextWay( WayData way ) throws Exception { byte[] description = abUnifier.unify( way.description ); byte wayBits = 0; expctxWay.decode( description ); if ( !expctxWay.getBooleanLookupValue( "bridge" ) ) wayBits |= OsmNodeP.NO_BRIDGE_BIT; if ( !expctxWay.getBooleanLookupValue( "tunnel" ) ) wayBits |= OsmNodeP.NO_TUNNEL_BIT; OsmNodeP n1 = null; OsmNodeP n2 = null; for (int i=0; i= 180 || ilon % 5 != 0 ) return -1; if ( ilat < - 90 || ilat >= 90 || ilat % 5 != 0 ) return -1; return (ilon+180) / 5 + 72*((ilat+90)/5); } private int tileForPos( int ilon, int ilat ) { return ilon / 5000000 + 72 * ( ilat / 5000000 ); } private int subIdxForPos( int ilon, int ilat ) { int lonModulo = ilon % 5000000; int latModulo = ilat % 5000000; return ( lonModulo / 12500 ) + 400 * (latModulo / 12500); } private List subListForPos( int ilon, int ilat ) { if ( ilon < 0 || ilon >= 360000000 || ilat < 0 || ilat >= 180000000 ) { throw new IllegalArgumentException( "illegal position: " + ilon + " " + ilat ); } int tileNr = tileForPos( ilon, ilat ); if ( seglistsArray.get(tileNr) == null ) return new ArrayList(); return seglistsArray.get(tileNr).getList( subIdxForPos( ilon, ilat ) ); } }