removed some old stuff, added profiler, minor performance tuning
This commit is contained in:
parent
42e9ddbdd1
commit
f70dd3c3ac
22 changed files with 234 additions and 802 deletions
|
@ -1,99 +0,0 @@
|
||||||
package btools.codec;
|
|
||||||
|
|
||||||
import btools.util.ByteDataWriter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MicroCache1 is the old data format as of brouter 1.1 that does not allow to
|
|
||||||
* filter out unaccessable nodes at the beginning of the cache pipeline
|
|
||||||
*
|
|
||||||
* Kept for backward compatibility
|
|
||||||
*/
|
|
||||||
public final class MicroCache1 extends MicroCache
|
|
||||||
{
|
|
||||||
private int lonIdxBase;
|
|
||||||
private int latIdxBase;
|
|
||||||
|
|
||||||
public MicroCache1( int size, byte[] databuffer, int lonIdx80, int latIdx80 ) throws Exception
|
|
||||||
{
|
|
||||||
super( databuffer ); // sets ab=databuffer, aboffset=0
|
|
||||||
faid = new int[size];
|
|
||||||
fapos = new int[size];
|
|
||||||
this.size = 0;
|
|
||||||
lonIdxBase = ( lonIdx80 / 5 ) * 62500 + 31250;
|
|
||||||
latIdxBase = ( latIdx80 / 5 ) * 62500 + 31250;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MicroCache1( byte[] databuffer, int lonIdx80, int latIdx80 ) throws Exception
|
|
||||||
{
|
|
||||||
super( databuffer ); // sets ab=databuffer, aboffset=0
|
|
||||||
lonIdxBase = ( lonIdx80 / 5 ) * 62500 + 31250;
|
|
||||||
latIdxBase = ( latIdx80 / 5 ) * 62500 + 31250;
|
|
||||||
|
|
||||||
size = readInt();
|
|
||||||
|
|
||||||
// get net size
|
|
||||||
int nbytes = 0;
|
|
||||||
for ( int i = 0; i < size; i++ )
|
|
||||||
{
|
|
||||||
aboffset += 4;
|
|
||||||
int bodySize = readVarLengthUnsigned();
|
|
||||||
aboffset += bodySize;
|
|
||||||
nbytes += bodySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// new array with only net data
|
|
||||||
byte[] nab = new byte[nbytes];
|
|
||||||
aboffset = 4;
|
|
||||||
int noffset = 0;
|
|
||||||
faid = new int[size];
|
|
||||||
fapos = new int[size];
|
|
||||||
|
|
||||||
for ( int i = 0; i < size; i++ )
|
|
||||||
{
|
|
||||||
faid[i] = readInt() ^ 0x8000; // flip lat-sign for correct ordering
|
|
||||||
|
|
||||||
int bodySize = readVarLengthUnsigned();
|
|
||||||
System.arraycopy( ab, aboffset, nab, noffset, bodySize );
|
|
||||||
aboffset += bodySize;
|
|
||||||
noffset += bodySize;
|
|
||||||
fapos[i] = noffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
ab = nab;
|
|
||||||
aboffset = noffset;
|
|
||||||
init( size );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long expandId( int id32 )
|
|
||||||
{
|
|
||||||
int lon32 = lonIdxBase + (short) ( id32 >> 16 );
|
|
||||||
int lat32 = latIdxBase + (short) ( ( id32 & 0xffff ) ^ 0x8000 );
|
|
||||||
return ( (long) lon32 ) << 32 | lat32;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int shrinkId( long id64 )
|
|
||||||
{
|
|
||||||
int lon32 = (int) ( id64 >> 32 );
|
|
||||||
int lat32 = (int) ( id64 & 0xffffffff );
|
|
||||||
return ( lon32 - lonIdxBase ) << 16 | ( ( ( lat32 - latIdxBase ) & 0xffff ) ^ 0x8000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int encodeMicroCache( byte[] buffer )
|
|
||||||
{
|
|
||||||
ByteDataWriter dos = new ByteDataWriter( buffer );
|
|
||||||
dos.writeInt( size );
|
|
||||||
for ( int n = 0; n < size; n++ )
|
|
||||||
{
|
|
||||||
dos.writeInt( faid[n] ^ 0x8000 );
|
|
||||||
int start = n > 0 ? fapos[n - 1] : 0;
|
|
||||||
int end = fapos[n];
|
|
||||||
int len = end - start;
|
|
||||||
dos.writeVarLengthUnsigned( len );
|
|
||||||
dos.write( ab, start, len );
|
|
||||||
}
|
|
||||||
return dos.size();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -108,10 +108,11 @@ final class OsmPath implements OsmLinkHolder
|
||||||
|
|
||||||
private void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc )
|
private void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc )
|
||||||
{
|
{
|
||||||
if ( link.descriptionBitmap == null ) throw new IllegalArgumentException( "null description for: " + link );
|
byte[] description = link.descriptionBitmap;
|
||||||
|
if ( description == null ) throw new IllegalArgumentException( "null description for: " + link );
|
||||||
|
|
||||||
boolean recordTransferNodes = detailMode || rc.countTraffic;
|
boolean recordTransferNodes = detailMode || rc.countTraffic;
|
||||||
boolean recordMessageData = detailMode;
|
boolean recordMessageData = detailMode;
|
||||||
|
|
||||||
rc.nogomatch = false;
|
rc.nogomatch = false;
|
||||||
|
|
||||||
|
@ -126,7 +127,7 @@ final class OsmPath implements OsmLinkHolder
|
||||||
|
|
||||||
int linkdisttotal = 0;
|
int linkdisttotal = 0;
|
||||||
|
|
||||||
MessageData msgData = new MessageData();
|
MessageData msgData = recordMessageData ? new MessageData() : null;
|
||||||
|
|
||||||
OsmTransferNode transferNode = link.decodeFirsttransfer( p1 );
|
OsmTransferNode transferNode = link.decodeFirsttransfer( p1 );
|
||||||
OsmNode targetNode = link.targetNode;
|
OsmNode targetNode = link.targetNode;
|
||||||
|
@ -138,27 +139,21 @@ final class OsmPath implements OsmLinkHolder
|
||||||
int lon2;
|
int lon2;
|
||||||
int lat2;
|
int lat2;
|
||||||
short ele2;
|
short ele2;
|
||||||
byte[] description;
|
|
||||||
|
|
||||||
if ( transferNode == null )
|
if ( transferNode == null )
|
||||||
{
|
{
|
||||||
lon2 = targetNode.ilon;
|
lon2 = targetNode.ilon;
|
||||||
lat2 = targetNode.ilat;
|
lat2 = targetNode.ilat;
|
||||||
ele2 = targetNode.selev;
|
ele2 = targetNode.selev;
|
||||||
description = link.descriptionBitmap;
|
|
||||||
if ( description == null ) throw new IllegalArgumentException( "null description for class: " + link.getClass() );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lon2 = transferNode.ilon;
|
lon2 = transferNode.ilon;
|
||||||
lat2 = transferNode.ilat;
|
lat2 = transferNode.ilat;
|
||||||
ele2 = transferNode.selev;
|
ele2 = transferNode.selev;
|
||||||
description = transferNode.descriptionBitmap;
|
|
||||||
if ( description == null ) throw new IllegalArgumentException( "null description for class: " + transferNode.getClass() + "/" + link.getClass() + " counterlinkwritten=" + link.counterLinkWritten );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc.messageHandler.setCurrentPos( lon2, lat2 );
|
boolean sameData = rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description );
|
||||||
boolean sameData = rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description, rc.messageHandler );
|
|
||||||
|
|
||||||
// if way description changed, store message
|
// if way description changed, store message
|
||||||
if ( recordMessageData && msgData.wayKeyValues != null )
|
if ( recordMessageData && msgData.wayKeyValues != null )
|
||||||
|
@ -198,7 +193,10 @@ final class OsmPath implements OsmLinkHolder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msgData.linkdist += dist;
|
if ( recordMessageData )
|
||||||
|
{
|
||||||
|
msgData.linkdist += dist;
|
||||||
|
}
|
||||||
linkdisttotal += dist;
|
linkdisttotal += dist;
|
||||||
|
|
||||||
boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f;
|
boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f;
|
||||||
|
@ -210,9 +208,9 @@ final class OsmPath implements OsmLinkHolder
|
||||||
double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
|
double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
|
||||||
int turncost = (int)(cos * rc.expctxWay.getTurncost() + 0.2 ); // e.g. turncost=90 -> 90 degree = 90m penalty
|
int turncost = (int)(cos * rc.expctxWay.getTurncost() + 0.2 ); // e.g. turncost=90 -> 90 degree = 90m penalty
|
||||||
cost += turncost;
|
cost += turncost;
|
||||||
msgData.linkturncost += turncost;
|
|
||||||
if ( recordMessageData )
|
if ( recordMessageData )
|
||||||
{
|
{
|
||||||
|
msgData.linkturncost += turncost;
|
||||||
msgData.turnangle = (float)rc.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
|
msgData.turnangle = (float)rc.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +248,10 @@ final class OsmPath implements OsmLinkHolder
|
||||||
{
|
{
|
||||||
int elevationCost = reduce/rc.downhillcostdiv;
|
int elevationCost = reduce/rc.downhillcostdiv;
|
||||||
cost += elevationCost;
|
cost += elevationCost;
|
||||||
msgData.linkelevationcost += elevationCost;
|
if ( recordMessageData )
|
||||||
|
{
|
||||||
|
msgData.linkelevationcost += elevationCost;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( ehbd < 0 )
|
else if ( ehbd < 0 )
|
||||||
|
@ -280,7 +281,10 @@ final class OsmPath implements OsmLinkHolder
|
||||||
{
|
{
|
||||||
int elevationCost = reduce/rc.uphillcostdiv;
|
int elevationCost = reduce/rc.uphillcostdiv;
|
||||||
cost += elevationCost;
|
cost += elevationCost;
|
||||||
msgData.linkelevationcost += elevationCost;
|
if ( recordMessageData )
|
||||||
|
{
|
||||||
|
msgData.linkelevationcost += elevationCost;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( ehbu < 0 )
|
else if ( ehbu < 0 )
|
||||||
|
@ -313,6 +317,7 @@ final class OsmPath implements OsmLinkHolder
|
||||||
cost += waycost;
|
cost += waycost;
|
||||||
|
|
||||||
// calculate traffic
|
// calculate traffic
|
||||||
|
if ( rc.countTraffic )
|
||||||
{
|
{
|
||||||
int minDist = (int)rc.trafficSourceMinDist;
|
int minDist = (int)rc.trafficSourceMinDist;
|
||||||
int cost2 = cost < minDist ? minDist : cost;
|
int cost2 = cost < minDist ? minDist : cost;
|
||||||
|
@ -330,7 +335,10 @@ final class OsmPath implements OsmLinkHolder
|
||||||
lastClassifier = newClassifier;
|
lastClassifier = newClassifier;
|
||||||
float initialcost = rc.expctxWay.getInitialcost();
|
float initialcost = rc.expctxWay.getInitialcost();
|
||||||
int iicost = (int)initialcost;
|
int iicost = (int)initialcost;
|
||||||
msgData.linkinitcost += iicost;
|
if ( recordMessageData )
|
||||||
|
{
|
||||||
|
msgData.linkinitcost += iicost;
|
||||||
|
}
|
||||||
cost += iicost;
|
cost += iicost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,8 +410,7 @@ final class OsmPath implements OsmLinkHolder
|
||||||
if ( targetNode.nodeDescription != null )
|
if ( targetNode.nodeDescription != null )
|
||||||
{
|
{
|
||||||
boolean nodeAccessGranted = rc.expctxWay.getNodeAccessGranted() != 0.;
|
boolean nodeAccessGranted = rc.expctxWay.getNodeAccessGranted() != 0.;
|
||||||
rc.messageHandler.setCurrentPos( targetNode.ilon, targetNode.ilat );
|
rc.expctxNode.evaluate( nodeAccessGranted , targetNode.nodeDescription );
|
||||||
rc.expctxNode.evaluate( nodeAccessGranted , targetNode.nodeDescription, rc.messageHandler );
|
|
||||||
float initialcost = rc.expctxNode.getInitialcost();
|
float initialcost = rc.expctxNode.getInitialcost();
|
||||||
if ( initialcost >= 1000000. )
|
if ( initialcost >= 1000000. )
|
||||||
{
|
{
|
||||||
|
@ -411,12 +418,12 @@ final class OsmPath implements OsmLinkHolder
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int iicost = (int)initialcost;
|
int iicost = (int)initialcost;
|
||||||
msgData.linknodecost += iicost;
|
|
||||||
|
|
||||||
cost += iicost;
|
cost += iicost;
|
||||||
|
|
||||||
if ( recordMessageData )
|
if ( recordMessageData )
|
||||||
{
|
{
|
||||||
|
msgData.linknodecost += iicost;
|
||||||
msgData.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription );
|
msgData.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,8 +111,6 @@ public final class RoutingContext implements DistanceChecker
|
||||||
turnInstructionRoundabouts = expctxGlobal.getVariableValue( "turnInstructionRoundabouts", 1.f ) != 0.f;
|
turnInstructionRoundabouts = expctxGlobal.getVariableValue( "turnInstructionRoundabouts", 1.f ) != 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RoutingMessageHandler messageHandler = new RoutingMessageHandler();
|
|
||||||
|
|
||||||
public List<OsmNodeNamed> nogopoints = null;
|
public List<OsmNodeNamed> nogopoints = null;
|
||||||
private List<OsmNodeNamed> keepnogopoints = null;
|
private List<OsmNodeNamed> keepnogopoints = null;
|
||||||
|
|
||||||
|
@ -222,10 +220,11 @@ public final class RoutingContext implements DistanceChecker
|
||||||
|
|
||||||
shortestmatch = false;
|
shortestmatch = false;
|
||||||
|
|
||||||
if ( d > 0. && nogopoints != null )
|
if ( nogopoints != null && !nogopoints.isEmpty() && d > 0. )
|
||||||
{
|
{
|
||||||
for( OsmNodeNamed nogo : nogopoints )
|
for( int ngidx = 0; ngidx < nogopoints.size(); ngidx++ )
|
||||||
{
|
{
|
||||||
|
OsmNodeNamed nogo = nogopoints.get(ngidx);
|
||||||
double x1 = (lon1 - nogo.ilon) * coslat6;
|
double x1 = (lon1 - nogo.ilon) * coslat6;
|
||||||
double y1 = (lat1 - nogo.ilat) * 0.000001;
|
double y1 = (lat1 - nogo.ilat) * 0.000001;
|
||||||
double x2 = (lon2 - nogo.ilon) * coslat6;
|
double x2 = (lon2 - nogo.ilon) * coslat6;
|
||||||
|
|
|
@ -16,6 +16,7 @@ import btools.mapaccess.OsmLinkHolder;
|
||||||
import btools.mapaccess.OsmNode;
|
import btools.mapaccess.OsmNode;
|
||||||
import btools.mapaccess.OsmNodesMap;
|
import btools.mapaccess.OsmNodesMap;
|
||||||
import btools.util.SortedHeap;
|
import btools.util.SortedHeap;
|
||||||
|
import btools.util.StackSampler;
|
||||||
|
|
||||||
public class RoutingEngine extends Thread
|
public class RoutingEngine extends Thread
|
||||||
{
|
{
|
||||||
|
@ -43,6 +44,7 @@ public class RoutingEngine extends Thread
|
||||||
private String logfileBase;
|
private String logfileBase;
|
||||||
private boolean infoLogEnabled;
|
private boolean infoLogEnabled;
|
||||||
private Writer infoLogWriter;
|
private Writer infoLogWriter;
|
||||||
|
private StackSampler stackSampler;
|
||||||
protected RoutingContext routingContext;
|
protected RoutingContext routingContext;
|
||||||
|
|
||||||
public double airDistanceCostFactor;
|
public double airDistanceCostFactor;
|
||||||
|
@ -66,9 +68,10 @@ public class RoutingEngine extends Thread
|
||||||
this.infoLogEnabled = outfileBase != null;
|
this.infoLogEnabled = outfileBase != null;
|
||||||
this.routingContext = rc;
|
this.routingContext = rc;
|
||||||
|
|
||||||
|
File baseFolder = new File( routingContext.localFunction ).getParentFile().getParentFile();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File debugLog = new File( new File( routingContext.localFunction ).getParentFile(), "../debug.txt" );
|
File debugLog = new File( baseFolder, "debug.txt" );
|
||||||
if ( debugLog.exists() )
|
if ( debugLog.exists() )
|
||||||
{
|
{
|
||||||
infoLogWriter = new FileWriter( debugLog, true );
|
infoLogWriter = new FileWriter( debugLog, true );
|
||||||
|
@ -80,6 +83,15 @@ public class RoutingEngine extends Thread
|
||||||
{
|
{
|
||||||
throw new RuntimeException( "cannot open debug-log:" + ioe );
|
throw new RuntimeException( "cannot open debug-log:" + ioe );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File stackLog = new File( baseFolder, "stacks.txt" );
|
||||||
|
if ( stackLog.exists() )
|
||||||
|
{
|
||||||
|
stackSampler = new StackSampler( stackLog, 1000 );
|
||||||
|
stackSampler.start();
|
||||||
|
logInfo( "********** started stacksampling" );
|
||||||
|
}
|
||||||
|
|
||||||
boolean cachedProfile = ProfileCache.parseProfile( rc );
|
boolean cachedProfile = ProfileCache.parseProfile( rc );
|
||||||
if ( hasInfo() )
|
if ( hasInfo() )
|
||||||
{
|
{
|
||||||
|
@ -229,6 +241,13 @@ public class RoutingEngine extends Thread
|
||||||
try { infoLogWriter.close(); } catch( Exception e ) {}
|
try { infoLogWriter.close(); } catch( Exception e ) {}
|
||||||
infoLogWriter = null;
|
infoLogWriter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( stackSampler != null )
|
||||||
|
{
|
||||||
|
try { stackSampler.close(); } catch( Exception e ) {}
|
||||||
|
stackSampler = null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,16 +397,6 @@ public class RoutingEngine extends Thread
|
||||||
{
|
{
|
||||||
preloadPosition( mwp.waypoint );
|
preloadPosition( mwp.waypoint );
|
||||||
}
|
}
|
||||||
|
|
||||||
// preliminary-hack: use old stuff if not yet matched
|
|
||||||
for( int i=0; i<unmatchedWaypoints.size(); i++)
|
|
||||||
{
|
|
||||||
MatchedWaypoint mwp = unmatchedWaypoints.get(i);
|
|
||||||
if ( mwp.crosspoint == null )
|
|
||||||
{
|
|
||||||
unmatchedWaypoints.set(i, matchNodeForPosition( mwp.waypoint ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preloadPosition( OsmNode n )
|
private void preloadPosition( OsmNode n )
|
||||||
|
@ -408,93 +417,6 @@ public class RoutingEngine extends Thread
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// geometric position matching finding the nearest routable way-section
|
|
||||||
private MatchedWaypoint matchNodeForPosition( OsmNodeNamed wp )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
routingContext.setWaypoint( wp, false );
|
|
||||||
|
|
||||||
int minRingWith = 1;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
MatchedWaypoint mwp = _matchNodeForPosition( wp, minRingWith );
|
|
||||||
if ( mwp.node1 != null )
|
|
||||||
{
|
|
||||||
int mismatch = wp.calcDistance( mwp.crosspoint );
|
|
||||||
if ( mismatch < 50*minRingWith )
|
|
||||||
{
|
|
||||||
return mwp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( minRingWith == 1 && nodesCache.first_file_access_failed )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException( "datafile " + nodesCache.first_file_access_name + " not found" );
|
|
||||||
}
|
|
||||||
if ( minRingWith++ == 5 )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException( wp.name + "-position not mapped in existing datafile" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
routingContext.unsetWaypoint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MatchedWaypoint _matchNodeForPosition( OsmNodeNamed wp, int minRingWidth )
|
|
||||||
{
|
|
||||||
wp.radius = 1e9;
|
|
||||||
resetCache();
|
|
||||||
preloadPosition( wp, minRingWidth, 2000 );
|
|
||||||
nodesCache.distanceChecker = routingContext;
|
|
||||||
List<OsmNode> nodeList = nodesCache.getAllNodes();
|
|
||||||
|
|
||||||
MatchedWaypoint mwp = new MatchedWaypoint();
|
|
||||||
mwp.waypoint = wp;
|
|
||||||
|
|
||||||
// first loop just to expand reverse links
|
|
||||||
for( OsmNode n : nodeList )
|
|
||||||
{
|
|
||||||
if ( !nodesCache.obtainNonHollowNode( n ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
expandHollowLinkTargets( n );
|
|
||||||
OsmLink startLink = new OsmLink();
|
|
||||||
startLink.targetNode = n;
|
|
||||||
OsmPath startPath = new OsmPath( startLink );
|
|
||||||
startLink.addLinkHolder( startPath );
|
|
||||||
for( OsmLink link = n.firstlink; link != null; link = link.next )
|
|
||||||
{
|
|
||||||
if ( link.descriptionBitmap == null ) continue; // reverse link not found
|
|
||||||
OsmNode nextNode = link.targetNode;
|
|
||||||
if ( nextNode.isHollow() ) continue; // border node?
|
|
||||||
if ( nextNode.firstlink == null ) continue; // don't care about dead ends
|
|
||||||
if ( nextNode == n ) continue; // ?
|
|
||||||
double oldRadius = wp.radius;
|
|
||||||
OsmPath testPath = new OsmPath( n, startPath, link, null, false, routingContext );
|
|
||||||
if ( wp.radius < oldRadius )
|
|
||||||
{
|
|
||||||
if ( testPath.cost < 0 )
|
|
||||||
{
|
|
||||||
wp.radius = oldRadius; // no valid way
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mwp.node1 = n;
|
|
||||||
mwp.node2 = nextNode;
|
|
||||||
mwp.radius = wp.radius;
|
|
||||||
mwp.crosspoint = new OsmNodeNamed();
|
|
||||||
mwp.crosspoint.ilon = routingContext.ilonshortest;
|
|
||||||
mwp.crosspoint.ilat = routingContext.ilatshortest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mwp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// expand hollow link targets and resolve reverse links
|
// expand hollow link targets and resolve reverse links
|
||||||
private void expandHollowLinkTargets( OsmNode n )
|
private void expandHollowLinkTargets( OsmNode n )
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
/**
|
|
||||||
* Container for routig configs
|
|
||||||
*
|
|
||||||
* @author ab
|
|
||||||
*/
|
|
||||||
package btools.router;
|
|
||||||
|
|
||||||
import btools.expressions.BExpressionReceiver;
|
|
||||||
|
|
||||||
final class RoutingMessageHandler implements BExpressionReceiver
|
|
||||||
{
|
|
||||||
private int ilon;
|
|
||||||
private int ilat;
|
|
||||||
|
|
||||||
public void setCurrentPos( int lon, int lat)
|
|
||||||
{
|
|
||||||
ilon = lon;
|
|
||||||
ilat = lat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void expressionWarning( String context, String message )
|
|
||||||
{
|
|
||||||
System.out.println( "message (lon=" + (ilon-180000000) + " lat=" + (ilat-90000000)
|
|
||||||
+ " context " + context + "): " + message );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,8 +25,6 @@ final class BExpression
|
||||||
private static final int NUMBER_EXP = 33;
|
private static final int NUMBER_EXP = 33;
|
||||||
private static final int VARIABLE_EXP = 34;
|
private static final int VARIABLE_EXP = 34;
|
||||||
|
|
||||||
private static final int DUMPPOS_EXP = 40;
|
|
||||||
|
|
||||||
private int typ;
|
private int typ;
|
||||||
private BExpression op1;
|
private BExpression op1;
|
||||||
private BExpression op2;
|
private BExpression op2;
|
||||||
|
@ -147,10 +145,6 @@ final class BExpression
|
||||||
{
|
{
|
||||||
exp.typ = NOT_EXP;
|
exp.typ = NOT_EXP;
|
||||||
}
|
}
|
||||||
else if ( "dumppos".equals( operator ) )
|
|
||||||
{
|
|
||||||
exp.typ = DUMPPOS_EXP;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nops = 0; // check elemantary expressions
|
nops = 0; // check elemantary expressions
|
||||||
|
@ -263,7 +257,6 @@ final class BExpression
|
||||||
case NUMBER_EXP: return numberValue;
|
case NUMBER_EXP: return numberValue;
|
||||||
case VARIABLE_EXP: return ctx.getVariableValue( variableIdx );
|
case VARIABLE_EXP: return ctx.getVariableValue( variableIdx );
|
||||||
case NOT_EXP: return op1.evaluate(ctx) == 0.f ? 1.f : 0.f;
|
case NOT_EXP: return op1.evaluate(ctx) == 0.f ? 1.f : 0.f;
|
||||||
case DUMPPOS_EXP: ctx.expressionWarning( "INFO" ); return op1.evaluate(ctx);
|
|
||||||
default: throw new IllegalArgumentException( "unknown op-code: " + typ );
|
default: throw new IllegalArgumentException( "unknown op-code: " + typ );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,6 @@ public abstract class BExpressionContext
|
||||||
private BufferedReader _br = null;
|
private BufferedReader _br = null;
|
||||||
private boolean _readerDone = false;
|
private boolean _readerDone = false;
|
||||||
|
|
||||||
private BExpressionReceiver _receiver;
|
|
||||||
|
|
||||||
private Map<String,Integer> lookupNumbers = new HashMap<String,Integer>();
|
private Map<String,Integer> lookupNumbers = new HashMap<String,Integer>();
|
||||||
private ArrayList<BExpressionLookupValue[]> lookupValues = new ArrayList<BExpressionLookupValue[]>();
|
private ArrayList<BExpressionLookupValue[]> lookupValues = new ArrayList<BExpressionLookupValue[]>();
|
||||||
private ArrayList<String> lookupNames = new ArrayList<String>();
|
private ArrayList<String> lookupNames = new ArrayList<String>();
|
||||||
|
@ -58,20 +56,21 @@ public abstract class BExpressionContext
|
||||||
private byte[] currentByteArray = null;
|
private byte[] currentByteArray = null;
|
||||||
private boolean currentInverseDirection= false;
|
private boolean currentInverseDirection= false;
|
||||||
|
|
||||||
public List<BExpression> expressionList;
|
private List<BExpression> expressionList;
|
||||||
|
|
||||||
private int minWriteIdx;
|
private int minWriteIdx;
|
||||||
|
|
||||||
// build-in variable indexes for fast access
|
// build-in variable indexes for fast access
|
||||||
private int[] buildInVariableIdx;
|
private int[] buildInVariableIdx;
|
||||||
|
|
||||||
protected float[][] arrayBuildInVariablesCache;
|
private float[][] arrayBuildInVariablesCache;
|
||||||
|
private float[] hashBucketVars;
|
||||||
|
|
||||||
abstract String[] getBuildInVariableNames();
|
abstract String[] getBuildInVariableNames();
|
||||||
|
|
||||||
protected float getBuildInVariable( int idx )
|
protected final float getBuildInVariable( int idx )
|
||||||
{
|
{
|
||||||
return arrayBuildInVariablesCache[idx][currentHashBucket];
|
return hashBucketVars[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
private int linenr;
|
private int linenr;
|
||||||
|
@ -105,10 +104,10 @@ public abstract class BExpressionContext
|
||||||
|
|
||||||
// create the build-in variables cache
|
// create the build-in variables cache
|
||||||
int nBuildInVars = getBuildInVariableNames().length;
|
int nBuildInVars = getBuildInVariableNames().length;
|
||||||
arrayBuildInVariablesCache = new float[nBuildInVars][];
|
arrayBuildInVariablesCache = new float[hashSize][];
|
||||||
for( int vi=0; vi<nBuildInVars; vi++ )
|
for( int hi=0; hi<hashSize; hi++ )
|
||||||
{
|
{
|
||||||
arrayBuildInVariablesCache[vi] = new float[hashSize];
|
arrayBuildInVariablesCache[hi] = new float[nBuildInVars];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,9 +263,10 @@ public abstract class BExpressionContext
|
||||||
public void evaluate( int[] lookupData2 )
|
public void evaluate( int[] lookupData2 )
|
||||||
{
|
{
|
||||||
lookupData = lookupData2;
|
lookupData = lookupData2;
|
||||||
for( BExpression exp: expressionList)
|
int n = expressionList.size();
|
||||||
|
for( int expidx = 0; expidx < n; expidx++ )
|
||||||
{
|
{
|
||||||
exp.evaluate( this );
|
expressionList.get( expidx ).evaluate( this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ public abstract class BExpressionContext
|
||||||
*
|
*
|
||||||
* @return true if the data is equivilant to the last calls data
|
* @return true if the data is equivilant to the last calls data
|
||||||
*/
|
*/
|
||||||
public boolean evaluate( boolean inverseDirection, byte[] ab, BExpressionReceiver receiver )
|
public boolean evaluate( boolean inverseDirection, byte[] ab )
|
||||||
{
|
{
|
||||||
requests ++;
|
requests ++;
|
||||||
lookupDataValid = false; // this is an assertion for a nasty pifall
|
lookupDataValid = false; // this is an assertion for a nasty pifall
|
||||||
|
@ -291,6 +291,7 @@ public abstract class BExpressionContext
|
||||||
int crc = Crc32.crcWithInverseBit(ab, inverseDirection ? inverseBitByteIndex : -1 );
|
int crc = Crc32.crcWithInverseBit(ab, inverseDirection ? inverseBitByteIndex : -1 );
|
||||||
int hashSize = _arrayBitmap.length;
|
int hashSize = _arrayBitmap.length;
|
||||||
currentHashBucket = (crc & 0xfffffff) % hashSize;
|
currentHashBucket = (crc & 0xfffffff) % hashSize;
|
||||||
|
hashBucketVars = arrayBuildInVariablesCache[currentHashBucket];
|
||||||
currentByteArray = ab;
|
currentByteArray = ab;
|
||||||
currentInverseDirection = inverseDirection;
|
currentInverseDirection = inverseDirection;
|
||||||
byte[] abBucket = _arrayBitmap[currentHashBucket];
|
byte[] abBucket = _arrayBitmap[currentHashBucket];
|
||||||
|
@ -325,18 +326,15 @@ public abstract class BExpressionContext
|
||||||
_arrayInverse[currentHashBucket] = currentInverseDirection;
|
_arrayInverse[currentHashBucket] = currentInverseDirection;
|
||||||
_arrayCrc[currentHashBucket] = crc;
|
_arrayCrc[currentHashBucket] = crc;
|
||||||
|
|
||||||
_receiver = receiver;
|
|
||||||
|
|
||||||
decode( lookupData, currentInverseDirection, currentByteArray );
|
decode( lookupData, currentInverseDirection, currentByteArray );
|
||||||
evaluate( lookupData );
|
evaluate( lookupData );
|
||||||
|
|
||||||
for( int vi=0; vi<buildInVariableIdx.length; vi++ )
|
for( int vi=0; vi<buildInVariableIdx.length; vi++ )
|
||||||
{
|
{
|
||||||
int idx = buildInVariableIdx[vi];
|
int idx = buildInVariableIdx[vi];
|
||||||
arrayBuildInVariablesCache[vi][currentHashBucket] = idx == -1 ? 0.f : variableData[idx];
|
hashBucketVars[vi] = idx == -1 ? 0.f : variableData[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
_receiver = null;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,9 +761,4 @@ public abstract class BExpressionContext
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void expressionWarning( String message )
|
|
||||||
{
|
|
||||||
_arrayBitmap[currentHashBucket] = null; // no caching if warnings
|
|
||||||
if ( _receiver != null ) _receiver.expressionWarning( context, message );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,11 @@ public final class BExpressionContextWay extends BExpressionContext implements T
|
||||||
@Override
|
@Override
|
||||||
public int accessType( byte[] description )
|
public int accessType( byte[] description )
|
||||||
{
|
{
|
||||||
evaluate( false, description, null );
|
evaluate( false, description );
|
||||||
float minCostFactor = getCostfactor();
|
float minCostFactor = getCostfactor();
|
||||||
if ( minCostFactor >= 9999.f )
|
if ( minCostFactor >= 9999.f )
|
||||||
{
|
{
|
||||||
evaluate( true, description, null );
|
evaluate( true, description );
|
||||||
float reverseCostFactor = getCostfactor();
|
float reverseCostFactor = getCostfactor();
|
||||||
if ( reverseCostFactor < minCostFactor )
|
if ( reverseCostFactor < minCostFactor )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
package btools.expressions;
|
|
||||||
|
|
||||||
|
|
||||||
public interface BExpressionReceiver
|
|
||||||
{
|
|
||||||
public void expressionWarning( String context, String message );
|
|
||||||
}
|
|
|
@ -39,7 +39,7 @@ public class EncodeDecodeTest
|
||||||
byte[] description = expctxWay.encode(lookupData);
|
byte[] description = expctxWay.encode(lookupData);
|
||||||
|
|
||||||
// calculate the cost factor from that description
|
// calculate the cost factor from that description
|
||||||
expctxWay.evaluate( false, description, null );
|
expctxWay.evaluate( false, description );
|
||||||
|
|
||||||
float costfactor = expctxWay.getCostfactor();
|
float costfactor = expctxWay.getCostfactor();
|
||||||
Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.15 ) < 0.00001 );
|
Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.15 ) < 0.00001 );
|
||||||
|
|
|
@ -156,9 +156,9 @@ public class OsmCutter extends MapCreatorBase
|
||||||
if ( w.description == null ) return;
|
if ( w.description == null ) return;
|
||||||
|
|
||||||
// filter according to profile
|
// filter according to profile
|
||||||
_expctxWay.evaluate( false, w.description, null );
|
_expctxWay.evaluate( false, w.description );
|
||||||
boolean ok = _expctxWay.getCostfactor() < 10000.;
|
boolean ok = _expctxWay.getCostfactor() < 10000.;
|
||||||
_expctxWay.evaluate( true, w.description, null );
|
_expctxWay.evaluate( true, w.description );
|
||||||
ok |= _expctxWay.getCostfactor() < 10000.;
|
ok |= _expctxWay.getCostfactor() < 10000.;
|
||||||
if ( !ok ) return;
|
if ( !ok ) return;
|
||||||
|
|
||||||
|
|
|
@ -10,18 +10,10 @@ import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import btools.codec.MicroCache;
|
import btools.codec.MicroCache;
|
||||||
import btools.codec.MicroCache1;
|
|
||||||
import btools.codec.MicroCache2;
|
import btools.codec.MicroCache2;
|
||||||
|
|
||||||
public class OsmNodeP extends OsmLinkP
|
public class OsmNodeP extends OsmLinkP
|
||||||
{
|
{
|
||||||
public static final int SIGNLON_BITMASK = 0x80;
|
|
||||||
public static final int SIGNLAT_BITMASK = 0x40;
|
|
||||||
public static final int TRANSFERNODE_BITMASK = 0x20;
|
|
||||||
public static final int WRITEDESC_BITMASK = 0x10;
|
|
||||||
public static final int SKIPDETAILS_BITMASK = 0x08;
|
|
||||||
public static final int NODEDESC_BITMASK = 0x04;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The latitude
|
* The latitude
|
||||||
*/
|
*/
|
||||||
|
@ -104,151 +96,10 @@ public class OsmNodeP extends OsmLinkP
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeNodeData1( MicroCache1 mc ) throws IOException
|
|
||||||
{
|
|
||||||
mc.writeShort( getSElev() );
|
|
||||||
|
|
||||||
// hack: write node-desc as link tag (copy cycleway-bits)
|
|
||||||
byte[] nodeDescription = getNodeDecsription();
|
|
||||||
|
|
||||||
for ( OsmLinkP link0 = getFirstLink(); link0 != null; link0 = link0.getNext( this ) )
|
|
||||||
{
|
|
||||||
int ilonref = ilon;
|
|
||||||
int ilatref = ilat;
|
|
||||||
|
|
||||||
OsmLinkP link = link0;
|
|
||||||
OsmNodeP origin = this;
|
|
||||||
int skipDetailBit = link0.descriptionBitmap == null ? SKIPDETAILS_BITMASK : 0;
|
|
||||||
|
|
||||||
// first pass just to see if that link is consistent
|
|
||||||
while (link != null)
|
|
||||||
{
|
|
||||||
OsmNodeP target = link.getTarget( origin );
|
|
||||||
if ( !target.isTransferNode() )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// next link is the one (of two), does does'nt point back
|
|
||||||
for ( link = target.getFirstLink(); link != null; link = link.getNext( target ) )
|
|
||||||
{
|
|
||||||
if ( link.getTarget( target ) != origin )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
origin = target;
|
|
||||||
}
|
|
||||||
if ( link == null )
|
|
||||||
continue; // dead end
|
|
||||||
|
|
||||||
if ( skipDetailBit == 0 )
|
|
||||||
{
|
|
||||||
link = link0;
|
|
||||||
origin = this;
|
|
||||||
}
|
|
||||||
byte[] lastDescription = null;
|
|
||||||
while (link != null)
|
|
||||||
{
|
|
||||||
if ( link.descriptionBitmap == null && skipDetailBit == 0 )
|
|
||||||
throw new IllegalArgumentException( "missing way description..." );
|
|
||||||
|
|
||||||
OsmNodeP target = link.getTarget( origin );
|
|
||||||
int tranferbit = target.isTransferNode() ? TRANSFERNODE_BITMASK : 0;
|
|
||||||
int nodedescbit = nodeDescription != null ? NODEDESC_BITMASK : 0;
|
|
||||||
|
|
||||||
int writedescbit = 0;
|
|
||||||
if ( skipDetailBit == 0 ) // check if description changed
|
|
||||||
{
|
|
||||||
int inverseBitByteIndex = 0;
|
|
||||||
boolean inverseDirection = link.isReverse( origin );
|
|
||||||
byte[] ab = link.descriptionBitmap;
|
|
||||||
int abLen = ab.length;
|
|
||||||
int lastLen = lastDescription == null ? 0 : lastDescription.length;
|
|
||||||
boolean equalsCurrent = abLen == lastLen;
|
|
||||||
if ( equalsCurrent )
|
|
||||||
{
|
|
||||||
for ( int i = 0; i < abLen; i++ )
|
|
||||||
{
|
|
||||||
byte b = ab[i];
|
|
||||||
if ( i == inverseBitByteIndex && inverseDirection )
|
|
||||||
b ^= 1;
|
|
||||||
if ( b != lastDescription[i] )
|
|
||||||
{
|
|
||||||
equalsCurrent = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !equalsCurrent )
|
|
||||||
{
|
|
||||||
writedescbit = WRITEDESC_BITMASK;
|
|
||||||
lastDescription = new byte[abLen];
|
|
||||||
System.arraycopy( ab, 0, lastDescription, 0, abLen );
|
|
||||||
if ( inverseDirection )
|
|
||||||
lastDescription[inverseBitByteIndex] ^= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int bm = tranferbit | writedescbit | nodedescbit | skipDetailBit;
|
|
||||||
int dlon = target.ilon - ilonref;
|
|
||||||
int dlat = target.ilat - ilatref;
|
|
||||||
ilonref = target.ilon;
|
|
||||||
ilatref = target.ilat;
|
|
||||||
if ( dlon < 0 )
|
|
||||||
{
|
|
||||||
bm |= SIGNLON_BITMASK;
|
|
||||||
dlon = -dlon;
|
|
||||||
}
|
|
||||||
if ( dlat < 0 )
|
|
||||||
{
|
|
||||||
bm |= SIGNLAT_BITMASK;
|
|
||||||
dlat = -dlat;
|
|
||||||
}
|
|
||||||
mc.writeByte( bm );
|
|
||||||
|
|
||||||
mc.writeVarLengthUnsigned( dlon );
|
|
||||||
mc.writeVarLengthUnsigned( dlat );
|
|
||||||
|
|
||||||
if ( writedescbit != 0 )
|
|
||||||
{
|
|
||||||
// write the way description, code direction into the first bit
|
|
||||||
mc.writeByte( lastDescription.length );
|
|
||||||
mc.write( lastDescription );
|
|
||||||
}
|
|
||||||
if ( nodedescbit != 0 )
|
|
||||||
{
|
|
||||||
mc.writeByte( nodeDescription.length );
|
|
||||||
mc.write( nodeDescription );
|
|
||||||
nodeDescription = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
link.descriptionBitmap = null; // mark link as written
|
|
||||||
|
|
||||||
if ( tranferbit == 0 )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mc.writeVarLengthSigned( target.getSElev() - getSElev() );
|
|
||||||
// next link is the one (of two), does does'nt point back
|
|
||||||
for ( link = target.getFirstLink(); link != null; link = link.getNext( target ) )
|
|
||||||
{
|
|
||||||
if ( link.getTarget( target ) != origin )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( link == null )
|
|
||||||
throw new RuntimeException( "follow-up link not found for transfer-node!" );
|
|
||||||
origin = target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeNodeData( MicroCache mc ) throws IOException
|
public void writeNodeData( MicroCache mc ) throws IOException
|
||||||
{
|
{
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
if ( mc instanceof MicroCache1 )
|
if ( mc instanceof MicroCache2 )
|
||||||
{
|
|
||||||
writeNodeData1( (MicroCache1) mc );
|
|
||||||
}
|
|
||||||
else if ( mc instanceof MicroCache2 )
|
|
||||||
{
|
{
|
||||||
valid = writeNodeData2( (MicroCache2) mc );
|
valid = writeNodeData2( (MicroCache2) mc );
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,11 +124,11 @@ public class RelationMerger extends MapCreatorBase
|
||||||
{
|
{
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
// check access and log a warning for conflicts
|
// check access and log a warning for conflicts
|
||||||
expctxReport.evaluate( false, data.description, null );
|
expctxReport.evaluate( false, data.description );
|
||||||
boolean warn = expctxReport.getCostfactor() >= 10000.;
|
boolean warn = expctxReport.getCostfactor() >= 10000.;
|
||||||
if ( warn )
|
if ( warn )
|
||||||
{
|
{
|
||||||
expctxCheck.evaluate( false, data.description, null );
|
expctxCheck.evaluate( false, data.description );
|
||||||
ok = expctxCheck.getCostfactor() < 10000.;
|
ok = expctxCheck.getCostfactor() < 10000.;
|
||||||
|
|
||||||
System.out.println( "** relation access conflict for wid = " + data.wid + " tags:" + expctxReport.getKeyValueDescription( false, data.description ) + " (ok=" + ok + ")" );
|
System.out.println( "** relation access conflict for wid = " + data.wid + " tags:" + expctxReport.getKeyValueDescription( false, data.description ) + " (ok=" + ok + ")" );
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.util.TreeMap;
|
||||||
|
|
||||||
import btools.codec.DataBuffers;
|
import btools.codec.DataBuffers;
|
||||||
import btools.codec.MicroCache;
|
import btools.codec.MicroCache;
|
||||||
import btools.codec.MicroCache1;
|
|
||||||
import btools.codec.MicroCache2;
|
import btools.codec.MicroCache2;
|
||||||
import btools.codec.StatCoderContext;
|
import btools.codec.StatCoderContext;
|
||||||
import btools.expressions.BExpressionContextWay;
|
import btools.expressions.BExpressionContextWay;
|
||||||
|
@ -57,7 +56,7 @@ public class WayLinker extends MapCreatorBase
|
||||||
private int minLat;
|
private int minLat;
|
||||||
|
|
||||||
private int microCacheEncoding = 2;
|
private int microCacheEncoding = 2;
|
||||||
private int divisor = microCacheEncoding == 2 ? 32 : 80;
|
private int divisor = 32;
|
||||||
private int cellsize = 1000000 / divisor;
|
private int cellsize = 1000000 / divisor;
|
||||||
|
|
||||||
private void reset()
|
private void reset()
|
||||||
|
@ -186,9 +185,9 @@ public class WayLinker extends MapCreatorBase
|
||||||
int lastTraffic = 0;
|
int lastTraffic = 0;
|
||||||
|
|
||||||
// filter according to profile
|
// filter according to profile
|
||||||
expctxWay.evaluate( false, description, null );
|
expctxWay.evaluate( false, description );
|
||||||
boolean ok = expctxWay.getCostfactor() < 10000.;
|
boolean ok = expctxWay.getCostfactor() < 10000.;
|
||||||
expctxWay.evaluate( true, description, null );
|
expctxWay.evaluate( true, description );
|
||||||
ok |= expctxWay.getCostfactor() < 10000.;
|
ok |= expctxWay.getCostfactor() < 10000.;
|
||||||
if ( !ok )
|
if ( !ok )
|
||||||
return;
|
return;
|
||||||
|
@ -330,8 +329,7 @@ public class WayLinker extends MapCreatorBase
|
||||||
OsmNodeP n0 = subList.get( 0 );
|
OsmNodeP n0 = subList.get( 0 );
|
||||||
int lonIdxDiv = n0.ilon / cellsize;
|
int lonIdxDiv = n0.ilon / cellsize;
|
||||||
int latIdxDiv = n0.ilat / cellsize;
|
int latIdxDiv = n0.ilat / cellsize;
|
||||||
MicroCache mc = microCacheEncoding == 0 ? new MicroCache1( size, abBuf2, lonIdxDiv, latIdxDiv ) : new MicroCache2( size, abBuf2,
|
MicroCache mc = new MicroCache2( size, abBuf2, lonIdxDiv, latIdxDiv, divisor );
|
||||||
lonIdxDiv, latIdxDiv, divisor );
|
|
||||||
|
|
||||||
// sort via treemap
|
// sort via treemap
|
||||||
TreeMap<Integer, OsmNodeP> sortedList = new TreeMap<Integer, OsmNodeP>();
|
TreeMap<Integer, OsmNodeP> sortedList = new TreeMap<Integer, OsmNodeP>();
|
||||||
|
@ -360,8 +358,7 @@ public class WayLinker extends MapCreatorBase
|
||||||
System.arraycopy( abBuf1, 0, subBytes, 0, len );
|
System.arraycopy( abBuf1, 0, subBytes, 0, len );
|
||||||
|
|
||||||
// cross-check the encoding: re-instantiate the cache
|
// cross-check the encoding: re-instantiate the cache
|
||||||
MicroCache mc2 = microCacheEncoding == 0 ? new MicroCache1( subBytes, lonIdxDiv, latIdxDiv ) : new MicroCache2( new DataBuffers(
|
MicroCache mc2 = new MicroCache2( new DataBuffers( subBytes ), lonIdxDiv, latIdxDiv, divisor, null, null );
|
||||||
subBytes ), lonIdxDiv, latIdxDiv, divisor, null, null );
|
|
||||||
// ..and check if still the same
|
// ..and check if still the same
|
||||||
String diffMessage = mc.compareWith( mc2 );
|
String diffMessage = mc.compareWith( mc2 );
|
||||||
if ( diffMessage != null )
|
if ( diffMessage != null )
|
||||||
|
|
|
@ -35,8 +35,6 @@ public final class NodesCache
|
||||||
private OsmFile[][] fileRows;
|
private OsmFile[][] fileRows;
|
||||||
private ArrayList<MicroCache> segmentList = new ArrayList<MicroCache>();
|
private ArrayList<MicroCache> segmentList = new ArrayList<MicroCache>();
|
||||||
|
|
||||||
public DistanceChecker distanceChecker;
|
|
||||||
|
|
||||||
public WaypointMatcher waypointMatcher;
|
public WaypointMatcher waypointMatcher;
|
||||||
|
|
||||||
public boolean first_file_access_failed = false;
|
public boolean first_file_access_failed = false;
|
||||||
|
@ -212,7 +210,7 @@ public final class NodesCache
|
||||||
long id = node.getIdFromPos();
|
long id = node.getIdFromPos();
|
||||||
if ( segment.getAndClear( id ) )
|
if ( segment.getAndClear( id ) )
|
||||||
{
|
{
|
||||||
node.parseNodeBody( segment, nodesMap, distanceChecker );
|
node.parseNodeBody( segment, nodesMap );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( garbageCollectionEnabled ) // garbage collection
|
if ( garbageCollectionEnabled ) // garbage collection
|
||||||
|
|
|
@ -10,7 +10,6 @@ import java.io.RandomAccessFile;
|
||||||
|
|
||||||
import btools.codec.DataBuffers;
|
import btools.codec.DataBuffers;
|
||||||
import btools.codec.MicroCache;
|
import btools.codec.MicroCache;
|
||||||
import btools.codec.MicroCache1;
|
|
||||||
import btools.codec.MicroCache2;
|
import btools.codec.MicroCache2;
|
||||||
import btools.codec.TagValueValidator;
|
import btools.codec.TagValueValidator;
|
||||||
import btools.codec.WaypointMatcher;
|
import btools.codec.WaypointMatcher;
|
||||||
|
@ -152,10 +151,6 @@ final class OsmFile
|
||||||
|
|
||||||
int crcData = Crc32.crc( ab, 0, asize - 4 );
|
int crcData = Crc32.crc( ab, 0, asize - 4 );
|
||||||
int crcFooter = new ByteDataReader( ab, asize - 4 ).readInt();
|
int crcFooter = new ByteDataReader( ab, asize - 4 ).readInt();
|
||||||
if ( crcData == crcFooter )
|
|
||||||
{
|
|
||||||
return reallyDecode ? new MicroCache1( ab, lonIdx, latIdx ) : null;
|
|
||||||
}
|
|
||||||
if ( ( crcData ^ 2 ) == crcFooter )
|
if ( ( crcData ^ 2 ) == crcFooter )
|
||||||
{
|
{
|
||||||
return reallyDecode ? new MicroCache2( dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher ) : null;
|
return reallyDecode ? new MicroCache2( dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher ) : null;
|
||||||
|
|
|
@ -26,21 +26,17 @@ public class OsmLink
|
||||||
|
|
||||||
public boolean counterLinkWritten;
|
public boolean counterLinkWritten;
|
||||||
|
|
||||||
public boolean hasNewGeometry; // preliminary
|
|
||||||
|
|
||||||
public byte state;
|
public byte state;
|
||||||
|
|
||||||
public void setGeometry( byte[] geometry )
|
public void setGeometry( byte[] geometry )
|
||||||
{
|
{
|
||||||
this.geometry = geometry;
|
this.geometry = geometry;
|
||||||
hasNewGeometry = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final public OsmTransferNode decodeFirsttransfer( OsmNode sourceNode )
|
final public OsmTransferNode decodeFirsttransfer( OsmNode sourceNode )
|
||||||
{
|
{
|
||||||
if ( geometry == null ) return null;
|
if ( geometry == null ) return null;
|
||||||
if ( hasNewGeometry )
|
|
||||||
{
|
|
||||||
OsmTransferNode firstTransferNode = null;
|
OsmTransferNode firstTransferNode = null;
|
||||||
OsmTransferNode lastTransferNode = null;
|
OsmTransferNode lastTransferNode = null;
|
||||||
OsmNode startnode = counterLinkWritten ? targetNode : sourceNode;
|
OsmNode startnode = counterLinkWritten ? targetNode : sourceNode;
|
||||||
|
@ -53,7 +49,6 @@ public class OsmLink
|
||||||
OsmTransferNode trans = new OsmTransferNode();
|
OsmTransferNode trans = new OsmTransferNode();
|
||||||
trans.ilon = olon + r.readVarLengthSigned();
|
trans.ilon = olon + r.readVarLengthSigned();
|
||||||
trans.ilat = olat + r.readVarLengthSigned();
|
trans.ilat = olat + r.readVarLengthSigned();
|
||||||
trans.descriptionBitmap = descriptionBitmap;
|
|
||||||
trans.selev = (short)(oselev + r.readVarLengthSigned());
|
trans.selev = (short)(oselev + r.readVarLengthSigned());
|
||||||
olon = trans.ilon;
|
olon = trans.ilon;
|
||||||
olat = trans.ilat;
|
olat = trans.ilat;
|
||||||
|
@ -77,14 +72,6 @@ public class OsmLink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return firstTransferNode;
|
return firstTransferNode;
|
||||||
}
|
|
||||||
return OsmTransferNode.decode( geometry );
|
|
||||||
}
|
|
||||||
|
|
||||||
final public void encodeFirsttransfer( OsmTransferNode firsttransfer )
|
|
||||||
{
|
|
||||||
if ( firsttransfer == null ) geometry = null;
|
|
||||||
else geometry = OsmTransferNode.encode( firsttransfer );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final public void addLinkHolder( OsmLinkHolder holder )
|
final public void addLinkHolder( OsmLinkHolder holder )
|
||||||
|
|
|
@ -6,22 +6,11 @@
|
||||||
package btools.mapaccess;
|
package btools.mapaccess;
|
||||||
|
|
||||||
import btools.codec.MicroCache;
|
import btools.codec.MicroCache;
|
||||||
import btools.codec.MicroCache1;
|
|
||||||
import btools.codec.MicroCache2;
|
import btools.codec.MicroCache2;
|
||||||
import btools.util.ByteArrayUnifier;
|
import btools.util.ByteArrayUnifier;
|
||||||
|
|
||||||
public class OsmNode implements OsmPos
|
public class OsmNode implements OsmPos
|
||||||
{
|
{
|
||||||
public static final int EXTERNAL_BITMASK = 0x80; // old semantic
|
|
||||||
public static final int SIGNLON_BITMASK = 0x80;
|
|
||||||
public static final int SIGNLAT_BITMASK = 0x40;
|
|
||||||
public static final int TRANSFERNODE_BITMASK = 0x20;
|
|
||||||
public static final int WRITEDESC_BITMASK = 0x10;
|
|
||||||
public static final int SKIPDETAILS_BITMASK = 0x08;
|
|
||||||
public static final int NODEDESC_BITMASK = 0x04;
|
|
||||||
public static final int RESERVED1_BITMASK = 0x02;
|
|
||||||
public static final int RESERVED2_BITMASK = 0x01;
|
|
||||||
|
|
||||||
public OsmNode()
|
public OsmNode()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -146,21 +135,17 @@ public class OsmNode implements OsmPos
|
||||||
return "" + getIdFromPos();
|
return "" + getIdFromPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parseNodeBody( MicroCache mc, OsmNodesMap hollowNodes, DistanceChecker dc )
|
public void parseNodeBody( MicroCache mc, OsmNodesMap hollowNodes )
|
||||||
{
|
{
|
||||||
if ( mc instanceof MicroCache1 )
|
if ( mc instanceof MicroCache2 )
|
||||||
{
|
{
|
||||||
parseNodeBody1( (MicroCache1) mc, hollowNodes, dc );
|
parseNodeBody2( (MicroCache2) mc, hollowNodes );
|
||||||
}
|
|
||||||
else if ( mc instanceof MicroCache2 )
|
|
||||||
{
|
|
||||||
parseNodeBody2( (MicroCache2) mc, hollowNodes, dc );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new IllegalArgumentException( "unknown cache version: " + mc.getClass() );
|
throw new IllegalArgumentException( "unknown cache version: " + mc.getClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parseNodeBody2( MicroCache2 mc, OsmNodesMap hollowNodes, DistanceChecker dc )
|
public void parseNodeBody2( MicroCache2 mc, OsmNodesMap hollowNodes )
|
||||||
{
|
{
|
||||||
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
|
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
|
||||||
|
|
||||||
|
@ -184,10 +169,6 @@ public class OsmNode implements OsmPos
|
||||||
}
|
}
|
||||||
byte[] geometry = mc.readDataUntil( endPointer );
|
byte[] geometry = mc.readDataUntil( endPointer );
|
||||||
|
|
||||||
// preliminary hack: way-point-matching not here (done at decoding time)
|
|
||||||
if ( dc != null )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( linklon == ilon && linklat == ilat )
|
if ( linklon == ilon && linklat == ilat )
|
||||||
{
|
{
|
||||||
continue; // skip self-ref
|
continue; // skip self-ref
|
||||||
|
@ -236,186 +217,10 @@ public class OsmNode implements OsmPos
|
||||||
rlink.setGeometry( geometry );
|
rlink.setGeometry( geometry );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
hollowNodes.remove( this );
|
hollowNodes.remove( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parseNodeBody1( MicroCache1 is, OsmNodesMap hollowNodes, DistanceChecker dc )
|
|
||||||
{
|
|
||||||
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
|
|
||||||
|
|
||||||
selev = is.readShort();
|
|
||||||
|
|
||||||
while (is.hasMoreData())
|
|
||||||
{
|
|
||||||
int ilonref = ilon;
|
|
||||||
int ilatref = ilat;
|
|
||||||
|
|
||||||
boolean counterLinkWritten = false;
|
|
||||||
OsmTransferNode firstTransferNode = null;
|
|
||||||
OsmTransferNode lastTransferNode = null;
|
|
||||||
int linklon;
|
|
||||||
int linklat;
|
|
||||||
byte[] description = null;
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
int bitField = is.readByte();
|
|
||||||
int dlon = is.readVarLengthUnsigned();
|
|
||||||
int dlat = is.readVarLengthUnsigned();
|
|
||||||
if ( ( bitField & SIGNLON_BITMASK ) != 0 )
|
|
||||||
{
|
|
||||||
dlon = -dlon;
|
|
||||||
}
|
|
||||||
if ( ( bitField & SIGNLAT_BITMASK ) != 0 )
|
|
||||||
{
|
|
||||||
dlat = -dlat;
|
|
||||||
}
|
|
||||||
linklon = ilonref + dlon;
|
|
||||||
linklat = ilatref + dlat;
|
|
||||||
ilonref = linklon;
|
|
||||||
ilatref = linklat;
|
|
||||||
// read variable length or old 8 byte fixed, and ensure that 8 bytes is
|
|
||||||
// only fixed
|
|
||||||
if ( ( bitField & WRITEDESC_BITMASK ) != 0 )
|
|
||||||
{
|
|
||||||
byte[] ab = new byte[is.readByte()];
|
|
||||||
is.readFully( ab );
|
|
||||||
description = abUnifier.unify( ab );
|
|
||||||
}
|
|
||||||
if ( ( bitField & NODEDESC_BITMASK ) != 0 )
|
|
||||||
{
|
|
||||||
byte[] ab = new byte[is.readByte()];
|
|
||||||
is.readFully( ab );
|
|
||||||
nodeDescription = abUnifier.unify( ab );
|
|
||||||
}
|
|
||||||
if ( ( bitField & RESERVED1_BITMASK ) != 0 )
|
|
||||||
{
|
|
||||||
byte[] ab = new byte[is.readByte()];
|
|
||||||
is.readFully( ab );
|
|
||||||
}
|
|
||||||
if ( ( bitField & RESERVED2_BITMASK ) != 0 )
|
|
||||||
{
|
|
||||||
byte[] ab = new byte[is.readByte()];
|
|
||||||
is.readFully( ab );
|
|
||||||
}
|
|
||||||
if ( ( bitField & SKIPDETAILS_BITMASK ) != 0 )
|
|
||||||
{
|
|
||||||
counterLinkWritten = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( description == null && !counterLinkWritten )
|
|
||||||
throw new IllegalArgumentException( "internal error: missing way description!" );
|
|
||||||
|
|
||||||
boolean isTransfer = ( bitField & TRANSFERNODE_BITMASK ) != 0;
|
|
||||||
if ( isTransfer )
|
|
||||||
{
|
|
||||||
OsmTransferNode trans = new OsmTransferNode();
|
|
||||||
trans.ilon = linklon;
|
|
||||||
trans.ilat = linklat;
|
|
||||||
trans.descriptionBitmap = description;
|
|
||||||
trans.selev = (short) ( selev + is.readVarLengthSigned() );
|
|
||||||
if ( lastTransferNode == null )
|
|
||||||
{
|
|
||||||
firstTransferNode = trans;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastTransferNode.next = trans;
|
|
||||||
}
|
|
||||||
lastTransferNode = trans;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// performance shortcut: ignore link if out of reach
|
|
||||||
if ( dc != null && !counterLinkWritten )
|
|
||||||
{
|
|
||||||
if ( !dc.isWithinRadius( ilon, ilat, firstTransferNode, linklon, linklat ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( linklon == ilon && linklat == ilat )
|
|
||||||
{
|
|
||||||
continue; // skip self-ref
|
|
||||||
}
|
|
||||||
|
|
||||||
// first check the known links for that target
|
|
||||||
OsmLink link = getCompatibleLink( linklon, linklat, counterLinkWritten, 2 );
|
|
||||||
if ( link == null ) // .. not found, then check the hollow nodes
|
|
||||||
{
|
|
||||||
long targetNodeId = ( (long) linklon ) << 32 | linklat;
|
|
||||||
OsmNode tn = hollowNodes.get( targetNodeId ); // target node
|
|
||||||
if ( tn == null ) // node not yet known, create a new hollow proxy
|
|
||||||
{
|
|
||||||
tn = new OsmNode( linklon, linklat );
|
|
||||||
tn.setHollow();
|
|
||||||
hollowNodes.put( tn );
|
|
||||||
}
|
|
||||||
link = new OsmLink();
|
|
||||||
link.targetNode = tn;
|
|
||||||
link.counterLinkWritten = counterLinkWritten;
|
|
||||||
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, !counterLinkWritten, 1 );
|
|
||||||
if ( rlink == null ) // .. not found, create it
|
|
||||||
{
|
|
||||||
rlink = new OsmLink();
|
|
||||||
rlink.targetNode = this;
|
|
||||||
rlink.counterLinkWritten = !counterLinkWritten;
|
|
||||||
rlink.state = 2;
|
|
||||||
link.targetNode.addLink( rlink );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !counterLinkWritten )
|
|
||||||
{
|
|
||||||
// we have the data for that link, so fill both the link ..
|
|
||||||
link.descriptionBitmap = description;
|
|
||||||
link.encodeFirsttransfer( firstTransferNode );
|
|
||||||
|
|
||||||
// .. and the reverse
|
|
||||||
if ( rlink.counterLinkWritten )
|
|
||||||
{
|
|
||||||
rlink.descriptionBitmap = description; // default for no
|
|
||||||
// transfer-nodes
|
|
||||||
OsmTransferNode previous = null;
|
|
||||||
OsmTransferNode rtrans = null;
|
|
||||||
for ( OsmTransferNode trans = firstTransferNode; trans != null; trans = trans.next )
|
|
||||||
{
|
|
||||||
if ( previous == null )
|
|
||||||
{
|
|
||||||
rlink.descriptionBitmap = trans.descriptionBitmap;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
previous.descriptionBitmap = trans.descriptionBitmap;
|
|
||||||
}
|
|
||||||
rtrans = new OsmTransferNode();
|
|
||||||
rtrans.ilon = trans.ilon;
|
|
||||||
rtrans.ilat = trans.ilat;
|
|
||||||
rtrans.selev = trans.selev;
|
|
||||||
rtrans.next = previous;
|
|
||||||
rtrans.descriptionBitmap = description;
|
|
||||||
previous = rtrans;
|
|
||||||
}
|
|
||||||
rlink.encodeFirsttransfer( rtrans );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if ( dc == null )
|
|
||||||
{
|
|
||||||
hollowNodes.remove( this );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHollow()
|
public boolean isHollow()
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,144 +5,15 @@
|
||||||
*/
|
*/
|
||||||
package btools.mapaccess;
|
package btools.mapaccess;
|
||||||
|
|
||||||
import btools.util.ByteDataReader;
|
|
||||||
import btools.util.ByteDataWriter;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public final class OsmTransferNode
|
public final class OsmTransferNode
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* The description bitmap is mainly the way description
|
|
||||||
* used to calculate the costfactor
|
|
||||||
*/
|
|
||||||
public byte[] descriptionBitmap;
|
|
||||||
|
|
||||||
public OsmTransferNode next;
|
public OsmTransferNode next;
|
||||||
|
|
||||||
public int ilon;
|
public int ilon;
|
||||||
public int ilat;
|
public int ilat;
|
||||||
public short selev;
|
public short selev;
|
||||||
|
|
||||||
private static final int BIT_DESC = 1;
|
|
||||||
private static final int BIT_ILONHIGH = 2;
|
|
||||||
private static final int BIT_ILATHIGH = 4;
|
|
||||||
private static final int BIT_STOP = 8;
|
|
||||||
|
|
||||||
// encode this transfer-node into a byte array
|
|
||||||
public static byte[] encode( OsmTransferNode tn )
|
|
||||||
{
|
|
||||||
byte[] currentDesc = null;
|
|
||||||
int currentILonHigh = 0;
|
|
||||||
int currentILatHigh = 0;
|
|
||||||
OsmTransferNode n = tn;
|
|
||||||
|
|
||||||
// first loop to calc size
|
|
||||||
int size = 1; // stop-bit
|
|
||||||
|
|
||||||
while( n != null )
|
|
||||||
{
|
|
||||||
if ( n.descriptionBitmap == null ) throw new IllegalArgumentException( "transfernode-encode: description is null" );
|
|
||||||
|
|
||||||
if( n.descriptionBitmap != currentDesc )
|
|
||||||
{
|
|
||||||
currentDesc = n.descriptionBitmap;
|
|
||||||
size += 1 + currentDesc.length;
|
|
||||||
}
|
|
||||||
if( ( n.ilon >> 16 ) != currentILonHigh )
|
|
||||||
{
|
|
||||||
size += 2;
|
|
||||||
currentILonHigh = n.ilon >> 16;
|
|
||||||
}
|
|
||||||
if( (n.ilat >> 16) != currentILatHigh )
|
|
||||||
{
|
|
||||||
size += 2;
|
|
||||||
currentILatHigh = n.ilat >> 16;
|
|
||||||
}
|
|
||||||
size += 7;
|
|
||||||
n = n.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] ab = new byte[size];
|
|
||||||
ByteDataWriter os = new ByteDataWriter( ab );
|
|
||||||
|
|
||||||
currentDesc = null;
|
|
||||||
currentILonHigh = 0;
|
|
||||||
currentILatHigh = 0;
|
|
||||||
n = tn;
|
|
||||||
while( n != null )
|
|
||||||
{
|
|
||||||
int mode = 0;
|
|
||||||
if( n.descriptionBitmap != currentDesc )
|
|
||||||
{
|
|
||||||
mode |= BIT_DESC;
|
|
||||||
currentDesc = n.descriptionBitmap;
|
|
||||||
}
|
|
||||||
if( ( n.ilon >> 16 ) != currentILonHigh )
|
|
||||||
{
|
|
||||||
mode |= BIT_ILONHIGH;
|
|
||||||
currentILonHigh = n.ilon >> 16;
|
|
||||||
}
|
|
||||||
if( (n.ilat >> 16) != currentILatHigh )
|
|
||||||
{
|
|
||||||
mode |= BIT_ILATHIGH;
|
|
||||||
currentILatHigh = n.ilat >> 16;
|
|
||||||
}
|
|
||||||
os.writeByte( mode);
|
|
||||||
if ( (mode & BIT_DESC) != 0 ) { os.writeByte( currentDesc.length ); os.write( currentDesc ); }
|
|
||||||
if ( (mode & BIT_ILONHIGH) != 0 ) os.writeShort( currentILonHigh );
|
|
||||||
if ( (mode & BIT_ILATHIGH) != 0 ) os.writeShort( currentILatHigh );
|
|
||||||
os.writeShort( n.ilon );
|
|
||||||
os.writeShort( n.ilat );
|
|
||||||
os.writeShort( n.selev );
|
|
||||||
n = n.next;
|
|
||||||
}
|
|
||||||
os.writeByte( BIT_STOP );
|
|
||||||
return ab;
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode a transfer-node from a byte array
|
|
||||||
public static OsmTransferNode decode( byte[] ab )
|
|
||||||
{
|
|
||||||
ByteDataReader is = new ByteDataReader( ab );
|
|
||||||
|
|
||||||
OsmTransferNode firstNode = null;
|
|
||||||
OsmTransferNode lastNode = null;
|
|
||||||
byte[] currentDesc = null;
|
|
||||||
int currentILonHigh = 0;
|
|
||||||
int currentILatHigh = 0;
|
|
||||||
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
byte mode = is.readByte();
|
|
||||||
if ( (mode & BIT_STOP ) != 0 ) break;
|
|
||||||
|
|
||||||
OsmTransferNode n = new OsmTransferNode();
|
|
||||||
if ( (mode & BIT_DESC) != 0 ) { int dlen = is.readByte(); currentDesc = new byte[dlen]; is.readFully( currentDesc ); }
|
|
||||||
if ( (mode & BIT_ILONHIGH) != 0 ) currentILonHigh = is.readShort();
|
|
||||||
if ( (mode & BIT_ILATHIGH) != 0 ) currentILatHigh = is.readShort();
|
|
||||||
n.descriptionBitmap = currentDesc;
|
|
||||||
if ( n.descriptionBitmap == null ) throw new IllegalArgumentException( "transfernode-decode: description is null" );
|
|
||||||
int ilon = is.readShort() & 0xffff; ilon |= currentILonHigh << 16;
|
|
||||||
int ilat = is.readShort() & 0xffff; ilat |= currentILatHigh << 16;
|
|
||||||
n.ilon = ilon;
|
|
||||||
n.ilat = ilat;
|
|
||||||
n.selev = is.readShort();
|
|
||||||
|
|
||||||
if ( ilon != n.ilon ) System.out.println( "ilon=" + ilon + " n.ilon=" + n.ilon );
|
|
||||||
if ( ilat != n.ilat ) System.out.println( "ilat=" + ilat + " n.ilat=" + n.ilat );
|
|
||||||
|
|
||||||
if ( lastNode != null )
|
|
||||||
{
|
|
||||||
lastNode.next = n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
firstNode = n;
|
|
||||||
}
|
|
||||||
lastNode = n;
|
|
||||||
}
|
|
||||||
return firstNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ public class GraphLoader extends MapCreatorBase
|
||||||
{
|
{
|
||||||
if ( link.isWayLink() )
|
if ( link.isWayLink() )
|
||||||
{
|
{
|
||||||
wayCtx.evaluate( false, link.descriptionBitmap, null );
|
wayCtx.evaluate( false, link.descriptionBitmap );
|
||||||
if ( wayCtx.getCostfactor() < 10000.f )
|
if ( wayCtx.getCostfactor() < 10000.f )
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -347,7 +347,7 @@ System.out.println( "*** finishedOffsets = " + finishedOffsets );
|
||||||
else if ( link.isWayLink() )
|
else if ( link.isWayLink() )
|
||||||
{
|
{
|
||||||
// get costfactor
|
// get costfactor
|
||||||
rc.expctxWay.evaluate( link.isReverse( currentNode ), link.descriptionBitmap, null );
|
rc.expctxWay.evaluate( link.isReverse( currentNode ), link.descriptionBitmap );
|
||||||
|
|
||||||
// *** penalty for distance
|
// *** penalty for distance
|
||||||
float costfactor = rc.expctxWay.getCostfactor();
|
float costfactor = rc.expctxWay.getCostfactor();
|
||||||
|
@ -366,7 +366,7 @@ System.out.println( "*** finishedOffsets = " + finishedOffsets );
|
||||||
|
|
||||||
if ( node.getNodeDecsription() != null )
|
if ( node.getNodeDecsription() != null )
|
||||||
{
|
{
|
||||||
rc.expctxNode.evaluate( rc.expctxWay.getNodeAccessGranted() != 0., node.getNodeDecsription(), null );
|
rc.expctxNode.evaluate( rc.expctxWay.getNodeAccessGranted() != 0., node.getNodeDecsription() );
|
||||||
float initialcost = rc.expctxNode.getInitialcost();
|
float initialcost = rc.expctxNode.getInitialcost();
|
||||||
if ( initialcost >= 1000000. )
|
if ( initialcost >= 1000000. )
|
||||||
{
|
{
|
||||||
|
|
148
brouter-util/src/main/java/btools/util/StackSampler.java
Normal file
148
brouter-util/src/main/java/btools/util/StackSampler.java
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
package btools.util;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class StackSampler extends Thread
|
||||||
|
{
|
||||||
|
private DateFormat df = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss,SSS", new Locale( "en", "US" ) );
|
||||||
|
private BufferedWriter bw;
|
||||||
|
private Random rand = new Random();
|
||||||
|
|
||||||
|
private int interval;
|
||||||
|
private int flushCnt = 0;
|
||||||
|
|
||||||
|
private volatile boolean stopped;
|
||||||
|
|
||||||
|
public StackSampler( File logfile, int interval )
|
||||||
|
{
|
||||||
|
this.interval = interval;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( logfile, true ) ) );
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
printError( "StackSampler: " + e.getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void printError( String msg )
|
||||||
|
{
|
||||||
|
System.out.println( msg );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
while( !stopped )
|
||||||
|
{
|
||||||
|
dumpThreads();
|
||||||
|
}
|
||||||
|
if ( bw != null )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bw.close();
|
||||||
|
}
|
||||||
|
catch( Exception e ) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dumpThreads()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int wait1 = rand.nextInt( interval );
|
||||||
|
int wait2 = interval - wait1;
|
||||||
|
Thread.sleep( wait1 );
|
||||||
|
StringBuilder sb = new StringBuilder( df.format( new Date() ) + " THREADDUMP\n" );
|
||||||
|
Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces();
|
||||||
|
for ( Map.Entry<Thread, StackTraceElement[]> e : allThreads.entrySet() )
|
||||||
|
{
|
||||||
|
Thread t = e.getKey();
|
||||||
|
if ( t == Thread.currentThread() )
|
||||||
|
{
|
||||||
|
continue; // not me
|
||||||
|
}
|
||||||
|
|
||||||
|
StackTraceElement[] stack = e.getValue();
|
||||||
|
if ( !matchesFilter( stack ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append( " (ID=" ).append( t.getId() ).append( " \"" ).append( t.getName() ).append( "\" " ).append( t.getState() ).append( "\n" );
|
||||||
|
for ( StackTraceElement line : stack )
|
||||||
|
{
|
||||||
|
sb.append( " " ).append( line.toString() ).append( "\n" );
|
||||||
|
}
|
||||||
|
sb.append( "\n" );
|
||||||
|
}
|
||||||
|
bw.write( sb.toString() );
|
||||||
|
if ( flushCnt++ >= 0 )
|
||||||
|
{
|
||||||
|
flushCnt = 0;
|
||||||
|
bw.flush();
|
||||||
|
}
|
||||||
|
Thread.sleep( wait2 );
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
stopped = true;
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesFilter( StackTraceElement[] stack )
|
||||||
|
{
|
||||||
|
boolean positiveMatch = false;
|
||||||
|
for ( StackTraceElement e : stack )
|
||||||
|
{
|
||||||
|
String s = e.toString();
|
||||||
|
if ( s.indexOf( "btools" ) >= 0 )
|
||||||
|
{
|
||||||
|
positiveMatch = true;
|
||||||
|
}
|
||||||
|
if ( s.indexOf( "Thread.sleep" ) >= 0 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return positiveMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main( String[] args ) throws Exception
|
||||||
|
{
|
||||||
|
System.out.println( "StackSampler..." );
|
||||||
|
Class<?> clazz = Class.forName( args[0] );
|
||||||
|
String[] args2 = new String[args.length - 1];
|
||||||
|
for ( int i = 1; i < args.length; i++ )
|
||||||
|
{
|
||||||
|
args2[i - 1] = args[i];
|
||||||
|
}
|
||||||
|
StackSampler t = new StackSampler( new File( "stacks.log" ), 1000 );
|
||||||
|
t.start();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clazz.getMethod( "main", String[].class ).invoke( null, new Object[]{ args2 } );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue