automatically ignore islands

This commit is contained in:
Arndt Brenschede 2018-04-02 19:19:52 +02:00
parent 230765106e
commit 971a5e904b
8 changed files with 203 additions and 22 deletions

View file

@ -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 )
{ {

View file

@ -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();
} }

View file

@ -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;
} }

View file

@ -0,0 +1,5 @@
package btools.router;
public class RoutingIslandException extends RuntimeException
{
}

View file

@ -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 );
} }
} }
} }

View file

@ -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);
} }
} }
} }

View file

@ -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;
} }

View file

@ -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;
}
}