statistical encoding
This commit is contained in:
parent
f8dee5b7d1
commit
ccf6641bad
41 changed files with 4543 additions and 1965 deletions
|
|
@ -17,6 +17,11 @@
|
|||
<artifactId>brouter-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter-codec</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter-mapaccess</artifactId>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ final class MatchedWaypoint
|
|||
public OsmNodeNamed crosspoint;
|
||||
public OsmNodeNamed waypoint;
|
||||
public double radius;
|
||||
public int cost;
|
||||
public boolean hasUpdate;
|
||||
|
||||
public void writeToStream( DataOutput dos ) throws IOException
|
||||
{
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ final class OsmPath implements OsmLinkHolder
|
|||
|
||||
MessageData msgData = new MessageData();
|
||||
|
||||
OsmTransferNode transferNode = link.decodeFirsttransfer();
|
||||
OsmTransferNode transferNode = link.decodeFirsttransfer( p1 );
|
||||
OsmNode targetNode = link.targetNode;
|
||||
for(;;)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -140,6 +140,27 @@ public final class RoutingContext implements DistanceChecker
|
|||
}
|
||||
}
|
||||
|
||||
public void cleanNogolist( List<OsmNodeNamed> waypoints )
|
||||
{
|
||||
if ( nogopoints == null ) return;
|
||||
List<OsmNodeNamed> nogos = new ArrayList<OsmNodeNamed>();
|
||||
for( OsmNodeNamed nogo : nogopoints )
|
||||
{
|
||||
int radiusInMeter = (int)(nogo.radius * 111894.);
|
||||
boolean goodGuy = true;
|
||||
for( OsmNodeNamed wp : waypoints )
|
||||
{
|
||||
if ( wp.calcDistance( nogo ) < radiusInMeter )
|
||||
{
|
||||
goodGuy = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( goodGuy ) nogos.add( nogo );
|
||||
}
|
||||
nogopoints = nogos;
|
||||
}
|
||||
|
||||
public long[] getNogoChecksums()
|
||||
{
|
||||
long[] cs = new long[3];
|
||||
|
|
@ -215,8 +236,7 @@ public final class RoutingContext implements DistanceChecker
|
|||
// calculate remaining distance
|
||||
if ( s2 < 0. )
|
||||
{
|
||||
double distance = d > 0. ? -s2 / d : 0.;
|
||||
wayfraction = d > 0. ? distance / d : 0.;
|
||||
wayfraction = -s2 / (d*d);
|
||||
double xm = x2 - wayfraction*dx;
|
||||
double ym = y2 - wayfraction*dy;
|
||||
ilonshortest = (int)(xm / coslat6 + nogo.ilon);
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ package btools.router;
|
|||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import btools.expressions.BExpressionContext;
|
||||
import btools.expressions.BExpressionContextGlobal;
|
||||
import btools.expressions.BExpressionContextNode;
|
||||
import btools.expressions.BExpressionContextWay;
|
||||
|
|
@ -28,6 +29,7 @@ public class RoutingEngine extends Thread
|
|||
private boolean finished = false;
|
||||
|
||||
protected List<OsmNodeNamed> waypoints = null;
|
||||
protected List<MatchedWaypoint> matchedWaypoints;
|
||||
private int linksProcessed = 0;
|
||||
|
||||
protected OsmTrack foundTrack = new OsmTrack();
|
||||
|
|
@ -85,8 +87,8 @@ public class RoutingEngine extends Thread
|
|||
BExpressionMetaData meta = new BExpressionMetaData();
|
||||
|
||||
BExpressionContextGlobal expctxGlobal = new BExpressionContextGlobal( meta );
|
||||
rc.expctxWay = new BExpressionContextWay( rc.serversizing ? 262144 : 4096, meta );
|
||||
rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 16384 : 1024, meta );
|
||||
rc.expctxWay = new BExpressionContextWay( rc.serversizing ? 262144 : 8192, meta );
|
||||
rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 16384 : 2048, meta );
|
||||
|
||||
meta.readMetaData( new File( profileDir, "lookups.dat" ) );
|
||||
|
||||
|
|
@ -111,6 +113,7 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
infoLogWriter.write( s );
|
||||
infoLogWriter.write( '\n' );
|
||||
infoLogWriter.flush();
|
||||
}
|
||||
catch( IOException io )
|
||||
{
|
||||
|
|
@ -119,6 +122,14 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
|
||||
private void logThrowable( Throwable t )
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
t.printStackTrace(pw);
|
||||
logInfo( sw.toString() );
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
doRun( 0 );
|
||||
|
|
@ -135,6 +146,9 @@ public class RoutingEngine extends Thread
|
|||
logInfo( "start request at " + new Date() );
|
||||
}
|
||||
|
||||
// delete nogos with waypoints in them
|
||||
routingContext.cleanNogolist( waypoints );
|
||||
|
||||
startTime = System.currentTimeMillis();
|
||||
this.maxRunningTime = maxRunningTime;
|
||||
int nsections = waypoints.size() - 1;
|
||||
|
|
@ -205,14 +219,14 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
errorMessage = e instanceof IllegalArgumentException ? e.getMessage() : e.toString();
|
||||
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
e.printStackTrace();
|
||||
logThrowable( e );
|
||||
}
|
||||
catch( Error e)
|
||||
{
|
||||
String hint = cleanOnOOM();
|
||||
errorMessage = e.toString() + hint;
|
||||
logInfo( "Error (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
e.printStackTrace();
|
||||
logThrowable( e );
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -250,14 +264,14 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
errorMessage = e instanceof IllegalArgumentException ? e.getMessage() : e.toString();
|
||||
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
e.printStackTrace();
|
||||
logThrowable( e );
|
||||
}
|
||||
catch( Error e)
|
||||
{
|
||||
String hint = cleanOnOOM();
|
||||
errorMessage = e.toString() + hint;
|
||||
logInfo( "Error (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
e.printStackTrace();
|
||||
logThrowable( e );
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -290,7 +304,7 @@ public class RoutingEngine extends Thread
|
|||
private OsmTrack findTrack( OsmTrack[] refTracks, OsmTrack[] lastTracks )
|
||||
{
|
||||
OsmTrack totaltrack = new OsmTrack();
|
||||
MatchedWaypoint[] wayointIds = new MatchedWaypoint[waypoints.size()];
|
||||
int nUnmatched = waypoints.size();
|
||||
|
||||
// check for a track for that target
|
||||
OsmTrack nearbyTrack = null;
|
||||
|
|
@ -299,20 +313,27 @@ public class RoutingEngine extends Thread
|
|||
nearbyTrack = OsmTrack.readBinary( routingContext.rawTrackPath, waypoints.get( waypoints.size()-1), routingContext.getNogoChecksums() );
|
||||
if ( nearbyTrack != null )
|
||||
{
|
||||
wayointIds[waypoints.size()-1] = nearbyTrack.endPoint;
|
||||
}
|
||||
}
|
||||
|
||||
// match waypoints to nodes
|
||||
for( int i=0; i<waypoints.size(); i++ )
|
||||
{
|
||||
if ( wayointIds[i] == null )
|
||||
{
|
||||
wayointIds[i] = matchNodeForPosition( waypoints.get(i) );
|
||||
nUnmatched--;
|
||||
}
|
||||
}
|
||||
|
||||
for( int i=0; i<waypoints.size() -1; i++ )
|
||||
if ( matchedWaypoints == null ) // could exist from the previous alternative level
|
||||
{
|
||||
matchedWaypoints = new ArrayList<MatchedWaypoint>();
|
||||
for( int i=0; i<nUnmatched; i++ )
|
||||
{
|
||||
MatchedWaypoint mwp = new MatchedWaypoint();
|
||||
mwp.waypoint = waypoints.get(i);
|
||||
matchedWaypoints.add( mwp );
|
||||
}
|
||||
matchWaypointsToNodes( matchedWaypoints );
|
||||
if ( nearbyTrack != null )
|
||||
{
|
||||
matchedWaypoints.add( nearbyTrack.endPoint );
|
||||
}
|
||||
}
|
||||
|
||||
for( int i=0; i<matchedWaypoints.size() -1; i++ )
|
||||
{
|
||||
if ( lastTracks[i] != null )
|
||||
{
|
||||
|
|
@ -320,7 +341,7 @@ public class RoutingEngine extends Thread
|
|||
refTracks[i].addNodes( lastTracks[i] );
|
||||
}
|
||||
|
||||
OsmTrack seg = searchTrack( wayointIds[i], wayointIds[i+1], i == waypoints.size()-2 ? nearbyTrack : null, refTracks[i] );
|
||||
OsmTrack seg = searchTrack( matchedWaypoints.get(i), matchedWaypoints.get(i+1), i == matchedWaypoints.size()-2 ? nearbyTrack : null, refTracks[i] );
|
||||
if ( seg == null ) return null;
|
||||
totaltrack.appendTrack( seg );
|
||||
lastTracks[i] = seg;
|
||||
|
|
@ -328,6 +349,50 @@ public class RoutingEngine extends Thread
|
|||
return totaltrack;
|
||||
}
|
||||
|
||||
// geometric position matching finding the nearest routable way-section
|
||||
private void matchWaypointsToNodes( List<MatchedWaypoint> unmatchedWaypoints )
|
||||
{
|
||||
resetCache();
|
||||
nodesCache.waypointMatcher = new WaypointMatcherImpl( unmatchedWaypoints, 250. );
|
||||
for( MatchedWaypoint mwp : unmatchedWaypoints )
|
||||
{
|
||||
preloadPosition( mwp.waypoint );
|
||||
}
|
||||
|
||||
// preliminary-hack: use old stuff if not yet matched
|
||||
for( int i=0; i<unmatchedWaypoints.size(); i++)
|
||||
{
|
||||
MatchedWaypoint mwp = unmatchedWaypoints.get(i);
|
||||
if ( mwp.crosspoint == null )
|
||||
{
|
||||
System.out.println( "name=" + mwp.waypoint.name + " NOT matched r=" + mwp.radius * 111894. );
|
||||
unmatchedWaypoints.set(i, matchNodeForPosition( mwp.waypoint ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println( "name=" + mwp.waypoint.name + " matched r=" + mwp.radius * 111894. );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void preloadPosition( OsmNode n )
|
||||
{
|
||||
int d = 12500;
|
||||
nodesCache.first_file_access_failed = false;
|
||||
nodesCache.first_file_access_name = null;
|
||||
nodesCache.loadSegmentFor( n.ilon, n.ilat );
|
||||
if ( nodesCache.first_file_access_failed )
|
||||
{
|
||||
throw new IllegalArgumentException( "datafile " + nodesCache.first_file_access_name + " not found" );
|
||||
}
|
||||
for( int idxLat=-1; idxLat<=1; idxLat++ )
|
||||
for( int idxLon=-1; idxLon<=1; idxLon++ )
|
||||
{
|
||||
nodesCache.loadSegmentFor( n.ilon + d*idxLon , n.ilat +d*idxLat );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// geometric position matching finding the nearest routable way-section
|
||||
private MatchedWaypoint matchNodeForPosition( OsmNodeNamed wp )
|
||||
{
|
||||
|
|
@ -406,7 +471,6 @@ public class RoutingEngine extends Thread
|
|||
mwp.node1 = n;
|
||||
mwp.node2 = nextNode;
|
||||
mwp.radius = wp.radius;
|
||||
mwp.cost = testPath.cost;
|
||||
mwp.crosspoint = new OsmNodeNamed();
|
||||
mwp.crosspoint.ilon = routingContext.ilonshortest;
|
||||
mwp.crosspoint.ilat = routingContext.ilatshortest;
|
||||
|
|
@ -510,8 +574,7 @@ public class RoutingEngine extends Thread
|
|||
private void resetCache()
|
||||
{
|
||||
nodesMap = new OsmNodesMap();
|
||||
BExpressionContext ctx = routingContext.expctxWay;
|
||||
nodesCache = new NodesCache(segmentDir, nodesMap, ctx.meta.lookupVersion, ctx.meta.lookupMinorVersion, routingContext.carMode, routingContext.forceSecondaryData, nodesCache );
|
||||
nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay, routingContext.carMode, routingContext.forceSecondaryData, nodesCache );
|
||||
}
|
||||
|
||||
private OsmNode getStartNode( long startId )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,140 @@
|
|||
package btools.router;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import btools.codec.WaypointMatcher;
|
||||
import btools.mapaccess.OsmNode;
|
||||
|
||||
/**
|
||||
* the WaypointMatcher is feeded by the decoder with geoemtries of ways that are
|
||||
* already check for allowed access according to the current routing profile
|
||||
*
|
||||
* It matches these geometries against the list of waypoints to find the best
|
||||
* match for each waypoint
|
||||
*/
|
||||
public final class WaypointMatcherImpl implements WaypointMatcher
|
||||
{
|
||||
private List<MatchedWaypoint> waypoints;
|
||||
|
||||
private int lonStart;
|
||||
private int latStart;
|
||||
private boolean anyUpdate;
|
||||
private int lonLast;
|
||||
private int latLast;
|
||||
|
||||
public WaypointMatcherImpl( List<MatchedWaypoint> waypoints, double maxDistance )
|
||||
{
|
||||
this.waypoints = waypoints;
|
||||
for ( MatchedWaypoint mwp : waypoints )
|
||||
{
|
||||
mwp.radius = maxDistance / 111894.; // 6378000. / 57.;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSegment( int lon1, int lat1, int lon2, int lat2 )
|
||||
{
|
||||
// todo: bounding-box pre-filter
|
||||
|
||||
double l = ( lat2 - 90000000 ) * 0.00000001234134;
|
||||
double l2 = l * l;
|
||||
double l4 = l2 * l2;
|
||||
double coslat = 1. - l2 + l4 / 6.;
|
||||
double coslat6 = coslat * 0.000001;
|
||||
|
||||
double dx = ( lon2 - lon1 ) * coslat6;
|
||||
double dy = ( lat2 - lat1 ) * 0.000001;
|
||||
double d = Math.sqrt( dy * dy + dx * dx );
|
||||
if ( d == 0. )
|
||||
return;
|
||||
|
||||
for ( MatchedWaypoint mwp : waypoints )
|
||||
{
|
||||
OsmNodeNamed wp = mwp.waypoint;
|
||||
|
||||
double x1 = ( lon1 - wp.ilon ) * coslat6;
|
||||
double y1 = ( lat1 - wp.ilat ) * 0.000001;
|
||||
double x2 = ( lon2 - wp.ilon ) * coslat6;
|
||||
double y2 = ( lat2 - wp.ilat ) * 0.000001;
|
||||
double r12 = x1 * x1 + y1 * y1;
|
||||
double r22 = x2 * x2 + y2 * y2;
|
||||
double radius = Math.abs( r12 < r22 ? y1 * dx - x1 * dy : y2 * dx - x2 * dy ) / d;
|
||||
|
||||
if ( radius < mwp.radius )
|
||||
{
|
||||
double s1 = x1 * dx + y1 * dy;
|
||||
double s2 = x2 * dx + y2 * dy;
|
||||
|
||||
if ( s1 < 0. )
|
||||
{
|
||||
s1 = -s1;
|
||||
s2 = -s2;
|
||||
}
|
||||
if ( s2 > 0. )
|
||||
{
|
||||
radius = Math.sqrt( s1 < s2 ? r12 : r22 );
|
||||
if ( radius > mwp.radius )
|
||||
continue;
|
||||
}
|
||||
// new match for that waypoint
|
||||
mwp.radius = radius; // shortest distance to way
|
||||
mwp.hasUpdate = true;
|
||||
anyUpdate = true;
|
||||
// calculate crosspoint
|
||||
if ( mwp.crosspoint == null )
|
||||
mwp.crosspoint = new OsmNodeNamed();
|
||||
if ( s2 < 0. )
|
||||
{
|
||||
double wayfraction = -s2 / ( d * d );
|
||||
double xm = x2 - wayfraction * dx;
|
||||
double ym = y2 - wayfraction * dy;
|
||||
mwp.crosspoint.ilon = (int) ( xm / coslat6 + wp.ilon );
|
||||
mwp.crosspoint.ilat = (int) ( ym / 0.000001 + wp.ilat );
|
||||
}
|
||||
else if ( s1 > s2 )
|
||||
{
|
||||
mwp.crosspoint.ilon = lon2;
|
||||
mwp.crosspoint.ilat = lat2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mwp.crosspoint.ilon = lon1;
|
||||
mwp.crosspoint.ilat = lat1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startNode( int ilon, int ilat )
|
||||
{
|
||||
lonLast = lonStart = ilon;
|
||||
latLast = latStart = ilat;
|
||||
anyUpdate = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferNode( int ilon, int ilat )
|
||||
{
|
||||
checkSegment( lonLast, latLast, ilon, ilat );
|
||||
lonLast = ilon;
|
||||
latLast = ilat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endNode( int ilon, int ilat )
|
||||
{
|
||||
checkSegment( lonLast, latLast, ilon, ilat );
|
||||
if ( anyUpdate )
|
||||
{
|
||||
for ( MatchedWaypoint mwp : waypoints )
|
||||
{
|
||||
if ( mwp.hasUpdate )
|
||||
{
|
||||
mwp.hasUpdate = false;
|
||||
mwp.node1 = new OsmNode( lonStart, latStart );
|
||||
mwp.node2 = new OsmNode( ilon, ilat );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue