refactored waypoint-matching into map-access-layer
This commit is contained in:
parent
02b8202001
commit
9e64eb39c4
6 changed files with 148 additions and 129 deletions
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
* Information on matched way point
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.router;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
import btools.mapaccess.OsmNode;
|
||||
|
||||
final class MatchedWaypoint
|
||||
{
|
||||
public OsmNode node1;
|
||||
public OsmNode node2;
|
||||
public OsmNodeNamed crosspoint;
|
||||
public OsmNodeNamed waypoint;
|
||||
public double radius; // radius in meters
|
||||
public boolean hasUpdate;
|
||||
|
||||
public void writeToStream( DataOutput dos ) throws IOException
|
||||
{
|
||||
dos.writeInt( node1.ilat );
|
||||
dos.writeInt( node1.ilon );
|
||||
dos.writeInt( node2.ilat );
|
||||
dos.writeInt( node2.ilon );
|
||||
dos.writeInt( crosspoint.ilat );
|
||||
dos.writeInt( crosspoint.ilon );
|
||||
dos.writeInt( waypoint.ilat );
|
||||
dos.writeInt( waypoint.ilon );
|
||||
dos.writeDouble( radius );
|
||||
}
|
||||
|
||||
public static MatchedWaypoint readFromStream( DataInput dis ) throws IOException
|
||||
{
|
||||
MatchedWaypoint mwp = new MatchedWaypoint();
|
||||
mwp.node1 = new OsmNode();
|
||||
mwp.node2 = new OsmNode();
|
||||
mwp.crosspoint = new OsmNodeNamed();
|
||||
mwp.waypoint = new OsmNodeNamed();
|
||||
|
||||
mwp.node1.ilat = dis.readInt();
|
||||
mwp.node1.ilon = dis.readInt();
|
||||
mwp.node2.ilat = dis.readInt();
|
||||
mwp.node2.ilon = dis.readInt();
|
||||
mwp.crosspoint.ilat = dis.readInt();
|
||||
mwp.crosspoint.ilon = dis.readInt();
|
||||
mwp.waypoint.ilat = dis.readInt();
|
||||
mwp.waypoint.ilon = dis.readInt();
|
||||
mwp.radius = dis.readDouble();
|
||||
return mwp;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -15,6 +15,15 @@ public class OsmNodeNamed extends OsmNode
|
|||
public double nogoWeight; // weight for nogopoint
|
||||
public boolean isNogo = false;
|
||||
|
||||
public OsmNodeNamed()
|
||||
{
|
||||
}
|
||||
|
||||
public OsmNodeNamed( OsmNode n)
|
||||
{
|
||||
super( n.ilon, n.ilat );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ import java.io.File;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import btools.mapaccess.MatchedWaypoint;
|
||||
import btools.mapaccess.OsmPos;
|
||||
import btools.util.CompactLongMap;
|
||||
import btools.util.FrozenLongMap;
|
||||
|
|
|
|||
|
|
@ -10,18 +10,17 @@ import java.util.ArrayList;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import btools.mapaccess.MatchedWaypoint;
|
||||
import btools.mapaccess.NodesCache;
|
||||
import btools.mapaccess.OsmLink;
|
||||
import btools.mapaccess.OsmLinkHolder;
|
||||
import btools.mapaccess.OsmNode;
|
||||
import btools.mapaccess.OsmNodePairSet;
|
||||
import btools.mapaccess.OsmNodesMap;
|
||||
import btools.util.SortedHeap;
|
||||
import btools.util.StackSampler;
|
||||
|
||||
public class RoutingEngine extends Thread
|
||||
{
|
||||
private OsmNodesMap nodesMap;
|
||||
private NodesCache nodesCache;
|
||||
private SortedHeap<OsmPath> openSet = new SortedHeap<OsmPath>();
|
||||
private boolean finished = false;
|
||||
|
|
@ -326,7 +325,6 @@ public class RoutingEngine extends Thread
|
|||
|
||||
public void cleanOnOOM()
|
||||
{
|
||||
nodesMap = null;
|
||||
terminate();
|
||||
}
|
||||
|
||||
|
|
@ -385,6 +383,7 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
MatchedWaypoint mwp = new MatchedWaypoint();
|
||||
mwp.waypoint = waypoints.get(i);
|
||||
mwp.name = waypoints.get(i).name;
|
||||
matchedWaypoints.add( mwp );
|
||||
}
|
||||
matchWaypointsToNodes( matchedWaypoints );
|
||||
|
|
@ -452,46 +451,9 @@ public class RoutingEngine extends Thread
|
|||
private void matchWaypointsToNodes( List<MatchedWaypoint> unmatchedWaypoints )
|
||||
{
|
||||
resetCache( false );
|
||||
nodesCache.waypointMatcher = new WaypointMatcherImpl( unmatchedWaypoints, 250., islandNodePairs );
|
||||
for( MatchedWaypoint mwp : unmatchedWaypoints )
|
||||
{
|
||||
preloadPosition( mwp.waypoint );
|
||||
}
|
||||
|
||||
if ( nodesCache.first_file_access_failed )
|
||||
{
|
||||
throw new IllegalArgumentException( "datafile " + nodesCache.first_file_access_name + " not found" );
|
||||
}
|
||||
for( MatchedWaypoint mwp : unmatchedWaypoints )
|
||||
{
|
||||
if ( mwp.crosspoint == null )
|
||||
{
|
||||
throw new IllegalArgumentException( mwp.waypoint.name + "-position not mapped in existing datafile" );
|
||||
}
|
||||
}
|
||||
nodesCache.matchWaypointsToNodes( unmatchedWaypoints, 250., islandNodePairs );
|
||||
}
|
||||
|
||||
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++ )
|
||||
{
|
||||
if ( idxLon != 0 || idxLat != 0 )
|
||||
{
|
||||
nodesCache.loadSegmentFor( n.ilon + d*idxLon , n.ilat +d*idxLat );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private OsmTrack searchTrack( MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack )
|
||||
{
|
||||
OsmTrack track = null;
|
||||
|
|
@ -613,30 +575,15 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
logInfo( "NodesCache status before reset=" + nodesCache.formatStatus() );
|
||||
}
|
||||
nodesMap = new OsmNodesMap();
|
||||
|
||||
long maxmem = routingContext.memoryclass * 131072L; // 1/8 of total
|
||||
|
||||
nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay, routingContext.forceSecondaryData, maxmem, nodesCache, detailed );
|
||||
nodesCache = new NodesCache(segmentDir, routingContext.expctxWay, routingContext.forceSecondaryData, maxmem, nodesCache, detailed );
|
||||
islandNodePairs.clearTempPairs();
|
||||
}
|
||||
|
||||
private OsmNode getStartNode( long startId )
|
||||
{
|
||||
// initialize the start-node
|
||||
OsmNode start = new OsmNode( startId );
|
||||
start.setHollow();
|
||||
if ( !nodesCache.obtainNonHollowNode( start ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
nodesCache.expandHollowLinkTargets( start );
|
||||
return start;
|
||||
}
|
||||
|
||||
private OsmPath getStartPath( OsmNode n1, OsmNode n2, MatchedWaypoint mwp, OsmNodeNamed endPos, boolean sameSegmentSearch )
|
||||
{
|
||||
OsmPath p = getStartPath( n1, n2, mwp.waypoint, endPos );
|
||||
OsmPath p = getStartPath( n1, n2, new OsmNodeNamed( mwp.waypoint ), endPos );
|
||||
|
||||
// special case: start+end on same segment
|
||||
if ( sameSegmentSearch )
|
||||
|
|
@ -680,7 +627,7 @@ public class RoutingEngine extends Thread
|
|||
|
||||
|
||||
|
||||
private OsmPath getStartPath( OsmNode n1, OsmNode n2, OsmNodeNamed wp, OsmNode endPos )
|
||||
private OsmPath getStartPath( OsmNode n1, OsmNode n2, OsmNodeNamed wp, OsmNodeNamed endPos )
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -775,12 +722,12 @@ public class RoutingEngine extends Thread
|
|||
long startNodeId1 = startWp.node1.getIdFromPos();
|
||||
long startNodeId2 = startWp.node2.getIdFromPos();
|
||||
|
||||
OsmNodeNamed endPos = endWp == null ? null : endWp.crosspoint;
|
||||
OsmNodeNamed endPos = endWp == null ? null : new OsmNodeNamed( endWp.crosspoint );
|
||||
|
||||
boolean sameSegmentSearch = ( startNodeId1 == endNodeId1 && startNodeId2 == endNodeId2 )
|
||||
|| ( startNodeId1 == endNodeId2 && startNodeId2 == endNodeId1 );
|
||||
|
||||
OsmNode start1 = getStartNode( startNodeId1 );
|
||||
OsmNode start1 = nodesCache.getStartNode( startNodeId1 );
|
||||
if ( start1 == null ) return null;
|
||||
OsmNode start2 = null;
|
||||
for( OsmLink link = start1.firstlink; link != null; link = link.getNext( start1 ) )
|
||||
|
|
@ -793,11 +740,6 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
if ( start2 == null ) return null;
|
||||
|
||||
|
||||
|
||||
|
||||
if ( start1 == null || start2 == null ) return null;
|
||||
|
||||
routingContext.startDirectionValid = routingContext.forceUseStartDirection || fastPartialRecalc;
|
||||
routingContext.startDirectionValid &= routingContext.startDirection != null && !routingContext.inverseDirection;
|
||||
if ( routingContext.startDirectionValid )
|
||||
|
|
|
|||
|
|
@ -1,157 +0,0 @@
|
|||
package btools.router;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import btools.codec.WaypointMatcher;
|
||||
import btools.mapaccess.OsmNode;
|
||||
import btools.mapaccess.OsmNodePairSet;
|
||||
import btools.util.CheapRuler;
|
||||
|
||||
/**
|
||||
* 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 OsmNodePairSet islandPairs;
|
||||
|
||||
private int lonStart;
|
||||
private int latStart;
|
||||
private int lonTarget;
|
||||
private int latTarget;
|
||||
private boolean anyUpdate;
|
||||
private int lonLast;
|
||||
private int latLast;
|
||||
|
||||
public WaypointMatcherImpl( List<MatchedWaypoint> waypoints, double maxDistance, OsmNodePairSet islandPairs )
|
||||
{
|
||||
this.waypoints = waypoints;
|
||||
this.islandPairs = islandPairs;
|
||||
for ( MatchedWaypoint mwp : waypoints )
|
||||
{
|
||||
mwp.radius = maxDistance;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSegment( int lon1, int lat1, int lon2, int lat2 )
|
||||
{
|
||||
// todo: bounding-box pre-filter
|
||||
|
||||
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (lat1+lat2) >> 1 );
|
||||
double dlon2m = lonlat2m[0];
|
||||
double dlat2m = lonlat2m[1];
|
||||
|
||||
double dx = ( lon2 - lon1 ) * dlon2m;
|
||||
double dy = ( lat2 - lat1 ) * dlat2m;
|
||||
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 ) * dlon2m;
|
||||
double y1 = ( lat1 - wp.ilat ) * dlat2m;
|
||||
double x2 = ( lon2 - wp.ilon ) * dlon2m;
|
||||
double y2 = ( lat2 - wp.ilat ) * dlat2m;
|
||||
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 / dlon2m + wp.ilon );
|
||||
mwp.crosspoint.ilat = (int) ( ym / dlat2m + 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 boolean start( int ilonStart, int ilatStart, int ilonTarget, int ilatTarget )
|
||||
{
|
||||
if ( islandPairs.size() > 0 )
|
||||
{
|
||||
long n1 = ( (long) ilonStart ) << 32 | ilatStart;
|
||||
long n2 = ( (long) ilonTarget ) << 32 | ilatTarget;
|
||||
if ( islandPairs.hasPair( n1, n2 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
lonLast = lonStart = ilonStart;
|
||||
latLast = latStart = ilatStart;
|
||||
lonTarget = ilonTarget;
|
||||
latTarget = ilatTarget;
|
||||
anyUpdate = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferNode( int ilon, int ilat )
|
||||
{
|
||||
checkSegment( lonLast, latLast, ilon, ilat );
|
||||
lonLast = ilon;
|
||||
latLast = ilat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end()
|
||||
{
|
||||
checkSegment( lonLast, latLast, lonTarget, latTarget );
|
||||
if ( anyUpdate )
|
||||
{
|
||||
for ( MatchedWaypoint mwp : waypoints )
|
||||
{
|
||||
if ( mwp.hasUpdate )
|
||||
{
|
||||
mwp.hasUpdate = false;
|
||||
mwp.node1 = new OsmNode( lonStart, latStart );
|
||||
mwp.node2 = new OsmNode( lonTarget, latTarget );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue