1.4.6 (memory footprint)
This commit is contained in:
parent
448bb11ad4
commit
56bdf76806
27 changed files with 613 additions and 454 deletions
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-codec</artifactId>
|
||||
|
|
|
@ -56,6 +56,8 @@ public final class MicroCache2 extends MicroCache
|
|||
faid = size > dataBuffers.ibuf2.length ? new int[size] : dataBuffers.ibuf2;
|
||||
fapos = size > dataBuffers.ibuf3.length ? new int[size] : dataBuffers.ibuf3;
|
||||
|
||||
|
||||
|
||||
int[] alon = size > dataBuffers.alon.length ? new int[size] : dataBuffers.alon;
|
||||
int[] alat = size > dataBuffers.alat.length ? new int[size] : dataBuffers.alat;
|
||||
|
||||
|
@ -73,7 +75,9 @@ public final class MicroCache2 extends MicroCache
|
|||
int netdatasize = bc.decodeNoisyNumber( 10 );
|
||||
ab = netdatasize > dataBuffers.bbuf1.length ? new byte[netdatasize] : dataBuffers.bbuf1;
|
||||
aboffset = 0;
|
||||
BitSet validNodes = new BitSet( size );
|
||||
|
||||
int[] validBits = new int[(size+31)>>5];
|
||||
|
||||
int finaldatasize = 0;
|
||||
|
||||
LinkedListContainer reverseLinks = new LinkedListContainer( size, dataBuffers.ibuf1 );
|
||||
|
@ -130,12 +134,12 @@ public final class MicroCache2 extends MicroCache
|
|||
writeVarLengthSigned( dlon_remaining );
|
||||
writeVarLengthSigned( dlat_remaining );
|
||||
|
||||
validNodes.set( n, true ); // mark source-node valid
|
||||
validBits[ n >> 5 ] |= 1 << n; // mark source-node valid
|
||||
if ( nodeIdx != n ) // valid internal (forward-) link
|
||||
{
|
||||
reverseLinks.addDataElement( nodeIdx, n ); // register reverse link
|
||||
finaldatasize += 1 + aboffset-startPointer; // reserve place for reverse
|
||||
validNodes.set( nodeIdx, true ); // mark target-node valid
|
||||
validBits[ nodeIdx >> 5 ] |= 1 << nodeIdx; // mark target-node valid
|
||||
}
|
||||
writeModeAndDesc( isReverse, wayTags.data );
|
||||
}
|
||||
|
@ -179,15 +183,16 @@ public final class MicroCache2 extends MicroCache
|
|||
|
||||
// calculate final data size
|
||||
int finalsize = 0;
|
||||
int startpos = 0;
|
||||
for( int i=0; i<size; i++ )
|
||||
{
|
||||
int startpos = i > 0 ? fapos[i-1] : 0;
|
||||
int endpos = fapos[i];
|
||||
if ( validNodes.get( i ) )
|
||||
if ( ( validBits[ i >> 5 ] & (1 << i ) ) != 0 )
|
||||
{
|
||||
finaldatasize += endpos-startpos;
|
||||
finalsize++;
|
||||
}
|
||||
startpos = endpos;
|
||||
}
|
||||
// append the reverse links at the end of each node
|
||||
byte[] abOld = ab;
|
||||
|
@ -200,21 +205,21 @@ public final class MicroCache2 extends MicroCache
|
|||
aboffset = 0;
|
||||
size = 0;
|
||||
|
||||
startpos = 0;
|
||||
for ( int n = 0; n < sizeOld; n++ )
|
||||
{
|
||||
if ( !validNodes.get( n ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int startpos = n > 0 ? faposOld[n-1] : 0;
|
||||
int endpos = faposOld[n];
|
||||
if ( ( validBits[ n >> 5 ] & (1 << n ) ) != 0 )
|
||||
{
|
||||
int len = endpos - startpos;
|
||||
System.arraycopy( abOld, startpos, ab, aboffset, len );
|
||||
if ( debug ) System.out.println( "*** copied " + len + " bytes from " + aboffset + " for node " + n );
|
||||
if ( debug )
|
||||
System.out.println( "*** copied " + len + " bytes from " + aboffset + " for node " + n );
|
||||
aboffset += len;
|
||||
|
||||
int cnt = reverseLinks.initList( n );
|
||||
if ( debug ) System.out.println( "*** appending " + cnt + " reverse links for node " + n );
|
||||
if ( debug )
|
||||
System.out.println( "*** appending " + cnt + " reverse links for node " + n );
|
||||
|
||||
for ( int ri = 0; ri < cnt; ri++ )
|
||||
{
|
||||
|
@ -229,6 +234,8 @@ public final class MicroCache2 extends MicroCache
|
|||
fapos[size] = aboffset;
|
||||
size++;
|
||||
}
|
||||
startpos = endpos;
|
||||
}
|
||||
init( size );
|
||||
}
|
||||
|
||||
|
|
|
@ -13,4 +13,5 @@ public interface TagValueValidator
|
|||
|
||||
public boolean isLookupIdxUsed( int idx );
|
||||
|
||||
public void setDecodeForbidden( boolean decodeForbidden );
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-core</artifactId>
|
||||
|
|
|
@ -31,7 +31,9 @@ final class OsmPath implements OsmLinkHolder
|
|||
|
||||
public int airdistance = 0; // distance to endpos
|
||||
|
||||
private OsmNode sourcenode;
|
||||
private OsmNode sourceNode;
|
||||
private OsmNode targetNode;
|
||||
|
||||
private OsmLink link;
|
||||
public OsmPathElement originElement;
|
||||
public OsmPathElement myElement;
|
||||
|
@ -86,10 +88,11 @@ final class OsmPath implements OsmLinkHolder
|
|||
{
|
||||
this();
|
||||
this.link = link;
|
||||
this.selev = link.targetNode.getSElev();
|
||||
targetNode = link.getTarget( null );
|
||||
selev = targetNode.getSElev();
|
||||
}
|
||||
|
||||
OsmPath( OsmNode sourcenode, OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode, RoutingContext rc )
|
||||
OsmPath( OsmPath origin, OsmLink link, OsmTrack refTrack, boolean detailMode, RoutingContext rc )
|
||||
{
|
||||
this();
|
||||
if ( origin.myElement == null )
|
||||
|
@ -98,7 +101,8 @@ final class OsmPath implements OsmLinkHolder
|
|||
}
|
||||
this.originElement = origin.myElement;
|
||||
this.link = link;
|
||||
this.sourcenode = sourcenode;
|
||||
this.sourceNode = origin.targetNode;
|
||||
this.targetNode = link.getTarget( sourceNode );
|
||||
this.cost = origin.cost;
|
||||
this.ehbd = origin.ehbd;
|
||||
this.ehbu = origin.ehbu;
|
||||
|
@ -120,7 +124,7 @@ final class OsmPath implements OsmLinkHolder
|
|||
int lon0 = origin.originLon;
|
||||
int lat0 = origin.originLat;
|
||||
|
||||
OsmNode p1 = origin.link.targetNode;
|
||||
OsmNode p1 = sourceNode;
|
||||
int lon1 = p1.getILon();
|
||||
int lat1 = p1.getILat();
|
||||
short ele1 = origin.selev;
|
||||
|
@ -129,8 +133,10 @@ final class OsmPath implements OsmLinkHolder
|
|||
|
||||
MessageData msgData = recordMessageData ? new MessageData() : null;
|
||||
|
||||
boolean isReverse = link.isReverse( sourceNode );
|
||||
|
||||
// evaluate the way tags
|
||||
rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description );
|
||||
rc.expctxWay.evaluate( rc.inverseDirection ^ isReverse, description );
|
||||
|
||||
// calculate the costfactor inputs
|
||||
boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f;
|
||||
|
@ -163,9 +169,8 @@ final class OsmPath implements OsmLinkHolder
|
|||
// OsmTransferNode transferNode = link.decodeGeometry( p1, rc.byteDataReaderGeometry, rc.transferNodeCache );
|
||||
|
||||
OsmTransferNode transferNode = link.geometry == null ? null
|
||||
: rc.geometryDecoder.decodeGeometry( link.geometry, p1, link.targetNode, link.counterLinkWritten );
|
||||
: rc.geometryDecoder.decodeGeometry( link.geometry, p1, targetNode, isReverse );
|
||||
|
||||
OsmNode targetNode = link.targetNode;
|
||||
for(;;)
|
||||
{
|
||||
originLon = lon1;
|
||||
|
@ -355,7 +360,7 @@ final class OsmPath implements OsmLinkHolder
|
|||
msgData.lon = lon2;
|
||||
msgData.lat = lat2;
|
||||
msgData.ele = ele2;
|
||||
msgData.wayKeyValues = rc.expctxWay.getKeyValueDescription( link.counterLinkWritten, description );
|
||||
msgData.wayKeyValues = rc.expctxWay.getKeyValueDescription( isReverse, description );
|
||||
}
|
||||
|
||||
if ( stopAtEndpoint )
|
||||
|
@ -379,7 +384,7 @@ final class OsmPath implements OsmLinkHolder
|
|||
if ( transferNode == null )
|
||||
{
|
||||
// *** penalty for being part of the reference track
|
||||
if ( refTrack != null && refTrack.containsNode( targetNode ) && refTrack.containsNode( origin.link.targetNode ) )
|
||||
if ( refTrack != null && refTrack.containsNode( targetNode ) && refTrack.containsNode( sourceNode ) )
|
||||
{
|
||||
int reftrackcost = linkdisttotal;
|
||||
cost += reftrackcost;
|
||||
|
@ -465,7 +470,12 @@ final class OsmPath implements OsmLinkHolder
|
|||
|
||||
public OsmNode getSourceNode()
|
||||
{
|
||||
return sourcenode;
|
||||
return sourceNode;
|
||||
}
|
||||
|
||||
public OsmNode getTargetNode()
|
||||
{
|
||||
return targetNode;
|
||||
}
|
||||
|
||||
public OsmLink getLink()
|
||||
|
|
|
@ -67,7 +67,7 @@ public class OsmPathElement implements OsmPos
|
|||
// construct a path element from a path
|
||||
public static final OsmPathElement create( OsmPath path, boolean countTraffic )
|
||||
{
|
||||
OsmNode n = path.getLink().targetNode;
|
||||
OsmNode n = path.getTargetNode();
|
||||
OsmPathElement pe = create( n.getILon(), n.getILat(), path.selev, path.originElement, countTraffic );
|
||||
pe.cost = path.cost;
|
||||
pe.message = path.message;
|
||||
|
|
|
@ -390,7 +390,7 @@ public final class OsmTrack
|
|||
}
|
||||
else
|
||||
{
|
||||
sb.append( " creator=\"BRouter-1.4.4\" version=\"1.1\">\n" );
|
||||
sb.append( " creator=\"BRouter-1.4.6\" version=\"1.1\">\n" );
|
||||
}
|
||||
|
||||
if ( turnInstructionMode == 3) // osmand style
|
||||
|
|
|
@ -175,7 +175,7 @@ public final class RoutingContext
|
|||
}
|
||||
if ( goodGuy ) nogos.add( nogo );
|
||||
}
|
||||
nogopoints = nogos;
|
||||
nogopoints = nogos.isEmpty() ? null : nogos;
|
||||
}
|
||||
|
||||
public long[] getNogoChecksums()
|
||||
|
|
|
@ -58,6 +58,8 @@ public class RoutingEngine extends Thread
|
|||
|
||||
public boolean quite = false;
|
||||
|
||||
private Object[] extract;
|
||||
|
||||
public RoutingEngine( String outfileBase, String logfileBase, String segmentDir,
|
||||
List<OsmNodeNamed> waypoints, RoutingContext rc )
|
||||
{
|
||||
|
@ -149,6 +151,7 @@ public class RoutingEngine extends Thread
|
|||
routingContext.cleanNogolist( waypoints );
|
||||
|
||||
startTime = System.currentTimeMillis();
|
||||
long startTime0 = startTime;
|
||||
this.maxRunningTime = maxRunningTime;
|
||||
int nsections = waypoints.size() - 1;
|
||||
OsmTrack[] refTracks = new OsmTrack[nsections]; // used ways for alternatives
|
||||
|
@ -208,24 +211,21 @@ public class RoutingEngine extends Thread
|
|||
break;
|
||||
}
|
||||
long endTime = System.currentTimeMillis();
|
||||
logInfo( "execution time = " + (endTime-startTime)/1000. + " seconds" );
|
||||
logInfo( "execution time = " + (endTime-startTime0)/1000. + " seconds" );
|
||||
}
|
||||
catch( IllegalArgumentException e)
|
||||
{
|
||||
errorMessage = e.getMessage();
|
||||
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
logException( e );
|
||||
}
|
||||
catch( Exception e)
|
||||
{
|
||||
errorMessage = e instanceof IllegalArgumentException ? e.getMessage() : e.toString();
|
||||
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
logException( e );
|
||||
logThrowable( e );
|
||||
}
|
||||
catch( Error e)
|
||||
{
|
||||
cleanOnOOM();
|
||||
errorMessage = e.toString();
|
||||
logInfo( "Error (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
logException( e );
|
||||
logThrowable( e );
|
||||
}
|
||||
finally
|
||||
|
@ -264,6 +264,13 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
|
||||
private void logException( Throwable t )
|
||||
{
|
||||
errorMessage = t instanceof IllegalArgumentException ? t.getMessage() : t.toString();
|
||||
logInfo( "Error (linksProcessed=" + linksProcessed + " open paths: " + openSet.getSize() + "): " + errorMessage );
|
||||
}
|
||||
|
||||
|
||||
public void doSearch()
|
||||
{
|
||||
try
|
||||
|
@ -280,20 +287,17 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
catch( IllegalArgumentException e)
|
||||
{
|
||||
errorMessage = e.getMessage();
|
||||
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
logException( e );
|
||||
}
|
||||
catch( Exception e)
|
||||
{
|
||||
errorMessage = e instanceof IllegalArgumentException ? e.getMessage() : e.toString();
|
||||
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
logException( e );
|
||||
logThrowable( e );
|
||||
}
|
||||
catch( Error e)
|
||||
{
|
||||
cleanOnOOM();
|
||||
errorMessage = e.toString();
|
||||
logInfo( "Error (linksProcessed=" + linksProcessed + ": " + errorMessage );
|
||||
logException( e );
|
||||
logThrowable( e );
|
||||
}
|
||||
finally
|
||||
|
@ -404,7 +408,7 @@ public class RoutingEngine extends Thread
|
|||
// geometric position matching finding the nearest routable way-section
|
||||
private void matchWaypointsToNodes( List<MatchedWaypoint> unmatchedWaypoints )
|
||||
{
|
||||
resetCache();
|
||||
resetCache( false );
|
||||
nodesCache.waypointMatcher = new WaypointMatcherImpl( unmatchedWaypoints, 250. );
|
||||
for( MatchedWaypoint mwp : unmatchedWaypoints )
|
||||
{
|
||||
|
@ -446,9 +450,9 @@ public class RoutingEngine extends Thread
|
|||
// expand hollow link targets and resolve reverse links
|
||||
private void expandHollowLinkTargets( OsmNode n )
|
||||
{
|
||||
for( OsmLink link = n.firstlink; link != null; link = link.next )
|
||||
for( OsmLink link = n.firstlink; link != null; link = link.getNext( n ) )
|
||||
{
|
||||
nodesCache.obtainNonHollowNode( link.targetNode );
|
||||
nodesCache.obtainNonHollowNode( link.getTarget( n ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,7 +571,7 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
|
||||
|
||||
private void resetCache()
|
||||
private void resetCache( boolean detailed )
|
||||
{
|
||||
if ( hasInfo() && nodesCache != null )
|
||||
{
|
||||
|
@ -575,9 +579,9 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
nodesMap = new OsmNodesMap();
|
||||
|
||||
long maxmem = routingContext.memoryclass * 131072L; // 1/4 of total
|
||||
long maxmem = routingContext.memoryclass * 131072L; // 1/8 of total
|
||||
|
||||
nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay, routingContext.forceSecondaryData, maxmem, nodesCache );
|
||||
nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay, routingContext.forceSecondaryData, maxmem, nodesCache, detailed );
|
||||
}
|
||||
|
||||
private OsmNode getStartNode( long startId )
|
||||
|
@ -645,21 +649,20 @@ public class RoutingEngine extends Thread
|
|||
routingContext.setWaypoint( wp, false );
|
||||
OsmPath bestPath = null;
|
||||
OsmLink bestLink = null;
|
||||
OsmLink startLink = new OsmLink();
|
||||
startLink.targetNode = n1;
|
||||
OsmLink startLink = new OsmLink( null, n1 );
|
||||
OsmPath startPath = new OsmPath( startLink );
|
||||
startLink.addLinkHolder( startPath );
|
||||
startLink.addLinkHolder( startPath, null );
|
||||
double minradius = 1e10;
|
||||
for( OsmLink link = n1.firstlink; link != null; link = link.next )
|
||||
for( OsmLink link = n1.firstlink; link != null; link = link.getNext( n1 ) )
|
||||
{
|
||||
OsmNode nextNode = link.targetNode;
|
||||
OsmNode nextNode = link.getTarget( n1 );
|
||||
if ( nextNode.isHollow() ) continue; // border node?
|
||||
if ( nextNode.firstlink == null ) continue; // don't care about dead ends
|
||||
if ( nextNode == n1 ) continue; // ?
|
||||
if ( nextNode != n2 ) continue; // just that link
|
||||
|
||||
wp.radius = 1e9;
|
||||
OsmPath testPath = new OsmPath( null, startPath, link, null, guideTrack != null, routingContext );
|
||||
OsmPath testPath = new OsmPath( startPath, link, null, guideTrack != null, routingContext );
|
||||
testPath.airdistance = endPos == null ? 0 : nextNode.calcDistance( endPos );
|
||||
if ( wp.radius < minradius )
|
||||
{
|
||||
|
@ -670,7 +673,7 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
if ( bestLink != null )
|
||||
{
|
||||
bestLink.addLinkHolder( bestPath );
|
||||
bestLink.addLinkHolder( bestPath, n1 );
|
||||
}
|
||||
bestPath.treedepth = 1;
|
||||
|
||||
|
@ -687,14 +690,13 @@ public class RoutingEngine extends Thread
|
|||
try
|
||||
{
|
||||
if ( wp != null ) routingContext.setWaypoint( wp, true );
|
||||
OsmLink startLink = new OsmLink();
|
||||
startLink.targetNode = n1;
|
||||
OsmLink startLink = new OsmLink( null, n1 );
|
||||
OsmPath startPath = new OsmPath( startLink );
|
||||
startLink.addLinkHolder( startPath );
|
||||
startLink.addLinkHolder( startPath, null );
|
||||
|
||||
if ( wp != null ) wp.radius = 1e-5;
|
||||
|
||||
return new OsmPath( n1, startPath, link, null, guideTrack != null, routingContext );
|
||||
return new OsmPath( startPath, link, null, guideTrack != null, routingContext );
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -706,7 +708,8 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
try
|
||||
{
|
||||
resetCache();
|
||||
boolean detailed = guideTrack != null;
|
||||
resetCache( detailed );
|
||||
return _findTrack( operationName, startWp, endWp, costCuttingTrack, refTrack, fastPartialRecalc );
|
||||
}
|
||||
finally
|
||||
|
@ -742,11 +745,11 @@ public class RoutingEngine extends Thread
|
|||
OsmNode start1 = getStartNode( startNodeId1 );
|
||||
if ( start1 == null ) return null;
|
||||
OsmNode start2 = null;
|
||||
for( OsmLink link = start1.firstlink; link != null; link = link.next )
|
||||
for( OsmLink link = start1.firstlink; link != null; link = link.getNext( start1 ) )
|
||||
{
|
||||
if ( link.targetNode.getIdFromPos() == startNodeId2 )
|
||||
if ( link.getTarget( start1 ).getIdFromPos() == startNodeId2 )
|
||||
{
|
||||
start2 = link.targetNode;
|
||||
start2 = link.getTarget( start1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -826,8 +829,8 @@ public class RoutingEngine extends Thread
|
|||
linksProcessed++;
|
||||
|
||||
OsmLink currentLink = path.getLink();
|
||||
OsmNode currentNode = currentLink.targetNode;
|
||||
OsmNode sourceNode = path.getSourceNode();
|
||||
OsmNode currentNode = path.getTargetNode();
|
||||
|
||||
long currentNodeId = currentNode.getIdFromPos();
|
||||
if ( sourceNode != null )
|
||||
|
@ -872,6 +875,21 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
|
||||
OsmLinkHolder firstLinkHolder = currentLink.getFirstLinkHolder( sourceNode );
|
||||
for( OsmLinkHolder linkHolder = firstLinkHolder; linkHolder != null; linkHolder = linkHolder.getNextForLink() )
|
||||
{
|
||||
((OsmPath)linkHolder).airdistance = -1; // invalidate the entry in the open set;
|
||||
}
|
||||
|
||||
boolean isBidir = currentLink.isBidirectional();
|
||||
sourceNode.unlinkLink ( currentLink );
|
||||
|
||||
// if the counterlink is alive and does not yet have a path, remove it
|
||||
if ( isBidir && currentLink.getFirstLinkHolder( currentNode ) == null )
|
||||
{
|
||||
currentNode.unlinkLink(currentLink);
|
||||
}
|
||||
|
||||
// recheck cutoff before doing expensive stuff
|
||||
if ( path.cost + path.airdistance > maxTotalCost + 10 )
|
||||
{
|
||||
|
@ -879,19 +897,11 @@ public class RoutingEngine extends Thread
|
|||
continue;
|
||||
}
|
||||
|
||||
expandHollowLinkTargets( currentNode );
|
||||
|
||||
if ( sourceNode != null )
|
||||
for( OsmLink link = currentNode.firstlink; link != null; link = link.getNext( currentNode) )
|
||||
{
|
||||
sourceNode.unlinkLink ( currentLink );
|
||||
}
|
||||
OsmNode nextNode = link.getTarget( currentNode );
|
||||
|
||||
OsmLink counterLink = null;
|
||||
for( OsmLink link = currentNode.firstlink; link != null; link = link.next )
|
||||
{
|
||||
OsmNode nextNode = link.targetNode;
|
||||
|
||||
if ( nextNode.isHollow() )
|
||||
if ( ! nodesCache.obtainNonHollowNode( nextNode ) )
|
||||
{
|
||||
continue; // border node?
|
||||
}
|
||||
|
@ -901,7 +911,6 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
if ( nextNode == sourceNode )
|
||||
{
|
||||
counterLink = link;
|
||||
continue; // border node?
|
||||
}
|
||||
|
||||
|
@ -919,7 +928,7 @@ public class RoutingEngine extends Thread
|
|||
// not along the guide-track, discard, but register for voice-hint processing
|
||||
if ( routingContext.turnInstructionMode > 0 )
|
||||
{
|
||||
OsmPath detour = new OsmPath( currentNode, path, link, refTrack, true, routingContext );
|
||||
OsmPath detour = new OsmPath( path, link, refTrack, true, routingContext );
|
||||
if ( detour.cost >= 0. && nextId != startNodeId1 && nextId != startNodeId2 )
|
||||
{
|
||||
guideTrack.registerDetourForId( currentNode.getIdFromPos(), OsmPathElement.create( detour, false ) );
|
||||
|
@ -932,7 +941,7 @@ public class RoutingEngine extends Thread
|
|||
OsmPath bestPath = null;
|
||||
|
||||
boolean isFinalLink = false;
|
||||
long targetNodeId = link.targetNode.getIdFromPos();
|
||||
long targetNodeId = nextNode.getIdFromPos();
|
||||
if ( currentNodeId == endNodeId1 || currentNodeId == endNodeId2 )
|
||||
{
|
||||
if ( targetNodeId == endNodeId1 || targetNodeId == endNodeId2 )
|
||||
|
@ -941,7 +950,7 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
|
||||
for( OsmLinkHolder linkHolder = currentLink.firstlinkholder; linkHolder != null; linkHolder = linkHolder.getNextForLink() )
|
||||
for( OsmLinkHolder linkHolder = firstLinkHolder; linkHolder != null; linkHolder = linkHolder.getNextForLink() )
|
||||
{
|
||||
OsmPath otherPath = (OsmPath)linkHolder;
|
||||
try
|
||||
|
@ -951,7 +960,7 @@ public class RoutingEngine extends Thread
|
|||
endPos.radius = 1e-5;
|
||||
routingContext.setWaypoint( endPos, true );
|
||||
}
|
||||
OsmPath testPath = new OsmPath( currentNode, otherPath, link, refTrack, guideTrack != null, routingContext );
|
||||
OsmPath testPath = new OsmPath( otherPath, link, refTrack, guideTrack != null, routingContext );
|
||||
if ( testPath.cost >= 0 && ( bestPath == null || testPath.cost < bestPath.cost ) )
|
||||
{
|
||||
bestPath = testPath;
|
||||
|
@ -961,10 +970,6 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
routingContext.unsetWaypoint();
|
||||
}
|
||||
if ( otherPath != path )
|
||||
{
|
||||
otherPath.airdistance = -1; // invalidate the entry in the open set
|
||||
}
|
||||
}
|
||||
if ( bestPath != null )
|
||||
{
|
||||
|
@ -977,7 +982,7 @@ public class RoutingEngine extends Thread
|
|||
if ( inRadius && ( isFinalLink || bestPath.cost + bestPath.airdistance <= maxTotalCost + 10 ) )
|
||||
{
|
||||
// add only if this may beat an existing path for that link
|
||||
OsmLinkHolder dominator = link.firstlinkholder;
|
||||
OsmLinkHolder dominator = link.getFirstLinkHolder( currentNode );
|
||||
while( !trafficSim && dominator != null )
|
||||
{
|
||||
if ( bestPath.definitlyWorseThan( (OsmPath)dominator, routingContext ) )
|
||||
|
@ -995,7 +1000,7 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
|
||||
bestPath.treedepth = path.treedepth + 1;
|
||||
link.addLinkHolder( bestPath );
|
||||
link.addLinkHolder( bestPath, currentNode );
|
||||
synchronized( openSet )
|
||||
{
|
||||
addToOpenset( bestPath );
|
||||
|
@ -1004,11 +1009,7 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
}
|
||||
// if the counterlink does not yet have a path, remove it
|
||||
if ( counterLink != null && counterLink.firstlinkholder == null )
|
||||
{
|
||||
currentNode.unlinkLink(counterLink);
|
||||
}
|
||||
|
||||
path.unregisterUpTree( routingContext );
|
||||
}
|
||||
return null;
|
||||
|
@ -1023,22 +1024,6 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
}
|
||||
|
||||
private int preloadRing( OsmNode n, int ring )
|
||||
{
|
||||
int d = 12500;
|
||||
int c = 0;
|
||||
for( int idxLat=-ring; idxLat<=ring; idxLat++ )
|
||||
for( int idxLon=-ring; idxLon<=ring; idxLon++ )
|
||||
{
|
||||
int absLat = idxLat < 0 ? -idxLat : idxLat;
|
||||
int absLon = idxLon < 0 ? -idxLon : idxLon;
|
||||
int max = absLat > absLon ? absLat : absLon;
|
||||
if ( max < ring ) continue;
|
||||
c += nodesCache.loadSegmentFor( n.ilon + d*idxLon , n.ilat +d*idxLat );
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private OsmTrack compileTrack( OsmPath path, boolean verbose )
|
||||
{
|
||||
OsmPathElement element = OsmPathElement.create( path, false );
|
||||
|
@ -1137,8 +1122,21 @@ public class RoutingEngine extends Thread
|
|||
return track;
|
||||
}
|
||||
|
||||
public int getPathPeak()
|
||||
{
|
||||
synchronized( openSet )
|
||||
{
|
||||
return openSet.getPeakSize();
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getOpenSet()
|
||||
{
|
||||
if ( extract == null )
|
||||
{
|
||||
extract = new Object[500];
|
||||
}
|
||||
|
||||
synchronized( openSet )
|
||||
{
|
||||
if ( guideTrack != null )
|
||||
|
@ -1154,14 +1152,15 @@ public class RoutingEngine extends Thread
|
|||
return res;
|
||||
}
|
||||
|
||||
List<OsmPath> extract = openSet.getExtract();
|
||||
int[] res = new int[extract.size() * 2];
|
||||
int i = 0;
|
||||
for( OsmPath p : extract )
|
||||
int size = openSet.getExtract(extract);
|
||||
int[] res = new int[size * 2];
|
||||
for( int i=0, j=0; i<size; i++ )
|
||||
{
|
||||
OsmNode n = p.getLink().targetNode;
|
||||
res[i++] = n.ilon;
|
||||
res[i++] = n.ilat;
|
||||
OsmPath p = (OsmPath)extract[i];
|
||||
extract[i] = null;
|
||||
OsmNode n = p.getTargetNode();
|
||||
res[j++] = n.ilon;
|
||||
res[j++] = n.ilat;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-expressions</artifactId>
|
||||
|
|
|
@ -8,10 +8,10 @@ package btools.expressions;
|
|||
|
||||
import btools.codec.TagValueValidator;
|
||||
|
||||
|
||||
|
||||
public final class BExpressionContextWay extends BExpressionContext implements TagValueValidator
|
||||
{
|
||||
private boolean decodeForbidden = true;
|
||||
|
||||
private static String[] buildInVariables =
|
||||
{ "costfactor", "turncost", "uphillcostfactor", "downhillcostfactor", "initialcost", "nodeaccessgranted", "initialclassifier", "trafficsourcedensity", "istrafficbackbone", "priorityclassifier", "classifiermask" };
|
||||
|
||||
|
@ -61,6 +61,12 @@ public final class BExpressionContextWay extends BExpressionContext implements T
|
|||
minCostFactor = reverseCostFactor;
|
||||
}
|
||||
}
|
||||
return minCostFactor < 9999.f ? 2 : minCostFactor < 10000.f ? 1 : 0;
|
||||
return minCostFactor < 9999.f ? 2 : decodeForbidden ? (minCostFactor < 10000.f ? 1 : 0) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDecodeForbidden( boolean decodeForbidden )
|
||||
{
|
||||
this.decodeForbidden= decodeForbidden;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-map-creator</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-mapaccess</artifactId>
|
||||
|
|
|
@ -38,6 +38,7 @@ public final class NodesCache
|
|||
|
||||
private long cacheSum = 0;
|
||||
private long maxmem;
|
||||
private boolean detailed;
|
||||
|
||||
private boolean garbageCollectionEnabled = false;
|
||||
private boolean ghostCleaningDone = false;
|
||||
|
@ -52,7 +53,7 @@ public final class NodesCache
|
|||
return "collecting=" + garbageCollectionEnabled + " noGhosts=" + ghostCleaningDone + " cacheSum=" + cacheSum + " cacheSumClean=" + cacheSumClean + " ghostSum=" + ghostSum + " ghostWakeup=" + ghostWakeup ;
|
||||
}
|
||||
|
||||
public NodesCache( String segmentDir, OsmNodesMap nodesMap, BExpressionContextWay ctxWay, boolean forceSecondaryData, long maxmem, NodesCache oldCache )
|
||||
public NodesCache( String segmentDir, OsmNodesMap nodesMap, BExpressionContextWay ctxWay, boolean forceSecondaryData, long maxmem, NodesCache oldCache, boolean detailed )
|
||||
{
|
||||
this.segmentDir = new File( segmentDir );
|
||||
this.nodesMap = nodesMap;
|
||||
|
@ -61,6 +62,12 @@ public final class NodesCache
|
|||
this.lookupMinorVersion = ctxWay.meta.lookupMinorVersion;
|
||||
this.forceSecondaryData = forceSecondaryData;
|
||||
this.maxmem = maxmem;
|
||||
this.detailed = detailed;
|
||||
|
||||
if ( ctxWay != null )
|
||||
{
|
||||
ctxWay.setDecodeForbidden( detailed );
|
||||
}
|
||||
|
||||
first_file_access_failed = false;
|
||||
first_file_access_name = null;
|
||||
|
@ -74,7 +81,9 @@ public final class NodesCache
|
|||
dataBuffers = oldCache.dataBuffers;
|
||||
secondarySegmentsDir = oldCache.secondarySegmentsDir;
|
||||
|
||||
// re-use old, virgin caches
|
||||
// re-use old, virgin caches (if same detail-mode)
|
||||
if ( oldCache.detailed == detailed)
|
||||
{
|
||||
fileRows = oldCache.fileRows;
|
||||
for ( OsmFile[] fileRow : fileRows )
|
||||
{
|
||||
|
@ -87,6 +96,11 @@ public final class NodesCache
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileRows = new OsmFile[180][];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileCache = new HashMap<String, PhysicalFile>( 4 );
|
||||
fileRows = new OsmFile[180][];
|
||||
|
@ -113,7 +127,7 @@ public final class NodesCache
|
|||
// clean all ghosts and enable garbage collection
|
||||
private void checkEnableCacheCleaning()
|
||||
{
|
||||
if ( cacheSum < maxmem || ghostCleaningDone )
|
||||
if ( cacheSum < maxmem )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -127,7 +141,7 @@ public final class NodesCache
|
|||
}
|
||||
for ( OsmFile osmf : fileRow )
|
||||
{
|
||||
if ( garbageCollectionEnabled )
|
||||
if ( garbageCollectionEnabled && !ghostCleaningDone )
|
||||
{
|
||||
cacheSum -= osmf.cleanGhosts();
|
||||
}
|
||||
|
@ -141,6 +155,7 @@ public final class NodesCache
|
|||
if ( garbageCollectionEnabled )
|
||||
{
|
||||
ghostCleaningDone = true;
|
||||
maxmem *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -10,36 +10,168 @@ package btools.mapaccess;
|
|||
public class OsmLink
|
||||
{
|
||||
/**
|
||||
* The description bitmap is mainly the way description
|
||||
* used to calculate the costfactor
|
||||
* The description bitmap contains the waytags (valid for both directions)
|
||||
*/
|
||||
public byte[] descriptionBitmap;
|
||||
|
||||
public OsmNode targetNode;
|
||||
|
||||
public OsmLink next;
|
||||
|
||||
public OsmLinkHolder firstlinkholder = null;
|
||||
|
||||
/**
|
||||
* The geometry contains intermediate nodes, null for none (valid for both directions)
|
||||
*/
|
||||
public byte[] geometry;
|
||||
|
||||
public boolean counterLinkWritten;
|
||||
// a link logically knows only its target, but for the reverse link, source and target are swapped
|
||||
protected OsmNode n1;
|
||||
protected OsmNode n2;
|
||||
|
||||
public byte state;
|
||||
// same for the next-link-for-node pointer: previous applies to the reverse link
|
||||
protected OsmLink previous;
|
||||
protected OsmLink next;
|
||||
|
||||
public void setGeometry( byte[] geometry )
|
||||
private OsmLinkHolder reverselinkholder = null;
|
||||
private OsmLinkHolder firstlinkholder = null;
|
||||
|
||||
protected OsmLink()
|
||||
{
|
||||
this.geometry = geometry;
|
||||
}
|
||||
|
||||
final public void addLinkHolder( OsmLinkHolder holder )
|
||||
public OsmLink( OsmNode source, OsmNode target )
|
||||
{
|
||||
n1 = source;
|
||||
n2 = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant target-node for the given source
|
||||
*/
|
||||
public final OsmNode getTarget( OsmNode source )
|
||||
{
|
||||
return n2 != source && n2 != null ? n2 : n1;
|
||||
/* if ( n2 != null && n2 != source )
|
||||
{
|
||||
return n2;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
return n1;
|
||||
}
|
||||
else
|
||||
{
|
||||
new Throwable( "ups" ).printStackTrace();
|
||||
throw new IllegalArgumentException( "internal error: getTarget: unknown source; " + source + " n1=" + n1 + " n2=" + n2 );
|
||||
} */
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant next-pointer for the given source
|
||||
*/
|
||||
public final OsmLink getNext( OsmNode source )
|
||||
{
|
||||
return n2 != source && n2 != null ? next : previous;
|
||||
/* if ( n2 != null && n2 != source )
|
||||
{
|
||||
return next;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
return previous;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: gextNext: unknown source" );
|
||||
} */
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this link for the given direction
|
||||
*/
|
||||
protected final OsmLink clear( OsmNode source )
|
||||
{
|
||||
OsmLink n;
|
||||
if ( n2 != null && n2 != source )
|
||||
{
|
||||
n = next;
|
||||
next = null;
|
||||
n2 = null;
|
||||
firstlinkholder = null;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
n = previous;
|
||||
previous = null;
|
||||
n1 = null;
|
||||
reverselinkholder = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: setNext: unknown source" );
|
||||
}
|
||||
if ( n1 == null && n2 == null )
|
||||
{
|
||||
descriptionBitmap = null;
|
||||
geometry = null;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public final void setFirstLinkHolder( OsmLinkHolder holder, OsmNode source )
|
||||
{
|
||||
if ( n2 != null && n2 != source )
|
||||
{
|
||||
if ( firstlinkholder != null ) { holder.setNextForLink( firstlinkholder ); }
|
||||
firstlinkholder = holder;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
return "Link(target=" + targetNode.getIdFromPos() + " counterLinkWritten=" + counterLinkWritten + " state=" + state + ")";
|
||||
reverselinkholder = holder;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: setFirstLinkHolder: unknown source" );
|
||||
}
|
||||
}
|
||||
|
||||
public final OsmLinkHolder getFirstLinkHolder( OsmNode source )
|
||||
{
|
||||
if ( n2 != null && n2 != source )
|
||||
{
|
||||
return firstlinkholder;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
return reverselinkholder;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: getFirstLinkHolder: unknown source" );
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean isReverse( OsmNode source )
|
||||
{
|
||||
return n1 != source && n1 != null;
|
||||
/* if ( n2 != null && n2 != source )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: isReverse: unknown source" );
|
||||
} */
|
||||
}
|
||||
|
||||
public final boolean isBidirectional()
|
||||
{
|
||||
return n1 != null && n2 != null;
|
||||
}
|
||||
|
||||
public final void addLinkHolder( OsmLinkHolder holder, OsmNode source )
|
||||
{
|
||||
OsmLinkHolder firstHolder = getFirstLinkHolder( source );
|
||||
if ( firstHolder != null ) { holder.setNextForLink( firstHolder ); }
|
||||
setFirstLinkHolder( holder, source );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,8 +11,33 @@ import btools.expressions.BExpressionContextWay;
|
|||
import btools.util.ByteArrayUnifier;
|
||||
import btools.util.IByteArrayUnifier;
|
||||
|
||||
public class OsmNode implements OsmPos
|
||||
public class OsmNode extends OsmLink implements OsmPos
|
||||
{
|
||||
/**
|
||||
* The latitude
|
||||
*/
|
||||
public int ilat;
|
||||
|
||||
/**
|
||||
* The longitude
|
||||
*/
|
||||
public int ilon;
|
||||
|
||||
/**
|
||||
* The elevation
|
||||
*/
|
||||
public short selev;
|
||||
|
||||
/**
|
||||
* The node-tags, if any
|
||||
*/
|
||||
public byte[] nodeDescription;
|
||||
|
||||
/**
|
||||
* The links to other nodes
|
||||
*/
|
||||
public OsmLink firstlink = null;
|
||||
|
||||
public OsmNode()
|
||||
{
|
||||
}
|
||||
|
@ -29,22 +54,6 @@ public class OsmNode implements OsmPos
|
|||
ilat = (int) ( id & 0xffffffff );
|
||||
}
|
||||
|
||||
/**
|
||||
* The latitude
|
||||
*/
|
||||
public int ilat;
|
||||
|
||||
/**
|
||||
* The longitude
|
||||
*/
|
||||
public int ilon;
|
||||
|
||||
/**
|
||||
* The elevation
|
||||
*/
|
||||
public short selev;
|
||||
|
||||
public byte[] nodeDescription;
|
||||
|
||||
// interface OsmPos
|
||||
public final int getILat()
|
||||
|
@ -67,58 +76,28 @@ public class OsmNode implements OsmPos
|
|||
return selev / 4.;
|
||||
}
|
||||
|
||||
/**
|
||||
* The links to other nodes
|
||||
*/
|
||||
public OsmLink firstlink = null;
|
||||
|
||||
// preliminry in forward order to avoid regressions
|
||||
public final void addLink( OsmLink link )
|
||||
private void addLink( OsmLink link, boolean isReverse, OsmNode tn )
|
||||
{
|
||||
if ( firstlink == null )
|
||||
if ( isReverse )
|
||||
{
|
||||
link.n1 = tn;
|
||||
link.n2 = this;
|
||||
link.next = tn.firstlink;
|
||||
link.previous = firstlink;
|
||||
tn.firstlink = link;
|
||||
firstlink = link;
|
||||
}
|
||||
else
|
||||
{
|
||||
OsmLink l = firstlink;
|
||||
while (l.next != null)
|
||||
l = l.next;
|
||||
l.next = link;
|
||||
link.n1 = this;
|
||||
link.n2 = tn;
|
||||
link.next = firstlink;
|
||||
link.previous = tn.firstlink;
|
||||
tn.firstlink = link;
|
||||
firstlink = link;
|
||||
}
|
||||
}
|
||||
|
||||
private OsmLink getCompatibleLink( int ilon, int ilat, boolean counterLinkWritten, int state )
|
||||
{
|
||||
for ( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( counterLinkWritten == l.counterLinkWritten && l.state == state )
|
||||
{
|
||||
OsmNode t = l.targetNode;
|
||||
if ( t.ilon == ilon && t.ilat == ilat )
|
||||
{
|
||||
l.state = 0;
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
// second try ignoring counterLinkWritten
|
||||
// (border links are written in both directions)
|
||||
for ( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( l.state == state )
|
||||
{
|
||||
OsmNode t = l.targetNode;
|
||||
if ( t.ilon == ilon && t.ilat == ilat )
|
||||
{
|
||||
l.state = 0;
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public final int calcDistance( OsmPos p )
|
||||
{
|
||||
double l = ( ilat - 90000000 ) * 0.00000001234134;
|
||||
|
@ -155,6 +134,8 @@ public class OsmNode implements OsmPos
|
|||
int nodeDescSize = mc.readVarLengthUnsigned();
|
||||
nodeDescription = nodeDescSize == 0 ? null : mc.readUnified( nodeDescSize, abUnifier );
|
||||
|
||||
OsmLink link0 = firstlink;
|
||||
|
||||
while (mc.hasMoreData())
|
||||
{
|
||||
// read link data
|
||||
|
@ -176,47 +157,42 @@ public class OsmNode implements OsmPos
|
|||
continue; // skip self-ref
|
||||
}
|
||||
|
||||
// first check the known links for that target
|
||||
OsmLink link = getCompatibleLink( linklon, linklat, isReverse, 2 );
|
||||
if ( link == null ) // .. not found, then check the hollow nodes
|
||||
OsmNode tn = null; // find the target node
|
||||
OsmLink link = null;
|
||||
|
||||
// ...in our known links
|
||||
for ( OsmLink l = link0; l != null; l = l.getNext( this ) )
|
||||
{
|
||||
OsmNode tn = hollowNodes.get( linklon, linklat ); // target node
|
||||
OsmNode t = l.getTarget( this );
|
||||
if ( t.ilon == linklon && t.ilat == linklat )
|
||||
{
|
||||
tn = t;
|
||||
if ( isReverse || ( l.descriptionBitmap == null && !l.isReverse( this ) ) )
|
||||
{
|
||||
link = l; // the correct one that needs our data
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( tn == null ) // .. not found, then check the hollow nodes
|
||||
{
|
||||
tn = hollowNodes.get( linklon, linklat ); // target node
|
||||
if ( tn == null ) // node not yet known, create a new hollow proxy
|
||||
{
|
||||
tn = new OsmNode( linklon, linklat );
|
||||
tn.setHollow();
|
||||
hollowNodes.put( tn );
|
||||
addLink( link = tn, isReverse, tn ); // technical inheritance: link instance in node
|
||||
}
|
||||
link = new OsmLink();
|
||||
link.targetNode = tn;
|
||||
link.counterLinkWritten = isReverse;
|
||||
link.state = 1;
|
||||
addLink( link );
|
||||
}
|
||||
|
||||
// now we have a link with a target node -> get the reverse link
|
||||
OsmLink rlink = link.targetNode.getCompatibleLink( ilon, ilat, !isReverse, 1 );
|
||||
if ( rlink == null ) // .. not found, create it
|
||||
if ( link == null )
|
||||
{
|
||||
rlink = new OsmLink();
|
||||
rlink.targetNode = this;
|
||||
rlink.counterLinkWritten = !isReverse;
|
||||
rlink.state = 2;
|
||||
link.targetNode.addLink( rlink );
|
||||
addLink( link = new OsmLink(), isReverse, tn );
|
||||
}
|
||||
|
||||
if ( !isReverse )
|
||||
{
|
||||
// we have the data for that link, so fill both the link ..
|
||||
link.descriptionBitmap = description;
|
||||
link.setGeometry( geometry );
|
||||
|
||||
// .. and the reverse
|
||||
if ( rlink.counterLinkWritten )
|
||||
{
|
||||
rlink.descriptionBitmap = description;
|
||||
rlink.setGeometry( geometry );
|
||||
}
|
||||
link.geometry = geometry;
|
||||
}
|
||||
}
|
||||
hollowNodes.remove( this );
|
||||
|
@ -240,20 +216,40 @@ public class OsmNode implements OsmPos
|
|||
|
||||
public final void unlinkLink( OsmLink link )
|
||||
{
|
||||
OsmLink n = link.clear( this );
|
||||
|
||||
if ( link == firstlink )
|
||||
{
|
||||
firstlink = link.next;
|
||||
firstlink = n;
|
||||
return;
|
||||
}
|
||||
for ( OsmLink l = firstlink; l != null; l = l.next )
|
||||
OsmLink l = firstlink;
|
||||
while( l != null )
|
||||
{
|
||||
if ( l.next == link )
|
||||
// if ( l.isReverse( this ) )
|
||||
if ( l.n1 != this && l.n1 != null ) // isReverse inline
|
||||
{
|
||||
l.next = link.next;
|
||||
OsmLink nl = l.previous;
|
||||
if ( nl == link )
|
||||
{
|
||||
l.previous = n;
|
||||
return;
|
||||
}
|
||||
l = nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
OsmLink nl = l.next;
|
||||
if ( nl == link )
|
||||
{
|
||||
l.next = n;
|
||||
return;
|
||||
}
|
||||
l = nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean equals( Object o )
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-mem-router</artifactId>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="15"
|
||||
android:versionName="1.4.4" package="btools.routingapp">
|
||||
android:versionCode="17"
|
||||
android:versionName="1.4.6" package="btools.routingapp">
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name">
|
||||
<activity android:name=".BRouterActivity"
|
||||
android:label="@string/app_name"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-routing-app</artifactId>
|
||||
|
|
|
@ -766,7 +766,8 @@ public class BRouterView extends View
|
|||
}
|
||||
else
|
||||
{
|
||||
String result = "version = BRouter-1.4.4\n" + "memory-class = " + memoryClass + "\ndistance = " + cr.getDistance() / 1000. + " km\n" + "filtered ascend = " + cr.getAscend()
|
||||
String memstat = memoryClass + "mb pathPeak " + ((cr.getPathPeak()+500)/1000) + "k";
|
||||
String result = "version = BRouter-1.4.6\n" + "mem = " + memstat + "\ndistance = " + cr.getDistance() / 1000. + " km\n" + "filtered ascend = " + cr.getAscend()
|
||||
+ " m\n" + "plain ascend = " + cr.getPlainAscend();
|
||||
|
||||
rawTrack = cr.getFoundRawTrack();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-server</artifactId>
|
||||
|
|
|
@ -88,7 +88,7 @@ public class BRouter
|
|||
}
|
||||
System.exit(0);
|
||||
}
|
||||
System.out.println("BRouter 1.4.4 / 29082016 / abrensch");
|
||||
System.out.println("BRouter 1.4.6 / 30092016 / abrensch");
|
||||
if ( args.length < 6 )
|
||||
{
|
||||
System.out.println("Find routes in an OSM map");
|
||||
|
@ -155,6 +155,7 @@ public class BRouter
|
|||
c.setAlternativeIdx( Integer.parseInt( args[6] ) );
|
||||
}
|
||||
}
|
||||
c.memoryclass = (int) ( Runtime.getRuntime().maxMemory() / 1024 / 1024 );
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ public class RouteServer extends Thread
|
|||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
System.out.println("BRouter 1.4.4 / 29082016");
|
||||
System.out.println("BRouter 1.4.6 / 30092016");
|
||||
if ( args.length != 5 )
|
||||
{
|
||||
System.out.println("serve BRouter protocol");
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-util</artifactId>
|
||||
|
|
|
@ -1,30 +1,19 @@
|
|||
package btools.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Memory efficient Heap to get the lowest-key value of a set of key-object pairs
|
||||
* Memory efficient and lightning fast heap to get the lowest-key value of a set of key-object pairs
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public final class SortedHeap<V>
|
||||
{
|
||||
private int[][] al;
|
||||
private int[] lv; // low values
|
||||
|
||||
private int[] nextNonEmpty;
|
||||
private int firstNonEmpty;
|
||||
|
||||
private int[] lp; // the low pointers
|
||||
|
||||
private Object[][] vla; // value list array
|
||||
|
||||
protected static final int MAXLISTS = 28; // enough for size = ca Integer.MAX_VALUE
|
||||
|
||||
private int size;
|
||||
private boolean isClear = false;
|
||||
private int peaksize;
|
||||
private SortedBin first;
|
||||
private SortedBin second;
|
||||
private SortedBin firstNonEmpty;
|
||||
|
||||
public SortedHeap()
|
||||
{
|
||||
|
@ -36,66 +25,111 @@ public final class SortedHeap<V>
|
|||
*/
|
||||
public V popLowestKeyValue()
|
||||
{
|
||||
int idx = firstNonEmpty;
|
||||
if ( idx < 0 )
|
||||
SortedBin bin = firstNonEmpty;
|
||||
if ( bin == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
size--;
|
||||
int minId = lv[idx];
|
||||
int minIdx = idx;
|
||||
for (;;)
|
||||
int minId = bin.lv;
|
||||
SortedBin minBin = bin;
|
||||
while( ( bin = bin.nextNonEmpty ) != null )
|
||||
{
|
||||
idx = nextNonEmpty[idx];
|
||||
if ( idx < 0 )
|
||||
if ( bin.lv < minId )
|
||||
{
|
||||
return dropLowest( minIdx );
|
||||
}
|
||||
if ( lv[idx] < minId )
|
||||
{
|
||||
minId = lv[idx];
|
||||
minIdx = idx;
|
||||
minId = bin.lv;
|
||||
minBin = bin;
|
||||
}
|
||||
}
|
||||
return (V) minBin.dropLowest();
|
||||
}
|
||||
|
||||
private V dropLowest( int idx )
|
||||
private static final class SortedBin
|
||||
{
|
||||
int lp_old = lp[idx]++;
|
||||
int lp_new = lp_old+1;
|
||||
if ( lp_new == 4 << idx )
|
||||
SortedHeap parent;
|
||||
SortedBin next;
|
||||
SortedBin nextNonEmpty;
|
||||
int binsize;
|
||||
int[] al; // key array
|
||||
Object[] vla; // value array
|
||||
int lv; // low value
|
||||
int lp; // low pointer
|
||||
|
||||
SortedBin( int binsize, SortedHeap parent )
|
||||
{
|
||||
unlinkIdx( idx );
|
||||
this.binsize = binsize;
|
||||
this.parent = parent;
|
||||
al = new int[binsize];
|
||||
vla = new Object[binsize];
|
||||
lp = binsize;
|
||||
}
|
||||
|
||||
SortedBin next()
|
||||
{
|
||||
if ( next == null )
|
||||
{
|
||||
next = new SortedBin( binsize << 1, parent );
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
Object dropLowest()
|
||||
{
|
||||
int lpOld = lp;
|
||||
if ( ++lp == binsize )
|
||||
{
|
||||
unlink();
|
||||
}
|
||||
else
|
||||
{
|
||||
lv[idx] = al[idx][lp_new];
|
||||
lv = al[lp];
|
||||
}
|
||||
Object[] vlai = vla[idx];
|
||||
V res = (V) vlai[lp_old];
|
||||
vlai[lp_old] = null;
|
||||
Object res = vla[lpOld];
|
||||
vla[lpOld] = null;
|
||||
return res;
|
||||
}
|
||||
|
||||
private void unlinkIdx( int idx )
|
||||
void unlink()
|
||||
{
|
||||
if ( idx == firstNonEmpty )
|
||||
SortedBin neBin = parent.firstNonEmpty;
|
||||
if ( neBin == this )
|
||||
{
|
||||
firstNonEmpty = nextNonEmpty[idx];
|
||||
parent.firstNonEmpty = nextNonEmpty;
|
||||
return;
|
||||
}
|
||||
int i = firstNonEmpty;
|
||||
for(;;)
|
||||
{
|
||||
if ( nextNonEmpty[i] == idx )
|
||||
SortedBin next = neBin.nextNonEmpty;
|
||||
if ( next == this )
|
||||
{
|
||||
nextNonEmpty[i] = nextNonEmpty[idx];
|
||||
neBin.nextNonEmpty = nextNonEmpty;
|
||||
return;
|
||||
}
|
||||
i = nextNonEmpty[i];
|
||||
neBin = next;
|
||||
}
|
||||
}
|
||||
|
||||
void add( int key, Object value )
|
||||
{
|
||||
int p = lp;
|
||||
for(;;)
|
||||
{
|
||||
if ( p == binsize || key < al[p] )
|
||||
{
|
||||
al[p-1] = key;
|
||||
vla[p-1] = value;
|
||||
lv = al[--lp];
|
||||
return;
|
||||
}
|
||||
al[p-1] = al[p];
|
||||
vla[p-1] = vla[p];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* add a key value pair to the heap
|
||||
*
|
||||
|
@ -106,182 +140,139 @@ public final class SortedHeap<V>
|
|||
*/
|
||||
public void add( int key, V value )
|
||||
{
|
||||
isClear = false;
|
||||
size++;
|
||||
|
||||
if ( lp[0] == 0 )
|
||||
if ( first.lp == 0 && second.lp == 0) // both full ?
|
||||
{
|
||||
sortUp();
|
||||
}
|
||||
int lp0 = lp[0];
|
||||
if ( first.lp > 0 )
|
||||
{
|
||||
first.add( key, value );
|
||||
if ( firstNonEmpty != first )
|
||||
{
|
||||
first.nextNonEmpty = firstNonEmpty;
|
||||
firstNonEmpty = first;
|
||||
}
|
||||
}
|
||||
else // second bin not full
|
||||
{
|
||||
second.add( key, value );
|
||||
if ( first.nextNonEmpty != second )
|
||||
{
|
||||
second.nextNonEmpty = first.nextNonEmpty;
|
||||
first.nextNonEmpty = second;
|
||||
}
|
||||
}
|
||||
|
||||
int[] al0 = al[0];
|
||||
Object[] vla0 = vla[0];
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if ( lp0 == 4 || key < al0[lp0] )
|
||||
{
|
||||
al0[lp0-1] = key;
|
||||
vla0[lp0-1] = value;
|
||||
lv[0] = al0[--lp[0]];
|
||||
if ( firstNonEmpty != 0 )
|
||||
{
|
||||
nextNonEmpty[0] = firstNonEmpty;
|
||||
firstNonEmpty = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
al0[lp0-1] = al0[lp0];
|
||||
vla0[lp0-1] = vla0[lp0];
|
||||
lp0++;
|
||||
}
|
||||
}
|
||||
|
||||
private void sortUp()
|
||||
{
|
||||
// determine the first array big enough to take them all
|
||||
int cnt = 4; // value count up to idx
|
||||
int idx = 1;
|
||||
int n = 8;
|
||||
int nonEmptyCount = 1;
|
||||
|
||||
for ( ;; )
|
||||
if ( size > peaksize )
|
||||
{
|
||||
int nentries = n - lp[idx];
|
||||
peaksize = size;
|
||||
}
|
||||
|
||||
// determine the first array big enough to take them all
|
||||
int cnt = 8; // value count of first 2 bins is always 8
|
||||
SortedBin tbin = second; // target bin
|
||||
SortedBin lastNonEmpty = second;
|
||||
do
|
||||
{
|
||||
tbin = tbin.next();
|
||||
int nentries = tbin.binsize - tbin.lp;
|
||||
if ( nentries > 0 )
|
||||
{
|
||||
cnt += n - lp[idx];
|
||||
nonEmptyCount++;
|
||||
cnt += nentries;
|
||||
lastNonEmpty = tbin;
|
||||
}
|
||||
if ( cnt <= n )
|
||||
{
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
n <<= 1;
|
||||
}
|
||||
while( cnt > tbin.binsize );
|
||||
|
||||
// create, if not yet
|
||||
if ( al[idx] == null )
|
||||
{
|
||||
al[idx] = new int[n];
|
||||
vla[idx] = new Object[n];
|
||||
}
|
||||
int[] al_t = tbin.al;
|
||||
Object[] vla_t = tbin.vla;
|
||||
int tp = tbin.binsize-cnt; // target pointer
|
||||
|
||||
int[] al_t = al[idx];
|
||||
Object[] vla_t = vla[idx];
|
||||
int tp = n-cnt; // target pointer
|
||||
// unlink any higher, non-empty arrays
|
||||
SortedBin otherNonEmpty = lastNonEmpty.nextNonEmpty;
|
||||
lastNonEmpty.nextNonEmpty = null;
|
||||
|
||||
// now merge the contents of arrays 0...idx into idx
|
||||
while( nonEmptyCount > 1 )
|
||||
// now merge the content of these non-empty bins into the target bin
|
||||
while( firstNonEmpty != null )
|
||||
{
|
||||
int neIdx = firstNonEmpty;
|
||||
int minIdx = neIdx;
|
||||
int minId = lv[minIdx];
|
||||
SortedBin ne = firstNonEmpty;
|
||||
SortedBin minBin = ne;
|
||||
int minId = minBin.lv;
|
||||
|
||||
for ( int i = 1; i < nonEmptyCount; i++ )
|
||||
while ( ( ne = ne.nextNonEmpty ) != null )
|
||||
{
|
||||
neIdx = nextNonEmpty[neIdx];
|
||||
if ( lv[neIdx] < minId )
|
||||
if ( ne.lv < minId )
|
||||
{
|
||||
minIdx = neIdx;
|
||||
minId = lv[neIdx];
|
||||
minBin = ne;
|
||||
minId = minBin.lv;
|
||||
}
|
||||
}
|
||||
|
||||
// current minimum found, copy to target array
|
||||
al_t[tp] = minId;
|
||||
vla_t[tp++] = dropLowest( minIdx );
|
||||
|
||||
if ( lp[minIdx] == 4 << minIdx )
|
||||
{
|
||||
nonEmptyCount--;
|
||||
}
|
||||
vla_t[tp++] = minBin.dropLowest();
|
||||
}
|
||||
|
||||
// only one non-empty index left, so just copy the remaining entries
|
||||
if ( firstNonEmpty != idx ) // no self-copy needed
|
||||
{
|
||||
int[] al_s = al[firstNonEmpty];
|
||||
Object[] vla_s = vla[firstNonEmpty];
|
||||
int sp = lp[firstNonEmpty]; // source-pointer
|
||||
while( sp < 4 << firstNonEmpty )
|
||||
{
|
||||
al_t[tp] = al_s[sp];
|
||||
vla_t[tp++] = vla_s[sp];
|
||||
vla_s[sp++] = null;
|
||||
}
|
||||
lp[firstNonEmpty] = sp;
|
||||
}
|
||||
unlinkIdx( firstNonEmpty );
|
||||
lp[idx] = n-cnt; // new target low pointer
|
||||
lv[idx] = al[idx][lp[idx]];
|
||||
nextNonEmpty[idx] = firstNonEmpty;
|
||||
firstNonEmpty = idx;
|
||||
tp = tbin.binsize-cnt;
|
||||
tbin.lp = tp; // new target low pointer
|
||||
tbin.lv = tbin.al[tp];
|
||||
tbin.nextNonEmpty = otherNonEmpty;
|
||||
firstNonEmpty = tbin;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
if ( !isClear )
|
||||
{
|
||||
isClear = true;
|
||||
size = 0;
|
||||
first = new SortedBin( 4, this );
|
||||
second = new SortedBin( 4, this );
|
||||
firstNonEmpty = null;
|
||||
}
|
||||
|
||||
lp = new int[MAXLISTS];
|
||||
|
||||
// allocate key lists
|
||||
al = new int[MAXLISTS][];
|
||||
al[0] = new int[4]; // make the first array
|
||||
|
||||
// same for the values
|
||||
vla = new Object[MAXLISTS][];
|
||||
vla[0] = new Object[4];
|
||||
|
||||
lv = new int[MAXLISTS];
|
||||
nextNonEmpty = new int[MAXLISTS];
|
||||
|
||||
firstNonEmpty = -1;
|
||||
|
||||
int n = 4;
|
||||
for ( int idx = 0; idx < MAXLISTS; idx++ )
|
||||
public int getSize()
|
||||
{
|
||||
lp[idx] = n;
|
||||
n <<= 1;
|
||||
nextNonEmpty[idx] = -1; // no next
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public List<V> getExtract()
|
||||
public int getPeakSize()
|
||||
{
|
||||
int div = size / 1000 + 1;
|
||||
return peaksize;
|
||||
}
|
||||
|
||||
public int getExtract( Object[] targetArray )
|
||||
{
|
||||
int tsize = targetArray.length;
|
||||
int div = size / tsize + 1;
|
||||
int tp = 0;
|
||||
|
||||
ArrayList<V> res = new ArrayList<V>( size / div + 1 );
|
||||
int lpi = 0;
|
||||
for ( int i = 1;; i++ )
|
||||
SortedBin bin = firstNonEmpty;
|
||||
while( bin != null )
|
||||
{
|
||||
int[] ali = al[i];
|
||||
if ( ali == null )
|
||||
break;
|
||||
lpi += lp[i];
|
||||
Object[] vlai = vla[i];
|
||||
int n = 4 << i;
|
||||
lpi += bin.lp;
|
||||
Object[] vlai = bin.vla;
|
||||
int n = bin.binsize;
|
||||
while (lpi < n)
|
||||
{
|
||||
res.add( (V) vla[i][lpi] );
|
||||
targetArray[tp++] = vlai[lpi];
|
||||
lpi += div;
|
||||
}
|
||||
lpi -= n;
|
||||
bin = bin.nextNonEmpty;
|
||||
}
|
||||
return res;
|
||||
return tp;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
SortedHeap<String> sh = new SortedHeap<String>();
|
||||
Random rnd = new Random();
|
||||
for( int i = 0; i< 100; i++ )
|
||||
for( int i = 0; i< 1000; i++ )
|
||||
{
|
||||
int val = rnd.nextInt( 1000000 );
|
||||
sh.add( val, "" + val );
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<packaging>pom</packaging>
|
||||
<url>http://brouter.de/brouter/</url>
|
||||
<name>brouter</name>
|
||||
|
|
Loading…
Reference in a new issue