automatically ignore islands
This commit is contained in:
parent
230765106e
commit
971a5e904b
8 changed files with 203 additions and 22 deletions
|
@ -170,9 +170,15 @@ public final class MicroCache2 extends MicroCache
|
||||||
if ( !isReverse ) // write geometry for forward links only
|
if ( !isReverse ) // write geometry for forward links only
|
||||||
{
|
{
|
||||||
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
|
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
|
||||||
if ( matcher != null ) matcher.startNode( ilon, ilat, wayTags.data );
|
|
||||||
int ilontarget = ilon + dlon_remaining;
|
int ilontarget = ilon + dlon_remaining;
|
||||||
int ilattarget = ilat + dlat_remaining;
|
int ilattarget = ilat + dlat_remaining;
|
||||||
|
if ( matcher != null )
|
||||||
|
{
|
||||||
|
if ( !matcher.start( ilon, ilat, ilontarget, ilattarget ) )
|
||||||
|
{
|
||||||
|
matcher = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int transcount = bc.decodeVarBits();
|
int transcount = bc.decodeVarBits();
|
||||||
if ( debug ) System.out.println( "*** decoding geometry with count=" + transcount );
|
if ( debug ) System.out.println( "*** decoding geometry with count=" + transcount );
|
||||||
|
@ -194,7 +200,7 @@ public final class MicroCache2 extends MicroCache
|
||||||
|
|
||||||
if ( matcher != null ) matcher.transferNode( ilontarget - dlon_remaining, ilattarget - dlat_remaining );
|
if ( matcher != null ) matcher.transferNode( ilontarget - dlon_remaining, ilattarget - dlat_remaining );
|
||||||
}
|
}
|
||||||
if ( matcher != null ) matcher.endNode( ilontarget, ilattarget );
|
if ( matcher != null ) matcher.end();
|
||||||
}
|
}
|
||||||
if ( wayTags != null )
|
if ( wayTags != null )
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ package btools.codec;
|
||||||
*/
|
*/
|
||||||
public interface WaypointMatcher
|
public interface WaypointMatcher
|
||||||
{
|
{
|
||||||
void startNode( int ilon, int ilat, byte[] wayTags );
|
boolean start( int ilonStart, int ilatStart, int ilonTarget, int ilatTarget );
|
||||||
void transferNode( int ilon, int ilat );
|
void transferNode( int ilon, int ilat );
|
||||||
void endNode( int ilon, int ilat );
|
void end();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import btools.mapaccess.NodesCache;
|
||||||
import btools.mapaccess.OsmLink;
|
import btools.mapaccess.OsmLink;
|
||||||
import btools.mapaccess.OsmLinkHolder;
|
import btools.mapaccess.OsmLinkHolder;
|
||||||
import btools.mapaccess.OsmNode;
|
import btools.mapaccess.OsmNode;
|
||||||
|
import btools.mapaccess.OsmNodePairSet;
|
||||||
import btools.mapaccess.OsmNodesMap;
|
import btools.mapaccess.OsmNodesMap;
|
||||||
import btools.util.SortedHeap;
|
import btools.util.SortedHeap;
|
||||||
import btools.util.StackSampler;
|
import btools.util.StackSampler;
|
||||||
|
@ -31,6 +32,8 @@ public class RoutingEngine extends Thread
|
||||||
private int linksProcessed = 0;
|
private int linksProcessed = 0;
|
||||||
|
|
||||||
private int nodeLimit; // used for target island search
|
private int nodeLimit; // used for target island search
|
||||||
|
private int MAXNODES_ISLAND_CHECK = 500;
|
||||||
|
private OsmNodePairSet islandNodePairs = new OsmNodePairSet(MAXNODES_ISLAND_CHECK);
|
||||||
|
|
||||||
protected OsmTrack foundTrack = new OsmTrack();
|
protected OsmTrack foundTrack = new OsmTrack();
|
||||||
private OsmTrack foundRawTrack = null;
|
private OsmTrack foundRawTrack = null;
|
||||||
|
@ -329,9 +332,24 @@ public class RoutingEngine extends Thread
|
||||||
terminate();
|
terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private OsmTrack findTrack( OsmTrack[] refTracks, OsmTrack[] lastTracks )
|
private OsmTrack findTrack( OsmTrack[] refTracks, OsmTrack[] lastTracks )
|
||||||
|
{
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return tryFindTrack( refTracks, lastTracks );
|
||||||
|
}
|
||||||
|
catch( RoutingIslandException rie )
|
||||||
|
{
|
||||||
|
islandNodePairs.freezeTempPairs();
|
||||||
|
nodesCache.clean( true );
|
||||||
|
matchedWaypoints = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OsmTrack tryFindTrack( OsmTrack[] refTracks, OsmTrack[] lastTracks )
|
||||||
{
|
{
|
||||||
OsmTrack totaltrack = new OsmTrack();
|
OsmTrack totaltrack = new OsmTrack();
|
||||||
int nUnmatched = waypoints.size();
|
int nUnmatched = waypoints.size();
|
||||||
|
@ -378,7 +396,7 @@ public class RoutingEngine extends Thread
|
||||||
airDistanceCostFactor = 0.;
|
airDistanceCostFactor = 0.;
|
||||||
for( int i=0; i<matchedWaypoints.size() -1; i++ )
|
for( int i=0; i<matchedWaypoints.size() -1; i++ )
|
||||||
{
|
{
|
||||||
nodeLimit = 200;
|
nodeLimit = MAXNODES_ISLAND_CHECK;
|
||||||
if ( routingContext.inverseRouting )
|
if ( routingContext.inverseRouting )
|
||||||
{
|
{
|
||||||
OsmTrack seg = findTrack( "start-island-check", matchedWaypoints.get(i), matchedWaypoints.get(i+1), null, null, false );
|
OsmTrack seg = findTrack( "start-island-check", matchedWaypoints.get(i), matchedWaypoints.get(i+1), null, null, false );
|
||||||
|
@ -436,7 +454,7 @@ public class RoutingEngine extends Thread
|
||||||
private void matchWaypointsToNodes( List<MatchedWaypoint> unmatchedWaypoints )
|
private void matchWaypointsToNodes( List<MatchedWaypoint> unmatchedWaypoints )
|
||||||
{
|
{
|
||||||
resetCache( false );
|
resetCache( false );
|
||||||
nodesCache.waypointMatcher = new WaypointMatcherImpl( unmatchedWaypoints, 250. );
|
nodesCache.waypointMatcher = new WaypointMatcherImpl( unmatchedWaypoints, 250., islandNodePairs );
|
||||||
for( MatchedWaypoint mwp : unmatchedWaypoints )
|
for( MatchedWaypoint mwp : unmatchedWaypoints )
|
||||||
{
|
{
|
||||||
preloadPosition( mwp.waypoint );
|
preloadPosition( mwp.waypoint );
|
||||||
|
@ -467,10 +485,13 @@ public class RoutingEngine extends Thread
|
||||||
}
|
}
|
||||||
for( int idxLat=-1; idxLat<=1; idxLat++ )
|
for( int idxLat=-1; idxLat<=1; idxLat++ )
|
||||||
for( int idxLon=-1; idxLon<=1; idxLon++ )
|
for( int idxLon=-1; idxLon<=1; idxLon++ )
|
||||||
|
{
|
||||||
|
if ( idxLon != 0 || idxLat != 0 )
|
||||||
{
|
{
|
||||||
nodesCache.loadSegmentFor( n.ilon + d*idxLon , n.ilat +d*idxLat );
|
nodesCache.loadSegmentFor( n.ilon + d*idxLon , n.ilat +d*idxLat );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -609,6 +630,7 @@ public class RoutingEngine extends Thread
|
||||||
long maxmem = routingContext.memoryclass * 131072L; // 1/8 of total
|
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, nodesMap, routingContext.expctxWay, routingContext.forceSecondaryData, maxmem, nodesCache, detailed );
|
||||||
|
islandNodePairs.clearTempPairs();
|
||||||
}
|
}
|
||||||
|
|
||||||
private OsmNode getStartNode( long startId )
|
private OsmNode getStartNode( long startId )
|
||||||
|
@ -742,7 +764,7 @@ public class RoutingEngine extends Thread
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
nodesCache.cleanNonVirgin();
|
nodesCache.clean( false ); // clean only non-virgin caches
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,6 +901,10 @@ public class RoutingEngine extends Thread
|
||||||
OsmNode currentNode = path.getTargetNode();
|
OsmNode currentNode = path.getTargetNode();
|
||||||
|
|
||||||
long currentNodeId = currentNode.getIdFromPos();
|
long currentNodeId = currentNode.getIdFromPos();
|
||||||
|
long sourceNodeId = sourceNode.getIdFromPos();
|
||||||
|
|
||||||
|
islandNodePairs.addTempPair( sourceNodeId, currentNodeId );
|
||||||
|
|
||||||
if ( path.treedepth != 1 )
|
if ( path.treedepth != 1 )
|
||||||
{
|
{
|
||||||
if ( path.treedepth == 0 ) // hack: sameSegment Paths marked treedepth=0 to pass above check
|
if ( path.treedepth == 0 ) // hack: sameSegment Paths marked treedepth=0 to pass above check
|
||||||
|
@ -886,7 +912,6 @@ public class RoutingEngine extends Thread
|
||||||
path.treedepth = 1;
|
path.treedepth = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
long sourceNodeId = sourceNode.getIdFromPos();
|
|
||||||
if ( ( sourceNodeId == endNodeId1 && currentNodeId == endNodeId2 )
|
if ( ( sourceNodeId == endNodeId1 && currentNodeId == endNodeId2 )
|
||||||
|| ( sourceNodeId == endNodeId2 && currentNodeId == endNodeId1 ) )
|
|| ( sourceNodeId == endNodeId2 && currentNodeId == endNodeId1 ) )
|
||||||
{
|
{
|
||||||
|
@ -1126,6 +1151,12 @@ public class RoutingEngine extends Thread
|
||||||
|
|
||||||
path.unregisterUpTree( routingContext );
|
path.unregisterUpTree( routingContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( nodesVisited < MAXNODES_ISLAND_CHECK && islandNodePairs.getFreezeCount() < 5 )
|
||||||
|
{
|
||||||
|
throw new RoutingIslandException();
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package btools.router;
|
||||||
|
|
||||||
|
public class RoutingIslandException extends RuntimeException
|
||||||
|
{
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
||||||
|
|
||||||
import btools.codec.WaypointMatcher;
|
import btools.codec.WaypointMatcher;
|
||||||
import btools.mapaccess.OsmNode;
|
import btools.mapaccess.OsmNode;
|
||||||
|
import btools.mapaccess.OsmNodePairSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the WaypointMatcher is feeded by the decoder with geoemtries of ways that are
|
* the WaypointMatcher is feeded by the decoder with geoemtries of ways that are
|
||||||
|
@ -15,16 +16,20 @@ import btools.mapaccess.OsmNode;
|
||||||
public final class WaypointMatcherImpl implements WaypointMatcher
|
public final class WaypointMatcherImpl implements WaypointMatcher
|
||||||
{
|
{
|
||||||
private List<MatchedWaypoint> waypoints;
|
private List<MatchedWaypoint> waypoints;
|
||||||
|
private OsmNodePairSet islandPairs;
|
||||||
|
|
||||||
private int lonStart;
|
private int lonStart;
|
||||||
private int latStart;
|
private int latStart;
|
||||||
|
private int lonTarget;
|
||||||
|
private int latTarget;
|
||||||
private boolean anyUpdate;
|
private boolean anyUpdate;
|
||||||
private int lonLast;
|
private int lonLast;
|
||||||
private int latLast;
|
private int latLast;
|
||||||
|
|
||||||
public WaypointMatcherImpl( List<MatchedWaypoint> waypoints, double maxDistance )
|
public WaypointMatcherImpl( List<MatchedWaypoint> waypoints, double maxDistance, OsmNodePairSet islandPairs )
|
||||||
{
|
{
|
||||||
this.waypoints = waypoints;
|
this.waypoints = waypoints;
|
||||||
|
this.islandPairs = islandPairs;
|
||||||
for ( MatchedWaypoint mwp : waypoints )
|
for ( MatchedWaypoint mwp : waypoints )
|
||||||
{
|
{
|
||||||
mwp.radius = maxDistance * 110984.; // 6378000. / 57.3;
|
mwp.radius = maxDistance * 110984.; // 6378000. / 57.3;
|
||||||
|
@ -105,11 +110,23 @@ public final class WaypointMatcherImpl implements WaypointMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startNode( int ilon, int ilat, byte[] wayTags )
|
public boolean start( int ilonStart, int ilatStart, int ilonTarget, int ilatTarget )
|
||||||
{
|
{
|
||||||
lonLast = lonStart = ilon;
|
if ( islandPairs.size() > 0 )
|
||||||
latLast = latStart = ilat;
|
{
|
||||||
|
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;
|
anyUpdate = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -121,9 +138,9 @@ public final class WaypointMatcherImpl implements WaypointMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endNode( int ilon, int ilat )
|
public void end()
|
||||||
{
|
{
|
||||||
checkSegment( lonLast, latLast, ilon, ilat );
|
checkSegment( lonLast, latLast, lonTarget, latTarget );
|
||||||
if ( anyUpdate )
|
if ( anyUpdate )
|
||||||
{
|
{
|
||||||
for ( MatchedWaypoint mwp : waypoints )
|
for ( MatchedWaypoint mwp : waypoints )
|
||||||
|
@ -132,7 +149,7 @@ public final class WaypointMatcherImpl implements WaypointMatcher
|
||||||
{
|
{
|
||||||
mwp.hasUpdate = false;
|
mwp.hasUpdate = false;
|
||||||
mwp.node1 = new OsmNode( lonStart, latStart );
|
mwp.node1 = new OsmNode( lonStart, latStart );
|
||||||
mwp.node2 = new OsmNode( ilon, ilat );
|
mwp.node2 = new OsmNode( lonTarget, latTarget );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ public final class NodesCache
|
||||||
ghostSum = cacheSum;
|
ghostSum = cacheSum;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanNonVirgin()
|
public void clean( boolean all )
|
||||||
{
|
{
|
||||||
for ( OsmFile[] fileRow : fileRows )
|
for ( OsmFile[] fileRow : fileRows )
|
||||||
{
|
{
|
||||||
|
@ -118,7 +118,7 @@ public final class NodesCache
|
||||||
continue;
|
continue;
|
||||||
for ( OsmFile osmf : fileRow )
|
for ( OsmFile osmf : fileRow )
|
||||||
{
|
{
|
||||||
osmf.cleanNonVirgin();
|
osmf.clean( all);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,7 +217,7 @@ final class OsmFile
|
||||||
return deleted;
|
return deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanNonVirgin()
|
void clean( boolean all )
|
||||||
{
|
{
|
||||||
int nc = microCaches == null ? 0 : microCaches.length;
|
int nc = microCaches == null ? 0 : microCaches.length;
|
||||||
for ( int i = 0; i < nc; i++ )
|
for ( int i = 0; i < nc; i++ )
|
||||||
|
@ -225,7 +225,7 @@ final class OsmFile
|
||||||
MicroCache mc = microCaches[i];
|
MicroCache mc = microCaches[i];
|
||||||
if ( mc == null )
|
if ( mc == null )
|
||||||
continue;
|
continue;
|
||||||
if ( !mc.virgin )
|
if ( all || !mc.virgin )
|
||||||
{
|
{
|
||||||
microCaches[i] = null;
|
microCaches[i] = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/**
|
||||||
|
* Set holding pairs of osm nodes
|
||||||
|
*
|
||||||
|
* @author ab
|
||||||
|
*/
|
||||||
|
package btools.mapaccess;
|
||||||
|
|
||||||
|
import btools.util.CompactLongMap;
|
||||||
|
|
||||||
|
public class OsmNodePairSet
|
||||||
|
{
|
||||||
|
private long[] n1a;
|
||||||
|
private long[] n2a;
|
||||||
|
private int tempNodes = 0;
|
||||||
|
private int maxTempNodes = 0;
|
||||||
|
private int npairs = 0;
|
||||||
|
private int freezecount = 0;
|
||||||
|
|
||||||
|
public OsmNodePairSet( int maxTempNodeCount )
|
||||||
|
{
|
||||||
|
maxTempNodes = maxTempNodeCount;
|
||||||
|
n1a = new long[maxTempNodes];
|
||||||
|
n2a = new long[maxTempNodes];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class OsmNodePair
|
||||||
|
{
|
||||||
|
public long node2;
|
||||||
|
public OsmNodePair next;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompactLongMap<OsmNodePair> map;
|
||||||
|
|
||||||
|
public void addTempPair( long n1, long n2 )
|
||||||
|
{
|
||||||
|
if ( tempNodes < maxTempNodes )
|
||||||
|
{
|
||||||
|
n1a[tempNodes] = n1;
|
||||||
|
n2a[tempNodes] = n2;
|
||||||
|
tempNodes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void freezeTempPairs()
|
||||||
|
{
|
||||||
|
freezecount++;
|
||||||
|
for( int i=0; i<tempNodes; i++ )
|
||||||
|
{
|
||||||
|
addPair( n1a[i], n2a[i] );
|
||||||
|
}
|
||||||
|
tempNodes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearTempPairs()
|
||||||
|
{
|
||||||
|
tempNodes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPair( long n1, long n2 )
|
||||||
|
{
|
||||||
|
if ( map == null )
|
||||||
|
{
|
||||||
|
map = new CompactLongMap<OsmNodePair>();
|
||||||
|
}
|
||||||
|
npairs++;
|
||||||
|
|
||||||
|
OsmNodePair e = getElement( n1, n2 );
|
||||||
|
if ( e == null )
|
||||||
|
{
|
||||||
|
e = new OsmNodePair();
|
||||||
|
e.node2 = n2;
|
||||||
|
|
||||||
|
OsmNodePair e0 = map.get( n1 );
|
||||||
|
if ( e0 != null )
|
||||||
|
{
|
||||||
|
while( e0.next != null )
|
||||||
|
{
|
||||||
|
e0 = e0.next;
|
||||||
|
}
|
||||||
|
e0.next = e;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
map.fastPut( n1, e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return npairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int tempSize()
|
||||||
|
{
|
||||||
|
return tempNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFreezeCount()
|
||||||
|
{
|
||||||
|
return freezecount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPair( long n1, long n2 )
|
||||||
|
{
|
||||||
|
return map != null && ( getElement( n1, n2 ) != null || getElement( n2, n1 ) != null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private OsmNodePair getElement( long n1, long n2 )
|
||||||
|
{
|
||||||
|
OsmNodePair e = map.get( n1 );
|
||||||
|
while (e != null)
|
||||||
|
{
|
||||||
|
if ( e.node2 == n2 )
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
e = e.next;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue