1.0 preparations

This commit is contained in:
Arndt 2014-06-19 09:15:51 +02:00
parent 55717c6e71
commit 8fa82633d4
34 changed files with 742 additions and 462 deletions

View file

@ -50,13 +50,13 @@ public final class RoutingContext implements DistanceChecker
public void readGlobalConfig( BExpressionContext expctxGlobal ) public void readGlobalConfig( BExpressionContext expctxGlobal )
{ {
downhillcostdiv = (int)expctxGlobal.getVariableValue( "downhillcost" ); downhillcostdiv = (int)expctxGlobal.getVariableValue( "downhillcost", 0.f );
downhillcutoff = (int)(expctxGlobal.getVariableValue( "downhillcutoff" )*10000); downhillcutoff = (int)(expctxGlobal.getVariableValue( "downhillcutoff", 0.f )*10000);
uphillcostdiv = (int)expctxGlobal.getVariableValue( "uphillcost" ); uphillcostdiv = (int)expctxGlobal.getVariableValue( "uphillcost", 0.f );
uphillcutoff = (int)(expctxGlobal.getVariableValue( "uphillcutoff" )*10000); uphillcutoff = (int)(expctxGlobal.getVariableValue( "uphillcutoff", 0.f )*10000);
if ( downhillcostdiv != 0 ) downhillcostdiv = 1000000/downhillcostdiv; if ( downhillcostdiv != 0 ) downhillcostdiv = 1000000/downhillcostdiv;
if ( uphillcostdiv != 0 ) uphillcostdiv = 1000000/uphillcostdiv; if ( uphillcostdiv != 0 ) uphillcostdiv = 1000000/uphillcostdiv;
carMode = 0.f != expctxGlobal.getVariableValue( "validForCars" ); carMode = 0.f != expctxGlobal.getVariableValue( "validForCars", 0.f );
pass1coefficient = expctxGlobal.getVariableValue( "pass1coefficient", 1.5f ); pass1coefficient = expctxGlobal.getVariableValue( "pass1coefficient", 1.5f );
pass2coefficient = expctxGlobal.getVariableValue( "pass2coefficient", 0.f ); pass2coefficient = expctxGlobal.getVariableValue( "pass2coefficient", 0.f );
} }

View file

@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import btools.expressions.BExpressionContext; import btools.expressions.BExpressionContext;
import btools.expressions.BExpressionMetaData;
import btools.mapaccess.NodesCache; import btools.mapaccess.NodesCache;
import btools.mapaccess.OsmLink; import btools.mapaccess.OsmLink;
import btools.mapaccess.OsmLinkHolder; import btools.mapaccess.OsmLinkHolder;
@ -70,18 +71,20 @@ public class RoutingEngine extends Thread
profileDir = new File( profileBaseDir ); profileDir = new File( profileBaseDir );
profileFile = new File( profileDir, rc.localFunction + ".brf" ) ; profileFile = new File( profileDir, rc.localFunction + ".brf" ) ;
} }
BExpressionContext expctxGlobal = new BExpressionContext( "global" );
expctxGlobal.readMetaData( new File( profileDir, "lookups.dat" ) ); BExpressionMetaData meta = new BExpressionMetaData();
BExpressionContext expctxGlobal = new BExpressionContext( "global", meta );
rc.expctxWay = new BExpressionContext( "way", meta );
rc.expctxNode = new BExpressionContext( "node", 1024, meta );
meta.readMetaData( new File( profileDir, "lookups.dat" ) );
expctxGlobal.parseFile( profileFile, null ); expctxGlobal.parseFile( profileFile, null );
expctxGlobal.evaluate( new int[0] ); expctxGlobal.evaluate( new int[0] );
rc.readGlobalConfig(expctxGlobal); rc.readGlobalConfig(expctxGlobal);
rc.expctxWay = new BExpressionContext( "way", 4096 );
rc.expctxWay.readMetaData( new File( profileDir, "lookups.dat" ) );
rc.expctxWay.parseFile( profileFile, "global" ); rc.expctxWay.parseFile( profileFile, "global" );
rc.expctxNode = new BExpressionContext( "node", 1024 );
rc.expctxNode.readMetaData( new File( profileDir, "lookups.dat" ) );
rc.expctxNode.parseFile( profileFile, "global" ); rc.expctxNode.parseFile( profileFile, "global" );
} }
} }
@ -372,7 +375,6 @@ public class RoutingEngine extends Thread
if ( matchPath != null ) if ( matchPath != null )
{ {
track = mergeTrack( matchPath, nearbyTrack ); track = mergeTrack( matchPath, nearbyTrack );
isDirty = true;
} }
maxRunningTime += System.currentTimeMillis() - startTime; // reset timeout... maxRunningTime += System.currentTimeMillis() - startTime; // reset timeout...
} }
@ -432,7 +434,8 @@ public class RoutingEngine extends Thread
private void resetCache() private void resetCache()
{ {
nodesMap = new OsmNodesMap(); nodesMap = new OsmNodesMap();
nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay.lookupVersion,routingContext.expctxWay.lookupMinorVersion, routingContext.carMode, nodesCache ); BExpressionContext ctx = routingContext.expctxWay;
nodesCache = new NodesCache(segmentDir, nodesMap, ctx.meta.lookupVersion, ctx.meta.lookupMinorVersion, ctx.meta.readVarLength, routingContext.carMode, nodesCache );
} }
private OsmNode getStartNode( long startId ) private OsmNode getStartNode( long startId )
@ -566,11 +569,13 @@ public class RoutingEngine extends Thread
} }
} }
private OsmTrack findTrack( String operationName, MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack costCuttingTrack, OsmTrack refTrack, boolean reducedTimeoutWhenUnmatched ) private OsmTrack findTrack( String operationName, MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack costCuttingTrack, OsmTrack refTrack, boolean fastPartialRecalc )
{ {
boolean verbose = guideTrack != null; boolean verbose = guideTrack != null;
int maxTotalCost = 1000000000; int maxTotalCost = 1000000000;
int firstMatchCost = 1000000000;
int firstEstimate = 1000000000;
logInfo( "findtrack with maxTotalCost=" + maxTotalCost + " airDistanceCostFactor=" + airDistanceCostFactor ); logInfo( "findtrack with maxTotalCost=" + maxTotalCost + " airDistanceCostFactor=" + airDistanceCostFactor );
@ -607,7 +612,7 @@ public class RoutingEngine extends Thread
{ {
if ( maxRunningTime > 0 ) if ( maxRunningTime > 0 )
{ {
long timeout = ( matchPath == null && reducedTimeoutWhenUnmatched ) ? maxRunningTime/3 : maxRunningTime; long timeout = ( matchPath == null && fastPartialRecalc ) ? maxRunningTime/3 : maxRunningTime;
if ( System.currentTimeMillis() - startTime > timeout ) if ( System.currentTimeMillis() - startTime > timeout )
{ {
throw new IllegalArgumentException( operationName + " timeout after " + (timeout/1000) + " seconds" ); throw new IllegalArgumentException( operationName + " timeout after " + (timeout/1000) + " seconds" );
@ -627,6 +632,11 @@ public class RoutingEngine extends Thread
} }
maxAdjCostFromQueue = path.adjustedCost; maxAdjCostFromQueue = path.adjustedCost;
if ( matchPath != null && fastPartialRecalc && firstMatchCost < 500 && path.cost > 30L*firstMatchCost )
{
throw new IllegalArgumentException( "early exit for a close recalc" );
}
nodesVisited++; nodesVisited++;
linksProcessed++; linksProcessed++;
@ -645,6 +655,32 @@ public class RoutingEngine extends Thread
logInfo( "found track at cost " + path.cost + " nodesVisited = " + nodesVisited ); logInfo( "found track at cost " + path.cost + " nodesVisited = " + nodesVisited );
return compileTrack( path, verbose ); return compileTrack( path, verbose );
} }
// check for a match with the cost-cutting-track
if ( costCuttingTrack != null )
{
OsmPathElement pe = costCuttingTrack.getLink( sourceNodeId, currentNodeId );
if ( pe != null )
{
// remember first match cost for fast termination of partial recalcs
int parentcost = path.originElement == null ? 0 : path.originElement.cost;
if ( parentcost < firstMatchCost ) firstMatchCost = parentcost;
int costEstimate = path.cost
+ path.elevationCorrection( routingContext )
+ ( costCuttingTrack.cost - pe.cost );
if ( costEstimate <= maxTotalCost )
{
if ( matchPath == null ) firstEstimate = costEstimate;
matchPath = new OsmPathElement( path );
}
if ( costEstimate < maxTotalCost )
{
logInfo( "maxcost " + maxTotalCost + " -> " + costEstimate );
maxTotalCost = costEstimate;
}
}
}
} }
// recheck cutoff before doing expensive stuff // recheck cutoff before doing expensive stuff
@ -743,27 +779,6 @@ public class RoutingEngine extends Thread
int airDistance = isFinalLink ? 0 : nextNode.calcDistance( endPos ); int airDistance = isFinalLink ? 0 : nextNode.calcDistance( endPos );
bestPath.setAirDistanceCostAdjustment( (int)( airDistance * airDistanceCostFactor ) ); bestPath.setAirDistanceCostAdjustment( (int)( airDistance * airDistanceCostFactor ) );
// check for a match with the cost-cutting-track
if ( costCuttingTrack != null )
{
OsmPathElement pe = costCuttingTrack.getLink( currentNodeId, targetNodeId );
if ( pe != null )
{
int costEstimate = bestPath.cost
+ bestPath.elevationCorrection( routingContext )
+ ( costCuttingTrack.cost - pe.cost );
if ( costEstimate <= maxTotalCost )
{
matchPath = new OsmPathElement( bestPath );
}
if ( costEstimate < maxTotalCost )
{
logInfo( "maxcost " + maxTotalCost + " -> " + costEstimate + " airDistance=" + airDistance );
maxTotalCost = costEstimate;
}
}
}
if ( isFinalLink || bestPath.cost + airDistance <= maxTotalCost + 10 ) if ( isFinalLink || bestPath.cost + airDistance <= maxTotalCost + 10 )
{ {
// add only if this may beat an existing path for that link // add only if this may beat an existing path for that link

View file

@ -24,9 +24,6 @@ import btools.util.Crc32;
public final class BExpressionContext public final class BExpressionContext
{ {
private static final String CONTEXT_TAG = "---context:"; private static final String CONTEXT_TAG = "---context:";
private static final String VERSION_TAG = "---lookupversion:";
private static final String MINOR_VERSION_TAG = "---minorversion:";
private static final String VARLENGTH_TAG = "---readvarlength";
private String context; private String context;
private boolean _inOurContext = false; private boolean _inOurContext = false;
@ -55,7 +52,6 @@ public final class BExpressionContext
private byte[][] _arrayBitmap; private byte[][] _arrayBitmap;
private int currentHashBucket = -1; private int currentHashBucket = -1;
private byte[] currentByteArray = null; private byte[] currentByteArray = null;
private boolean currentInversion = false;
public List<BExpression> expressionList; public List<BExpression> expressionList;
@ -79,13 +75,12 @@ public final class BExpressionContext
private int linenr; private int linenr;
public short lookupVersion = -1; public BExpressionMetaData meta;
public short lookupMinorVersion = -1; private boolean lookupDataValid = false;
public boolean readVarLength = false;
public BExpressionContext( String context ) public BExpressionContext( String context, BExpressionMetaData meta )
{ {
this( context, 4096 ); this( context, 4096, meta );
} }
/** /**
@ -94,9 +89,15 @@ public final class BExpressionContext
* @param context global, way or node - context of that instance * @param context global, way or node - context of that instance
* @param hashSize size of hashmap for result caching * @param hashSize size of hashmap for result caching
*/ */
public BExpressionContext( String context, int hashSize ) public BExpressionContext( String context, int hashSize, BExpressionMetaData meta )
{ {
this.context = context; this.context = context;
this.meta = meta;
meta.registerListener(context, this );
if ( Boolean.getBoolean( "disableExpressionCache" ) ) hashSize = 1;
_arrayBitmap = new byte[hashSize][]; _arrayBitmap = new byte[hashSize][];
_arrayCostfactor = new float[hashSize]; _arrayCostfactor = new float[hashSize];
@ -105,18 +106,18 @@ public final class BExpressionContext
_arrayNodeAccessGranted = new float[hashSize]; _arrayNodeAccessGranted = new float[hashSize];
} }
/** /**
* encode internal lookup data to a byte array * encode internal lookup data to a byte array
*/ */
public byte[] encode() public byte[] encode()
{ {
if ( !lookupDataValid ) throw new IllegalArgumentException( "internal error: encoding undefined data?" );
return encode( lookupData ); return encode( lookupData );
} }
public byte[] encode( int[] ld ) public byte[] encode( int[] ld )
{ {
if ( !readVarLength ) return encodeFix( ld ); if ( !meta.readVarLength ) return encodeFix( ld );
// start with first bit hardwired ("reversedirection") // start with first bit hardwired ("reversedirection")
BitCoderContext ctx = new BitCoderContext( abBuf ); BitCoderContext ctx = new BitCoderContext( abBuf );
@ -134,16 +135,16 @@ public final class BExpressionContext
skippedTags++; skippedTags++;
continue; continue;
} }
ctx.encodeDistance( skippedTags+1 ); ctx.encodeVarBits( skippedTags+1 );
nonNullTags++; nonNullTags++;
skippedTags = 0; skippedTags = 0;
// 0 excluded already, 1 (=unknown) we rotate up to 8 // 0 excluded already, 1 (=unknown) we rotate up to 8
// to have the good code space for the popular values // to have the good code space for the popular values
int dd = d < 2 ? 7 : ( d < 9 ? d - 2 : d - 1); int dd = d < 2 ? 7 : ( d < 9 ? d - 2 : d - 1);
ctx.encodeDistance( dd ); ctx.encodeVarBits( dd );
} }
ctx.encodeDistance( 0 ); ctx.encodeVarBits( 0 );
if ( nonNullTags == 0) return null; if ( nonNullTags == 0) return null;
@ -200,6 +201,7 @@ public final class BExpressionContext
public void decode( byte[] ab ) public void decode( byte[] ab )
{ {
decode( lookupData, ab ); decode( lookupData, ab );
lookupDataValid = true;
} }
/** /**
@ -207,7 +209,7 @@ public final class BExpressionContext
*/ */
public void decode( int[] ld, byte[] ab ) public void decode( int[] ld, byte[] ab )
{ {
if ( !readVarLength ) { decodeFix( ld, ab ); return; } if ( !meta.readVarLength ) { decodeFix( ld, ab ); return; }
BitCoderContext ctx = new BitCoderContext(ab); BitCoderContext ctx = new BitCoderContext(ab);
@ -218,14 +220,14 @@ public final class BExpressionContext
int inum = 1; int inum = 1;
for(;;) for(;;)
{ {
int delta = ctx.decodeDistance(); int delta = ctx.decodeVarBits();
if ( delta == 0) break; if ( delta == 0) break;
if ( inum + delta > ld.length ) break; // higher minor version is o.k. if ( inum + delta > ld.length ) break; // higher minor version is o.k.
while ( delta-- > 1 ) ld[inum++] = 0; while ( delta-- > 1 ) ld[inum++] = 0;
// see encoder for value rotation // see encoder for value rotation
int dd = ctx.decodeDistance(); int dd = ctx.decodeVarBits();
int d = dd == 7 ? 1 : ( dd < 7 ? dd + 2 : dd + 1); int d = dd == 7 ? 1 : ( dd < 7 ? dd + 2 : dd + 1);
if ( d >= lookupValues.get(inum).length ) d = 1; // map out-of-range to unknown if ( d >= lookupValues.get(inum).length ) d = 1; // map out-of-range to unknown
ld[inum++] = d; ld[inum++] = d;
@ -265,7 +267,7 @@ public final class BExpressionContext
public String getCsvDescription( boolean inverseDirection, byte[] ab ) public String getCsvDescription( boolean inverseDirection, byte[] ab )
{ {
int inverseBitByteIndex = readVarLength ? 0 : 7; int inverseBitByteIndex = meta.readVarLength ? 0 : 7;
int abLen = ab.length; int abLen = ab.length;
byte[] ab_copy = new byte[abLen]; byte[] ab_copy = new byte[abLen];
System.arraycopy( ab, 0, ab_copy, 0 , abLen ); System.arraycopy( ab, 0, ab_copy, 0 , abLen );
@ -275,8 +277,10 @@ public final class BExpressionContext
decode( lookupData, ab_copy ); decode( lookupData, ab_copy );
for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names
{ {
BExpressionLookupValue[] va = lookupValues.get(inum); int idx = meta.readVarLength ? (inum+1)%lookupValues.size() : inum; // reversebit at the end..
sb.append( '\t' ).append( va[lookupData[inum]].toString() );
BExpressionLookupValue[] va = lookupValues.get(idx);
sb.append( '\t' ).append( va[lookupData[idx]].toString() );
} }
return sb.toString(); return sb.toString();
} }
@ -284,9 +288,10 @@ public final class BExpressionContext
public String getCsvHeader() public String getCsvHeader()
{ {
StringBuilder sb = new StringBuilder( 200 ); StringBuilder sb = new StringBuilder( 200 );
for( String name: lookupNames ) for( int inum = 0; inum < lookupNames.size(); inum++ ) // loop over lookup names
{ {
sb.append( '\t' ).append( name ); int idx = meta.readVarLength ? (inum+1)%lookupValues.size() : inum; // reversebit at the end..
sb.append( '\t' ).append( lookupNames.get(idx) );
} }
return sb.toString(); return sb.toString();
} }
@ -307,42 +312,11 @@ public final class BExpressionContext
return sb.toString(); return sb.toString();
} }
public void readMetaData( File lookupsFile ) private int parsedLines = 0;
{ private boolean fixTagsWritten = false;
try
{
BufferedReader br = new BufferedReader( new FileReader( lookupsFile ) );
int parsedLines = 0; public void parseMetaLine( String line )
boolean ourContext = false;
boolean fixTagsWritten = false;
for(;;)
{ {
String line = br.readLine();
if ( line == null ) break;
line = line.trim();
if ( line.length() == 0 || line.startsWith( "#" ) ) continue;
if ( line.startsWith( CONTEXT_TAG ) )
{
ourContext = line.substring( CONTEXT_TAG.length() ).equals( context );
continue;
}
if ( line.startsWith( VERSION_TAG ) )
{
lookupVersion = Short.parseShort( line.substring( VERSION_TAG.length() ) );
continue;
}
if ( line.startsWith( MINOR_VERSION_TAG ) )
{
lookupMinorVersion = Short.parseShort( line.substring( MINOR_VERSION_TAG.length() ) );
continue;
}
if ( line.startsWith( VARLENGTH_TAG ) )
{
readVarLength = true;
continue;
}
if ( !ourContext ) continue;
parsedLines++; parsedLines++;
StringTokenizer tk = new StringTokenizer( line, " " ); StringTokenizer tk = new StringTokenizer( line, " " );
String name = tk.nextToken(); String name = tk.nextToken();
@ -350,7 +324,7 @@ public final class BExpressionContext
int idx = name.indexOf( ';' ); int idx = name.indexOf( ';' );
if ( idx >= 0 ) name = name.substring( 0, idx ); if ( idx >= 0 ) name = name.substring( 0, idx );
if ( readVarLength ) if ( meta.readVarLength )
{ {
if ( !fixTagsWritten ) if ( !fixTagsWritten )
{ {
@ -358,29 +332,25 @@ public final class BExpressionContext
if ( "way".equals( context ) ) addLookupValue( "reversedirection", "yes", null ); if ( "way".equals( context ) ) addLookupValue( "reversedirection", "yes", null );
else if ( "node".equals( context ) ) addLookupValue( "nodeaccessgranted", "yes", null ); else if ( "node".equals( context ) ) addLookupValue( "nodeaccessgranted", "yes", null );
} }
if ( "reversedirection".equals( name ) ) continue; // this is hardcoded if ( "reversedirection".equals( name ) ) return; // this is hardcoded
if ( "nodeaccessgranted".equals( name ) ) continue; // this is hardcoded if ( "nodeaccessgranted".equals( name ) ) return; // this is hardcoded
} }
BExpressionLookupValue newValue = addLookupValue( name, value, null ); BExpressionLookupValue newValue = addLookupValue( name, value, null );
// add aliases // add aliases
while( newValue != null && tk.hasMoreTokens() ) newValue.addAlias( tk.nextToken() ); while( newValue != null && tk.hasMoreTokens() ) newValue.addAlias( tk.nextToken() );
} }
br.close();
public void finishMetaParsing()
{
if ( parsedLines == 0 && !"global".equals(context) ) if ( parsedLines == 0 && !"global".equals(context) )
{ {
throw new IllegalArgumentException( lookupsFile.getAbsolutePath() throw new IllegalArgumentException( "lookup table does not contain data for context " + context + " (old version?)" );
+ " does not contain data for context " + context + " (old version?)" );
} }
// post-process metadata: // post-process metadata:
lookupDataFrozen = true; lookupDataFrozen = true;
} }
catch( Exception e )
{
throw new RuntimeException( e );
}
}
public void evaluate( int[] lookupData2 ) public void evaluate( int[] lookupData2 )
{ {
@ -400,7 +370,9 @@ public final class BExpressionContext
*/ */
public boolean evaluate( boolean inverseDirection, byte[] ab, BExpressionReceiver receiver ) public boolean evaluate( boolean inverseDirection, byte[] ab, BExpressionReceiver receiver )
{ {
int inverseBitByteIndex = readVarLength ? 0 : 7; lookupDataValid = false; // this is an assertion for a nasty pifall
int inverseBitByteIndex = meta.readVarLength ? 0 : 7;
int abLen = ab.length; int abLen = ab.length;
boolean equalsCurrent = currentHashBucket >= 0 && abLen == currentByteArray.length; boolean equalsCurrent = currentHashBucket >= 0 && abLen == currentByteArray.length;
@ -685,18 +657,12 @@ public final class BExpressionContext
return num == null ? defaultValue : getVariableValue( num.intValue() ); return num == null ? defaultValue : getVariableValue( num.intValue() );
} }
public float getVariableValue( String name ) float getVariableValue( int variableIdx )
{
Integer num = variableNumbers.get( name );
return num == null ? 0.f : getVariableValue( num.intValue() );
}
public float getVariableValue( int variableIdx )
{ {
return variableData[variableIdx]; return variableData[variableIdx];
} }
public int getVariableIdx( String name, boolean create ) int getVariableIdx( String name, boolean create )
{ {
Integer num = variableNumbers.get( name ); Integer num = variableNumbers.get( name );
if ( num == null ) if ( num == null )
@ -714,12 +680,12 @@ public final class BExpressionContext
return num.intValue(); return num.intValue();
} }
public int getMinWriteIdx() int getMinWriteIdx()
{ {
return minWriteIdx; return minWriteIdx;
} }
public float getLookupMatch( int nameIdx, int valueIdx ) float getLookupMatch( int nameIdx, int valueIdx )
{ {
return lookupData[nameIdx] == valueIdx ? 1.0f : 0.0f; return lookupData[nameIdx] == valueIdx ? 1.0f : 0.0f;
} }
@ -730,7 +696,7 @@ public final class BExpressionContext
return num == null ? -1 : num.intValue(); return num == null ? -1 : num.intValue();
} }
public int getLookupValueIdx( int nameIdx, String value ) int getLookupValueIdx( int nameIdx, String value )
{ {
BExpressionLookupValue[] values = lookupValues.get( nameIdx ); BExpressionLookupValue[] values = lookupValues.get( nameIdx );
for( int i=0; i< values.length; i++ ) for( int i=0; i< values.length; i++ )
@ -741,7 +707,7 @@ public final class BExpressionContext
} }
public String parseToken() throws Exception String parseToken() throws Exception
{ {
for(;;) for(;;)
{ {
@ -790,13 +756,13 @@ public final class BExpressionContext
} }
} }
public float assign( int variableIdx, float value ) float assign( int variableIdx, float value )
{ {
variableData[variableIdx] = value; variableData[variableIdx] = value;
return value; return value;
} }
public void expressionWarning( String message ) void expressionWarning( String message )
{ {
_arrayBitmap[currentHashBucket] = null; // no caching if warnings _arrayBitmap[currentHashBucket] = null; // no caching if warnings
if ( _receiver != null ) _receiver.expressionWarning( context, message ); if ( _receiver != null ) _receiver.expressionWarning( context, message );

View file

@ -0,0 +1,91 @@
// context for simple expression
// context means:
// - the local variables
// - the local variable names
// - the lookup-input variables
package btools.expressions;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import btools.util.BitCoderContext;
import btools.util.Crc32;
public final class BExpressionMetaData
{
private static final String CONTEXT_TAG = "---context:";
private static final String VERSION_TAG = "---lookupversion:";
private static final String MINOR_VERSION_TAG = "---minorversion:";
private static final String VARLENGTH_TAG = "---readvarlength";
public short lookupVersion = -1;
public short lookupMinorVersion = -1;
public boolean readVarLength = false;
private HashMap<String,BExpressionContext> listeners = new HashMap<String,BExpressionContext>();
public void registerListener( String context, BExpressionContext ctx )
{
listeners.put( context, ctx );
}
public void readMetaData( File lookupsFile )
{
try
{
BufferedReader br = new BufferedReader( new FileReader( lookupsFile ) );
BExpressionContext ctx = null;
for(;;)
{
String line = br.readLine();
if ( line == null ) break;
line = line.trim();
if ( line.length() == 0 || line.startsWith( "#" ) ) continue;
if ( line.startsWith( CONTEXT_TAG ) )
{
ctx = listeners.get( line.substring( CONTEXT_TAG.length() ) );
continue;
}
if ( line.startsWith( VERSION_TAG ) )
{
lookupVersion = Short.parseShort( line.substring( VERSION_TAG.length() ) );
continue;
}
if ( line.startsWith( MINOR_VERSION_TAG ) )
{
lookupMinorVersion = Short.parseShort( line.substring( MINOR_VERSION_TAG.length() ) );
continue;
}
if ( line.startsWith( VARLENGTH_TAG ) )
{
readVarLength = true;
continue;
}
if ( ctx != null ) ctx.parseMetaLine( line );
}
br.close();
for( BExpressionContext c : listeners.values() )
{
c.finishMetaParsing();
}
}
catch( Exception e )
{
throw new RuntimeException( e );
}
}
}

View file

@ -18,8 +18,9 @@ public class EncodeDecodeTest
File lookupFile = new File( profileDir, "lookups.dat" ); File lookupFile = new File( profileDir, "lookups.dat" );
// read lookup.dat + trekking.brf // read lookup.dat + trekking.brf
BExpressionContext expctxWay = new BExpressionContext("way"); BExpressionMetaData meta = new BExpressionMetaData();
expctxWay.readMetaData( lookupFile ); BExpressionContext expctxWay = new BExpressionContext("way", 4096, meta );
meta.readMetaData( lookupFile );
expctxWay.parseFile( new File( profileDir, "trekking.brf" ), "global" ); expctxWay.parseFile( new File( profileDir, "trekking.brf" ), "global" );
String[] tags = { "highway=residential", "oneway=yes", "reversedirection=yes" }; String[] tags = { "highway=residential", "oneway=yes", "reversedirection=yes" };

View file

@ -15,9 +15,11 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import btools.util.DiffCoderDataOutputStream;
public abstract class MapCreatorBase implements WayListener, NodeListener, RelationListener public abstract class MapCreatorBase implements WayListener, NodeListener, RelationListener
{ {
private DataOutputStream[] tileOutStreams; private DiffCoderDataOutputStream[] tileOutStreams;
protected File outTileDir; protected File outTileDir;
protected HashMap<String,String> tags; protected HashMap<String,String> tags;
@ -102,16 +104,16 @@ public abstract class MapCreatorBase implements WayListener, NodeListener, Relat
return new DataInputStream( new BufferedInputStream ( new FileInputStream( inFile ) ) ); return new DataInputStream( new BufferedInputStream ( new FileInputStream( inFile ) ) );
} }
protected DataOutputStream createOutStream( File outFile ) throws IOException protected DiffCoderDataOutputStream createOutStream( File outFile ) throws IOException
{ {
return new DataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) ); return new DiffCoderDataOutputStream( new BufferedOutputStream( new FileOutputStream( outFile ) ) );
} }
protected DataOutputStream getOutStreamForTile( int tileIndex ) throws Exception protected DiffCoderDataOutputStream getOutStreamForTile( int tileIndex ) throws Exception
{ {
if ( tileOutStreams == null ) if ( tileOutStreams == null )
{ {
tileOutStreams = new DataOutputStream[64]; tileOutStreams = new DiffCoderDataOutputStream[64];
} }
if ( tileOutStreams[tileIndex] == null ) if ( tileOutStreams[tileIndex] == null )

View file

@ -1,7 +1,7 @@
package btools.mapcreator; package btools.mapcreator;
import java.io.DataInputStream; import btools.util.DiffCoderDataInputStream;
import java.io.DataOutputStream; import btools.util.DiffCoderDataOutputStream;
/** /**
* Container for node data on the preprocessor level * Container for node data on the preprocessor level
@ -23,21 +23,21 @@ public class NodeData extends MapCreatorBase
ilon = (int)( ( lon + 180. )*1000000. + 0.5); ilon = (int)( ( lon + 180. )*1000000. + 0.5);
} }
public NodeData( DataInputStream dis ) throws Exception public NodeData( DiffCoderDataInputStream dis ) throws Exception
{ {
nid = readId( dis ); nid = dis.readDiffed( 0 );
ilon = dis.readInt(); ilon = (int)dis.readDiffed( 1 );
ilat = dis.readInt(); ilat = (int)dis.readDiffed( 2 );
int mode = dis.readByte(); int mode = dis.readByte();
if ( ( mode & 1 ) != 0 ) { int dlen = dis.readByte(); description = new byte[dlen]; dis.readFully( description ); } if ( ( mode & 1 ) != 0 ) { int dlen = dis.readByte(); description = new byte[dlen]; dis.readFully( description ); }
if ( ( mode & 2 ) != 0 ) selev = dis.readShort(); if ( ( mode & 2 ) != 0 ) selev = dis.readShort();
} }
public void writeTo( DataOutputStream dos ) throws Exception public void writeTo( DiffCoderDataOutputStream dos ) throws Exception
{ {
writeId( dos, nid ); dos.writeDiffed( nid, 0 );
dos.writeInt( ilon ); dos.writeDiffed( ilon, 1 );
dos.writeInt( ilat ); dos.writeDiffed( ilat, 2 );
int mode = ( description == null ? 0 : 1 ) | ( selev == Short.MIN_VALUE ? 0 : 2 ); int mode = ( description == null ? 0 : 1 ) | ( selev == Short.MIN_VALUE ? 0 : 2 );
dos.writeByte( (byte)mode ); dos.writeByte( (byte)mode );
if ( ( mode & 1 ) != 0 ) { dos.writeByte( description.length ); dos.write( description ); } if ( ( mode & 1 ) != 0 ) { dos.writeByte( description.length ); dos.write( description ); }

View file

@ -1,11 +1,11 @@
package btools.mapcreator; package btools.mapcreator;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import btools.util.DenseLongMap; import btools.util.DenseLongMap;
import btools.util.DiffCoderDataOutputStream;
import btools.util.TinyDenseLongMap; import btools.util.TinyDenseLongMap;
/** /**
@ -17,7 +17,7 @@ import btools.util.TinyDenseLongMap;
*/ */
public class NodeFilter extends MapCreatorBase public class NodeFilter extends MapCreatorBase
{ {
private DataOutputStream nodesOutStream; private DiffCoderDataOutputStream nodesOutStream;
private File nodeTilesOut; private File nodeTilesOut;
protected DenseLongMap nodebitmap; protected DenseLongMap nodebitmap;
@ -61,7 +61,7 @@ public class NodeFilter extends MapCreatorBase
String filename = nodefile.getName(); String filename = nodefile.getName();
filename = filename.substring( 0, filename.length() - 3 ) + "tlf"; filename = filename.substring( 0, filename.length() - 3 ) + "tlf";
File outfile = new File( nodeTilesOut, filename ); File outfile = new File( nodeTilesOut, filename );
nodesOutStream = new DataOutputStream( new BufferedOutputStream ( new FileOutputStream( outfile ) ) ); nodesOutStream = new DiffCoderDataOutputStream( new BufferedOutputStream ( new FileOutputStream( outfile ) ) );
} }
@Override @Override

View file

@ -1,11 +1,12 @@
package btools.mapcreator; package btools.mapcreator;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import btools.util.DiffCoderDataInputStream;
/** /**
* Iterate over a singe nodefile or a directory * Iterate over a singe nodefile or a directory
* of nodetiles and feed the nodes to the callback listener * of nodetiles and feed the nodes to the callback listener
@ -48,7 +49,7 @@ public class NodeIterator extends MapCreatorBase
listener.nodeFileStart( nodefile ); listener.nodeFileStart( nodefile );
DataInputStream di = new DataInputStream( new BufferedInputStream ( new FileInputStream( nodefile ) ) ); DiffCoderDataInputStream di = new DiffCoderDataInputStream( new BufferedInputStream ( new FileInputStream( nodefile ) ) );
try try
{ {
for(;;) for(;;)

View file

@ -13,6 +13,7 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import btools.expressions.BExpressionContext; import btools.expressions.BExpressionContext;
import btools.expressions.BExpressionMetaData;
public class OsmCutter extends MapCreatorBase public class OsmCutter extends MapCreatorBase
{ {
@ -47,7 +48,7 @@ public class OsmCutter extends MapCreatorBase
private BExpressionContext _expctxNode; private BExpressionContext _expctxNode;
private BExpressionContext _expctxWayStat; private BExpressionContext _expctxWayStat;
private BExpressionContext _expctxNodeStat; // private BExpressionContext _expctxNodeStat;
public void process (File lookupFile, File outTileDir, File wayFile, File relFile, File mapFile) throws Exception public void process (File lookupFile, File outTileDir, File wayFile, File relFile, File mapFile) throws Exception
{ {
@ -56,13 +57,13 @@ public class OsmCutter extends MapCreatorBase
throw new IllegalArgumentException( "lookup-file: " + lookupFile + " does not exist" ); throw new IllegalArgumentException( "lookup-file: " + lookupFile + " does not exist" );
} }
_expctxWay = new BExpressionContext("way"); BExpressionMetaData meta = new BExpressionMetaData();
_expctxWay.readMetaData( lookupFile );
// _expctxWayStat = new BExpressionContext("way");
_expctxNode = new BExpressionContext("node"); _expctxWay = new BExpressionContext("way", meta );
_expctxNode.readMetaData( lookupFile ); _expctxNode = new BExpressionContext("node", meta );
// _expctxNodeStat = new BExpressionContext("node"); meta.readMetaData( lookupFile );
// _expctxWayStat = new BExpressionContext("way", null );
// _expctxNodeStat = new BExpressionContext("node", null );
this.outTileDir = outTileDir; this.outTileDir = outTileDir;
if ( !outTileDir.isDirectory() ) throw new RuntimeException( "out tile directory " + outTileDir + " does not exist" ); if ( !outTileDir.isDirectory() ) throw new RuntimeException( "out tile directory " + outTileDir + " does not exist" );
@ -122,8 +123,7 @@ public class OsmCutter extends MapCreatorBase
int tileIndex = getTileIndex( n.ilon, n.ilat ); int tileIndex = getTileIndex( n.ilon, n.ilat );
if ( tileIndex >= 0 ) if ( tileIndex >= 0 )
{ {
DataOutputStream dos = getOutStreamForTile( tileIndex ); n.writeTo( getOutStreamForTile( tileIndex ) );
n.writeTo( dos );
} }
} }

View file

@ -9,10 +9,14 @@ import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import sun.security.pkcs.SigningCertificateInfo;
import btools.util.ByteDataWriter;
public class OsmNodeP implements Comparable<OsmNodeP> public class OsmNodeP implements Comparable<OsmNodeP>
{ {
public static final int EXTERNAL_BITMASK = 0x80; public static final int SIGNLON_BITMASK = 0x80;
public static final int VARIABLEDESC_BITMASK = 0x40; public static final int SIGNLAT_BITMASK = 0x40;
public static final int TRANSFERNODE_BITMASK = 0x20; public static final int TRANSFERNODE_BITMASK = 0x20;
public static final int WRITEDESC_BITMASK = 0x10; public static final int WRITEDESC_BITMASK = 0x10;
public static final int SKIPDETAILS_BITMASK = 0x08; public static final int SKIPDETAILS_BITMASK = 0x08;
@ -42,10 +46,12 @@ public class OsmNodeP implements Comparable<OsmNodeP>
public boolean isBorder = false; public boolean isBorder = false;
public final static int BRIDGE_AND_BIT = 1; public final static int NO_BRIDGE_BIT = 1;
public final static int TUNNEL_AND_BIT = 2; public final static int NO_TUNNEL_BIT = 2;
public byte wayAndBits = -1; // use for bridge/tunnel logic public final static int LCN_BIT = 4;
public final static int CR_BIT = 8;
public byte wayBits = 0;
// interface OsmPos // interface OsmPos
public int getILat() public int getILat()
@ -61,7 +67,7 @@ public class OsmNodeP implements Comparable<OsmNodeP>
public short getSElev() public short getSElev()
{ {
// if all bridge or all tunnel, elevation=no-data // if all bridge or all tunnel, elevation=no-data
return (wayAndBits & ( BRIDGE_AND_BIT | TUNNEL_AND_BIT ) ) == 0 ? selev : Short.MIN_VALUE; return ( wayBits & NO_BRIDGE_BIT ) == 0 || ( wayBits & NO_TUNNEL_BIT ) == 0 ? Short.MIN_VALUE : selev;
} }
public double getElev() public double getElev()
@ -82,15 +88,13 @@ public class OsmNodeP implements Comparable<OsmNodeP>
return null; return null;
} }
public void writeNodeData( DataOutputStream os, boolean writeVarLength ) throws IOException public void writeNodeData( ByteDataWriter os, boolean writeVarLength, byte[] abBuf ) throws IOException
{ {
int lonIdx = ilon/62500; int lonIdx = ilon/62500;
int latIdx = ilat/62500; int latIdx = ilat/62500;
// buffer the body to first calc size // buffer the body to first calc size
ByteArrayOutputStream bos = new ByteArrayOutputStream( ); ByteDataWriter os2 = new ByteDataWriter( abBuf );
DataOutputStream os2 = new DataOutputStream( bos );
os2.writeShort( getSElev() ); os2.writeShort( getSElev() );
// hack: write node-desc as link tag (copy cycleway-bits) // hack: write node-desc as link tag (copy cycleway-bits)
@ -98,6 +102,9 @@ public class OsmNodeP implements Comparable<OsmNodeP>
for( OsmLinkP link0 = firstlink; link0 != null; link0 = link0.next ) for( OsmLinkP link0 = firstlink; link0 != null; link0 = link0.next )
{ {
int ilonref = ilon;
int ilatref = ilat;
OsmLinkP link = link0; OsmLinkP link = link0;
OsmNodeP origin = this; OsmNodeP origin = this;
int skipDetailBit = link0.counterLinkWritten() ? SKIPDETAILS_BITMASK : 0; int skipDetailBit = link0.counterLinkWritten() ? SKIPDETAILS_BITMASK : 0;
@ -160,32 +167,24 @@ public class OsmNodeP implements Comparable<OsmNodeP>
} }
} }
int targetLonIdx = target.ilon/62500;
int targetLatIdx = target.ilat/62500;
int bm = tranferbit | writedescbit | nodedescbit | skipDetailBit; int bm = tranferbit | writedescbit | nodedescbit | skipDetailBit;
if ( writeVarLength ) bm |= VARIABLEDESC_BITMASK; int dlon = target.ilon - ilonref;
int dlat = target.ilat - ilatref;
if ( targetLonIdx == lonIdx && targetLatIdx == latIdx ) ilonref = target.ilon;
{ ilatref = target.ilat;
// reduced position for internal target if ( dlon < 0 ) { bm |= SIGNLON_BITMASK; dlon = - dlon; }
if ( dlat < 0 ) { bm |= SIGNLAT_BITMASK; dlat = - dlat; }
os2.writeByte( bm ); os2.writeByte( bm );
os2.writeShort( (short)(target.ilon - lonIdx*62500 - 31250) );
os2.writeShort( (short)(target.ilat - latIdx*62500 - 31250) ); int blon = os2.writeVarLengthUnsigned( dlon );
} int blat = os2.writeVarLengthUnsigned( dlat );
else
{
// full position for external target
os2.writeByte( bm | EXTERNAL_BITMASK );
os2.writeInt( target.ilon );
os2.writeInt( target.ilat );
}
if ( writedescbit != 0 ) if ( writedescbit != 0 )
{ {
// write the way description, code direction into the first bit // write the way description, code direction into the first bit
int len = lastDescription.length; if ( writeVarLength ) os2.writeByte( lastDescription.length );
if ( writeVarLength ) os2.writeByte( len ); os2.write( lastDescription );
os2.write( lastDescription, 0, len );
} }
if ( nodedescbit != 0 ) if ( nodedescbit != 0 )
{ {
@ -199,7 +198,7 @@ public class OsmNodeP implements Comparable<OsmNodeP>
target.markLinkWritten( origin ); target.markLinkWritten( origin );
break; break;
} }
os2.writeShort( target.getSElev() ); os2.writeVarLengthSigned( target.getSElev() -getSElev() );
// next link is the one (of two), does does'nt point back // next link is the one (of two), does does'nt point back
for( link = target.firstlink; link != null; link = link.next ) for( link = target.firstlink; link != null; link = link.next )
{ {
@ -211,12 +210,15 @@ public class OsmNodeP implements Comparable<OsmNodeP>
} }
// calculate the body size // calculate the body size
int bodySize = bos.size(); int bodySize = os2.size();
os.ensureCapacity( bodySize + 8 );
os.writeShort( (short)(ilon - lonIdx*62500 - 31250) ); os.writeShort( (short)(ilon - lonIdx*62500 - 31250) );
os.writeShort( (short)(ilat - latIdx*62500 - 31250) ); os.writeShort( (short)(ilat - latIdx*62500 - 31250) );
os.writeInt( bodySize );
bos.writeTo( os ); os.writeVarLengthUnsigned( bodySize );
os.write( abBuf, 0, bodySize );
} }
public String toString2() public String toString2()

View file

@ -10,8 +10,6 @@ public class OsmNodePT extends OsmNodeP
{ {
public byte[] descriptionBits; public byte[] descriptionBits;
public byte wayOrBits = 0; // used to propagate bike networks to nodes
public OsmNodePT() public OsmNodePT()
{ {
} }
@ -25,7 +23,6 @@ public class OsmNodePT extends OsmNodeP
public final byte[] getNodeDecsription() public final byte[] getNodeDecsription()
{ {
return descriptionBits; return descriptionBits;
// return descriptionBits | (long)( (wayOrBits & 6) >> 1 ); TODO !!!!!!!!!!1
} }
@Override @Override

View file

@ -7,6 +7,7 @@ import java.io.File;
import java.util.HashMap; import java.util.HashMap;
import btools.util.CompactLongSet; import btools.util.CompactLongSet;
import btools.util.DiffCoderDataOutputStream;
import btools.util.FrozenLongSet; import btools.util.FrozenLongSet;
/** /**
@ -21,8 +22,8 @@ import btools.util.FrozenLongSet;
*/ */
public class PosUnifier extends MapCreatorBase public class PosUnifier extends MapCreatorBase
{ {
private DataOutputStream nodesOutStream; private DiffCoderDataOutputStream nodesOutStream;
private DataOutputStream borderNodesOut; private DiffCoderDataOutputStream borderNodesOut;
private File nodeTilesOut; private File nodeTilesOut;
private CompactLongSet positionSet; private CompactLongSet positionSet;

View file

@ -7,6 +7,7 @@ import java.io.File;
import java.util.HashMap; import java.util.HashMap;
import btools.expressions.BExpressionContext; import btools.expressions.BExpressionContext;
import btools.expressions.BExpressionMetaData;
import btools.util.CompactLongSet; import btools.util.CompactLongSet;
import btools.util.FrozenLongSet; import btools.util.FrozenLongSet;
@ -29,7 +30,7 @@ public class RelationMerger extends MapCreatorBase
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception
{ {
System.out.println("*** RelationMerger: merge relation bits into ways" ); System.out.println("*** RelationMerger: merge relations into ways" );
if (args.length != 6) if (args.length != 6)
{ {
System.out.println("usage: java RelationMerger <way-file-in> <way-file-out> <relation-file> <lookup-file> <report-profile> <check-profile>" ); System.out.println("usage: java RelationMerger <way-file-in> <way-file-out> <relation-file> <lookup-file> <report-profile> <check-profile>" );
@ -42,11 +43,15 @@ public class RelationMerger extends MapCreatorBase
public void process( File wayFileIn, File wayFileOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile ) throws Exception public void process( File wayFileIn, File wayFileOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile ) throws Exception
{ {
// read lookup + profile for relation access-check // read lookup + profile for relation access-check
expctxReport = new BExpressionContext("way"); BExpressionMetaData metaReport = new BExpressionMetaData();
expctxReport.readMetaData( lookupFile ); expctxReport = new BExpressionContext("way", metaReport );
metaReport.readMetaData( lookupFile );
BExpressionMetaData metaCheck = new BExpressionMetaData();
expctxCheck = new BExpressionContext("way", metaCheck );
metaCheck.readMetaData( lookupFile );
expctxReport.parseFile( reportProfile, "global" ); expctxReport.parseFile( reportProfile, "global" );
expctxCheck = new BExpressionContext("way");
expctxCheck.readMetaData( lookupFile );
expctxCheck.parseFile( checkProfile, "global" ); expctxCheck.parseFile( checkProfile, "global" );
// expctxStat = new BExpressionContext("way"); // expctxStat = new BExpressionContext("way");
@ -63,6 +68,7 @@ public class RelationMerger extends MapCreatorBase
String network = dis.readUTF(); String network = dis.readUTF();
String tagname = "route_" + route + "_" + network; String tagname = "route_" + route + "_" + network;
CompactLongSet routeset = null; CompactLongSet routeset = null;
if ( expctxCheck.getLookupNameIdx(tagname) >= 0 ) if ( expctxCheck.getLookupNameIdx(tagname) >= 0 )
{ {
@ -127,6 +133,7 @@ public class RelationMerger extends MapCreatorBase
if ( ok ) if ( ok )
{ {
expctxReport.decode( data.description );
for( String tagname : routesets.keySet() ) for( String tagname : routesets.keySet() )
{ {
CompactLongSet routeset = routesets.get( tagname ); CompactLongSet routeset = routesets.get( tagname );

View file

@ -8,7 +8,9 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import btools.expressions.BExpressionContext; import btools.expressions.BExpressionContext;
import btools.expressions.BExpressionMetaData;
import btools.util.ByteArrayUnifier; import btools.util.ByteArrayUnifier;
import btools.util.ByteDataWriter;
import btools.util.CompactLongMap; import btools.util.CompactLongMap;
import btools.util.CompactLongSet; import btools.util.CompactLongSet;
import btools.util.Crc32; import btools.util.Crc32;
@ -45,6 +47,7 @@ public class WayLinker extends MapCreatorBase
private long creationTimeStamp; private long creationTimeStamp;
private BExpressionContext expctxWay; private BExpressionContext expctxWay;
private BExpressionContext expctxNode;
private ByteArrayUnifier abUnifier; private ByteArrayUnifier abUnifier;
@ -77,13 +80,19 @@ public class WayLinker extends MapCreatorBase
this.borderFileIn = borderFileIn; this.borderFileIn = borderFileIn;
this.dataTilesSuffix = dataTilesSuffix; this.dataTilesSuffix = dataTilesSuffix;
BExpressionMetaData meta = new BExpressionMetaData();
// read lookup + profile for lookup-version + access-filter // read lookup + profile for lookup-version + access-filter
expctxWay = new BExpressionContext("way"); expctxWay = new BExpressionContext("way", meta);
expctxWay.readMetaData( lookupFile ); expctxNode = new BExpressionContext("node", meta);
lookupVersion = expctxWay.lookupVersion; meta.readMetaData( lookupFile );
lookupMinorVersion = expctxWay.lookupMinorVersion;
writeVarLength = expctxWay.readVarLength; lookupVersion = meta.lookupVersion;
lookupMinorVersion = meta.lookupMinorVersion;
writeVarLength = meta.readVarLength;
expctxWay.parseFile( profileFile, "global" ); expctxWay.parseFile( profileFile, "global" );
expctxNode.parseFile( profileFile, "global" );
creationTimeStamp = System.currentTimeMillis(); creationTimeStamp = System.currentTimeMillis();
@ -158,10 +167,10 @@ public class WayLinker extends MapCreatorBase
ok |= expctxWay.getCostfactor() < 10000.; ok |= expctxWay.getCostfactor() < 10000.;
if ( !ok ) return; if ( !ok ) return;
byte bridgeTunnel = 0; byte wayBits = 0;
expctxWay.decode( description ); expctxWay.decode( description );
if ( expctxWay.getBooleanLookupValue( "bridge" ) ) bridgeTunnel |= OsmNodeP.BRIDGE_AND_BIT; if ( !expctxWay.getBooleanLookupValue( "bridge" ) ) wayBits |= OsmNodeP.NO_BRIDGE_BIT;
if ( expctxWay.getBooleanLookupValue( "tunnel" ) ) bridgeTunnel |= OsmNodeP.TUNNEL_AND_BIT; if ( !expctxWay.getBooleanLookupValue( "tunnel" ) ) wayBits |= OsmNodeP.NO_TUNNEL_BIT;
OsmNodeP n1 = null; OsmNodeP n1 = null;
OsmNodeP n2 = null; OsmNodeP n2 = null;
@ -185,7 +194,7 @@ public class WayLinker extends MapCreatorBase
} }
if ( n2 != null ) if ( n2 != null )
{ {
n2.wayAndBits &= bridgeTunnel; n2.wayBits |= wayBits;
} }
} }
} }
@ -196,6 +205,9 @@ public class WayLinker extends MapCreatorBase
nodesMap = null; nodesMap = null;
borderSet = null; borderSet = null;
byte[] abBuf = new byte[1024*1024];
byte[] abBuf2 = new byte[10*1024*1024];
int maxLon = minLon + 5000000; int maxLon = minLon + 5000000;
int maxLat = minLat + 5000000; int maxLat = minLat + 5000000;
@ -264,17 +276,16 @@ public class WayLinker extends MapCreatorBase
{ {
Collections.sort( subList ); Collections.sort( subList );
ByteArrayOutputStream bos = new ByteArrayOutputStream( ); ByteDataWriter dos = new ByteDataWriter( abBuf2 );
DataOutputStream dos = new DataOutputStream( bos );
dos.writeInt( subList.size() + 1 ); // reserve 1 dummy node for crc dos.writeInt( subList.size() );
for( int ni=0; ni<subList.size(); ni++ ) for( int ni=0; ni<subList.size(); ni++ )
{ {
OsmNodeP n = subList.get(ni); OsmNodeP n = subList.get(ni);
n.writeNodeData( dos, writeVarLength ); n.writeNodeData( dos, writeVarLength, abBuf );
} }
dos.close(); byte[] subBytes = dos.toByteArray();
byte[] subBytes = bos.toByteArray(); pos += subBytes.length + 4; // reserve 4 bytes for crc
pos += subBytes.length + 12; // reserve 12 bytes for crc dummy node
subByteArrays[si] = subBytes; subByteArrays[si] = subBytes;
} }
posIdx[si] = pos; posIdx[si] = pos;
@ -289,9 +300,6 @@ public class WayLinker extends MapCreatorBase
if ( ab != null ) if ( ab != null )
{ {
os.write( ab ); os.write( ab );
os.writeShort( Short.MAX_VALUE ); // write crc as a dummy node for compatibility
os.writeShort( Short.MAX_VALUE );
os.writeInt( 4 );
os.writeInt( Crc32.crc( ab, 0 , ab.length ) ); os.writeInt( Crc32.crc( ab, 0 , ab.length ) );
} }
} }

View file

@ -5,12 +5,14 @@
*/ */
package btools.mapaccess; package btools.mapaccess;
import java.util.*; import java.io.IOException;
import java.io.*; import java.util.ArrayList;
import java.util.List;
import btools.util.ByteDataReader;
import btools.util.Crc32; import btools.util.Crc32;
final class MicroCache final class MicroCache extends ByteDataReader
{ {
private long[] faid; private long[] faid;
private int[] fapos; private int[] fapos;
@ -19,9 +21,9 @@ final class MicroCache
private int delbytes = 0; private int delbytes = 0;
private int p2size; // next power of 2 of size private int p2size; // next power of 2 of size
private boolean readVarLength;
// the object parsing position and length // the object parsing position and length
private byte[] ab;
private int aboffset;
private int aboffsetEnd; private int aboffsetEnd;
// cache control: a virgin cache can be // cache control: a virgin cache can be
@ -29,8 +31,11 @@ final class MicroCache
boolean virgin = true; boolean virgin = true;
boolean ghost = false; boolean ghost = false;
public MicroCache( OsmFile segfile, int lonIdx80, int latIdx80, byte[] iobuffer ) throws Exception public MicroCache( OsmFile segfile, int lonIdx80, int latIdx80, byte[] iobuffer, boolean readVarLength ) throws Exception
{ {
super( null );
this.readVarLength = readVarLength;
int lonDegree = lonIdx80/80; int lonDegree = lonIdx80/80;
int latDegree = latIdx80/80; int latDegree = latIdx80/80;
@ -62,13 +67,15 @@ final class MicroCache
{ {
int ilon = readShort(); int ilon = readShort();
int ilat = readShort(); int ilat = readShort();
int bodySize = readInt(); int bodySize = readVarLength ? readVarLengthUnsigned() : readInt();
if ( ilon == Short.MAX_VALUE && ilat == Short.MAX_VALUE )
// kack for the old format crc
if ( !readVarLength && ilon == Short.MAX_VALUE && ilat == Short.MAX_VALUE )
{ {
int crc = Crc32.crc( ab, 0, aboffset-8 ); int crc = Crc32.crc( ab, 0, aboffset-8 ); // old format crc
if ( crc != readInt() ) if ( crc != readInt() )
{ {
throw new IOException( "checkum error" ); throw new IOException( "checkum-error" );
} }
size = i; size = i;
break; break;
@ -77,6 +84,15 @@ final class MicroCache
nbytes += bodySize; nbytes += bodySize;
} }
if ( readVarLength ) // new format crc
{
int crc = Crc32.crc( ab, 0, aboffset );
if ( crc != readInt() )
{
throw new IOException( "checkum error" );
}
}
// new array with only net data // new array with only net data
byte[] nab = new byte[nbytes]; byte[] nab = new byte[nbytes];
aboffset = 4; aboffset = 4;
@ -95,7 +111,7 @@ final class MicroCache
long nodeId = ((long)ilon)<<32 | ilat; long nodeId = ((long)ilon)<<32 | ilat;
faid[i] = nodeId; faid[i] = nodeId;
int bodySize = readInt(); int bodySize = readVarLength ? readVarLengthUnsigned() : readInt();
fapos[i] = noffset; fapos[i] = noffset;
System.arraycopy( ab, aboffset, nab, noffset, bodySize ); System.arraycopy( ab, aboffset, nab, noffset, bodySize );
aboffset += bodySize; aboffset += bodySize;
@ -173,7 +189,7 @@ final class MicroCache
long id = node.getIdFromPos(); long id = node.getIdFromPos();
if ( getAndClear( id ) ) if ( getAndClear( id ) )
{ {
node.parseNodeBody( this, nodesMap, dc ); node.parseNodeBody( this, nodesMap, dc, readVarLength );
} }
if ( doCollect && delcount > size / 2 ) // garbage collection if ( doCollect && delcount > size / 2 ) // garbage collection
@ -252,53 +268,6 @@ final class MicroCache
return positions; return positions;
} }
public int readInt()
{
int i3 = ab[aboffset++]& 0xff;
int i2 = ab[aboffset++]& 0xff;
int i1 = ab[aboffset++]& 0xff;
int i0 = ab[aboffset++]& 0xff;
return (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
}
public long readLong()
{
long i7 = ab[aboffset++]& 0xff;
long i6 = ab[aboffset++]& 0xff;
long i5 = ab[aboffset++]& 0xff;
long i4 = ab[aboffset++]& 0xff;
long i3 = ab[aboffset++]& 0xff;
long i2 = ab[aboffset++]& 0xff;
long i1 = ab[aboffset++]& 0xff;
long i0 = ab[aboffset++]& 0xff;
return (i7 << 56) + (i6 << 48) + (i5 << 40) + (i4 << 32) + (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
}
public boolean readBoolean()
{
int i0 = ab[aboffset++]& 0xff;
return i0 != 0;
}
public byte readByte()
{
int i0 = ab[aboffset++] & 0xff;
return (byte)(i0);
}
public short readShort()
{
int i1 = ab[aboffset++] & 0xff;
int i0 = ab[aboffset++] & 0xff;
return (short)( (i1 << 8) | i0);
}
public void readFully( byte[] ta )
{
System.arraycopy( ab, aboffset, ta, 0, ta.length );
aboffset += ta.length;
}
public boolean hasMoreData() public boolean hasMoreData()
{ {
return aboffset < aboffsetEnd; return aboffset < aboffsetEnd;

View file

@ -17,6 +17,7 @@ public final class NodesCache
private OsmNodesMap nodesMap; private OsmNodesMap nodesMap;
private int lookupVersion; private int lookupVersion;
private int lookupMinorVersion; private int lookupMinorVersion;
private boolean readVarLength;
private boolean carMode; private boolean carMode;
private String currentFileName; private String currentFileName;
@ -33,12 +34,13 @@ public final class NodesCache
private long cacheSum = 0; private long cacheSum = 0;
private boolean garbageCollectionEnabled = false; private boolean garbageCollectionEnabled = false;
public NodesCache( String segmentDir, OsmNodesMap nodesMap, int lookupVersion, int lookupMinorVersion, boolean carMode, NodesCache oldCache ) public NodesCache( String segmentDir, OsmNodesMap nodesMap, int lookupVersion, int minorVersion, boolean varLen, boolean carMode, NodesCache oldCache )
{ {
this.segmentDir = segmentDir; this.segmentDir = segmentDir;
this.nodesMap = nodesMap; this.nodesMap = nodesMap;
this.lookupVersion = lookupVersion; this.lookupVersion = lookupVersion;
this.lookupMinorVersion = lookupMinorVersion; this.lookupMinorVersion = minorVersion;
this.readVarLength = varLen;
this.carMode = carMode; this.carMode = carMode;
if ( oldCache != null ) if ( oldCache != null )
@ -145,7 +147,7 @@ public final class NodesCache
checkEnableCacheCleaning(); checkEnableCacheCleaning();
segment = new MicroCache( osmf, lonIdx80, latIdx80, iobuffer ); segment = new MicroCache( osmf, lonIdx80, latIdx80, iobuffer, readVarLength );
cacheSum += segment.getDataSize(); cacheSum += segment.getDataSize();
osmf.microCaches[subIdx] = segment; osmf.microCaches[subIdx] = segment;
segmentList.add( segment ); segmentList.add( segment );

View file

@ -7,6 +7,8 @@ package btools.mapaccess;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import btools.util.ByteDataReader;
import btools.util.Crc32; import btools.util.Crc32;
final class OsmFile final class OsmFile

View file

@ -11,8 +11,9 @@ import btools.util.ByteArrayUnifier;
public class OsmNode implements OsmPos public class OsmNode implements OsmPos
{ {
public static final int EXTERNAL_BITMASK = 0x80; public static final int EXTERNAL_BITMASK = 0x80; // old semantic
public static final int VARIABLEDESC_BITMASK = 0x40; 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 TRANSFERNODE_BITMASK = 0x20;
public static final int WRITEDESC_BITMASK = 0x10; public static final int WRITEDESC_BITMASK = 0x10;
public static final int SKIPDETAILS_BITMASK = 0x08; public static final int SKIPDETAILS_BITMASK = 0x08;
@ -111,7 +112,7 @@ public class OsmNode implements OsmPos
} }
public void parseNodeBody( MicroCache is, OsmNodesMap hollowNodes, DistanceChecker dc ) public void parseNodeBody( MicroCache is, OsmNodesMap hollowNodes, DistanceChecker dc, boolean readVarLength )
{ {
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier(); ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
@ -124,6 +125,9 @@ public class OsmNode implements OsmPos
while( is.hasMoreData() ) while( is.hasMoreData() )
{ {
int ilonref = ilon;
int ilatref = ilat;
OsmLink link = new OsmLink(); OsmLink link = new OsmLink();
OsmTransferNode firstTransferNode = null; OsmTransferNode firstTransferNode = null;
OsmTransferNode lastTransferNode = null; OsmTransferNode lastTransferNode = null;
@ -133,6 +137,20 @@ public class OsmNode implements OsmPos
for(;;) for(;;)
{ {
int bitField = is.readByte(); int bitField = is.readByte();
// System.out.println( "parseNodeBody: var=" + readVarLength + " bitField=" + bitField );
if ( readVarLength )
{
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;
}
else
{
if ( (bitField & EXTERNAL_BITMASK) != 0 ) if ( (bitField & EXTERNAL_BITMASK) != 0 )
{ {
// full position for external target // full position for external target
@ -147,17 +165,17 @@ public class OsmNode implements OsmPos
linklon += lonIdx*62500 + 31250; linklon += lonIdx*62500 + 31250;
linklat += latIdx*62500 + 31250; linklat += latIdx*62500 + 31250;
} }
}
// read variable length or old 8 byte fixed, and ensure that 8 bytes is only fixed // read variable length or old 8 byte fixed, and ensure that 8 bytes is only fixed
boolean readFix8 = (bitField & VARIABLEDESC_BITMASK ) == 0; // old, fix length format
if ( (bitField & WRITEDESC_BITMASK ) != 0 ) if ( (bitField & WRITEDESC_BITMASK ) != 0 )
{ {
byte[] ab = new byte[readFix8 ? 8 : is.readByte()]; byte[] ab = new byte[readVarLength ? is.readByte() : 8 ];
is.readFully( ab ); is.readFully( ab );
description = abUnifier.unify( ab ); description = abUnifier.unify( ab );
} }
if ( (bitField & NODEDESC_BITMASK ) != 0 ) if ( (bitField & NODEDESC_BITMASK ) != 0 )
{ {
byte[] ab = new byte[readFix8 ? 8 : is.readByte()]; byte[] ab = new byte[readVarLength ? is.readByte() : 8 ];
is.readFully( ab ); is.readFully( ab );
nodeDescription = abUnifier.unify( ab ); nodeDescription = abUnifier.unify( ab );
} }
@ -185,7 +203,7 @@ public class OsmNode implements OsmPos
trans.ilon = linklon; trans.ilon = linklon;
trans.ilat = linklat; trans.ilat = linklat;
trans.descriptionBitmap = description; trans.descriptionBitmap = description;
trans.selev = is.readShort(); trans.selev = readVarLength ? (short)(selev + is.readVarLengthSigned()) : is.readShort();
if ( lastTransferNode == null ) if ( lastTransferNode == null )
{ {
firstTransferNode = trans; firstTransferNode = trans;

View file

@ -5,6 +5,9 @@
*/ */
package btools.mapaccess; package btools.mapaccess;
import btools.util.ByteDataReader;
import btools.util.ByteDataWriter;
public final class OsmTransferNode public final class OsmTransferNode

View file

@ -6,6 +6,8 @@
package btools.mapaccess; package btools.mapaccess;
import java.io.*; import java.io.*;
import btools.util.ByteDataReader;
import btools.util.Crc32; import btools.util.Crc32;
final public class PhysicalFile final public class PhysicalFile
@ -37,7 +39,7 @@ final public class PhysicalFile
if ( osmf.microCaches != null ) if ( osmf.microCaches != null )
for( int lonIdx80=0; lonIdx80<80; lonIdx80++ ) for( int lonIdx80=0; lonIdx80<80; lonIdx80++ )
for( int latIdx80=0; latIdx80<80; latIdx80++ ) for( int latIdx80=0; latIdx80<80; latIdx80++ )
new MicroCache( osmf, lonIdx80, latIdx80, iobuffer ); new MicroCache( osmf, lonIdx80, latIdx80, iobuffer, true ); // TODO: readVarLength ?
} }
} }
catch( IllegalArgumentException iae ) catch( IllegalArgumentException iae )

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="2" android:versionCode="3"
android:versionName="0.9.9" package="btools.routingapp"> android:versionName="1.0.1" package="btools.routingapp">
<application android:icon="@drawable/icon" android:label="@string/app_name"> <application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".BRouterActivity" <activity android:name=".BRouterActivity"
android:label="@string/app_name" android:label="@string/app_name"

View file

@ -152,7 +152,7 @@ public class BInstallerView extends View
private void startDownload( int tileIndex, boolean isCd5 ) private void startDownload( int tileIndex, boolean isCd5 )
{ {
String namebase = baseNameForTile( tileIndex ); String namebase = baseNameForTile( tileIndex );
String baseurl = "http://h2096617.stratoserver.net/brouter/segments2/"; String baseurl = "http://brouter.de/brouter/segments3/";
currentDownloadFile = namebase + (isCd5 ? ".cd5" : ".rd5" ); currentDownloadFile = namebase + (isCd5 ? ".cd5" : ".rd5" );
String url = baseurl + (isCd5 ? "carsubset/" : "" ) + currentDownloadFile; String url = baseurl + (isCd5 ? "carsubset/" : "" ) + currentDownloadFile;
isDownloading = true; isDownloading = true;
@ -584,7 +584,7 @@ float tx, ty;
// download the file // download the file
input = connection.getInputStream(); input = connection.getInputStream();
int slidx = surl.lastIndexOf( "segments2/" ); int slidx = surl.lastIndexOf( "segments3/" );
fname = baseDir + "/brouter/segments2/" + surl.substring( slidx+10 ); fname = baseDir + "/brouter/segments2/" + surl.substring( slidx+10 );
tmp_file = new File( fname + "_tmp" ); tmp_file = new File( fname + "_tmp" );
if ( new File( fname ).exists() ) return "internal error: file exists: " + fname; if ( new File( fname ).exists() ) return "internal error: file exists: " + fname;

View file

@ -30,6 +30,7 @@ import android.util.DisplayMetrics;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
import btools.expressions.BExpressionContext; import btools.expressions.BExpressionContext;
import btools.expressions.BExpressionMetaData;
import btools.mapaccess.OsmNode; import btools.mapaccess.OsmNode;
import btools.router.OsmNodeNamed; import btools.router.OsmNodeNamed;
import btools.router.OsmTrack; import btools.router.OsmTrack;
@ -668,13 +669,14 @@ private long startTime = 0L;
boolean[] modesChecked = new boolean[6]; boolean[] modesChecked = new boolean[6];
// parse global section of profile for mode preselection // parse global section of profile for mode preselection
BExpressionContext expctxGlobal = new BExpressionContext( "global" ); BExpressionMetaData meta = new BExpressionMetaData();
expctxGlobal.readMetaData( new File( profileDir, "lookups.dat" ) ); BExpressionContext expctxGlobal = new BExpressionContext( "global", meta );
meta.readMetaData( new File( profileDir, "lookups.dat" ) );
expctxGlobal.parseFile( new File( profilePath ), null ); expctxGlobal.parseFile( new File( profilePath ), null );
expctxGlobal.evaluate( new int[0] ); expctxGlobal.evaluate( new int[0] );
boolean isFoot = 0.f != expctxGlobal.getVariableValue( "validForFoot" ); boolean isFoot = 0.f != expctxGlobal.getVariableValue( "validForFoot", 0.f );
boolean isBike = 0.f != expctxGlobal.getVariableValue( "validForBikes" ); boolean isBike = 0.f != expctxGlobal.getVariableValue( "validForBikes", 0.f );
boolean isCar = 0.f != expctxGlobal.getVariableValue( "validForCars" ); boolean isCar = 0.f != expctxGlobal.getVariableValue( "validForCars", 0.f );
if ( isFoot || isBike || isCar ) if ( isFoot || isBike || isCar )
{ {

View file

@ -19,7 +19,7 @@ package btools.util;
// 001 -> 3 + following 2-bit word ( 3..6 ) // 001 -> 3 + following 2-bit word ( 3..6 )
// 0001 -> 7 + following 3-bit word ( 7..14 ) etc. // 0001 -> 7 + following 3-bit word ( 7..14 ) etc.
public void encodeDistance( int value ) public void encodeVarBits( int value )
{ {
int range = 0; int range = 0;
while ( value > range ) while ( value > range )
@ -33,7 +33,7 @@ package btools.util;
} }
// twin to encodeDistance // twin to encodeDistance
public int decodeDistance() public int decodeVarBits()
{ {
int range = 0; int range = 0;
int value = 0; int value = 0;

View file

@ -9,7 +9,11 @@ public final class ByteArrayUnifier
public ByteArrayUnifier( int size, boolean validateImmutability ) public ByteArrayUnifier( int size, boolean validateImmutability )
{ {
this.size = size; this.size = size;
if ( !Boolean.getBoolean( "disableByteArrayUnifification" ) )
{
byteArrayCache = new byte[size][]; byteArrayCache = new byte[size][];
}
if ( validateImmutability ) crcCrosscheck = new int[size]; if ( validateImmutability ) crcCrosscheck = new int[size];
} }
@ -22,6 +26,8 @@ public final class ByteArrayUnifier
*/ */
public byte[] unify( byte[] ab ) public byte[] unify( byte[] ab )
{ {
if ( byteArrayCache == null ) return ab;
int n = ab.length; int n = ab.length;
int crc = Crc32.crc( ab, 0, n ); int crc = Crc32.crc( ab, 0, n );
int idx = (crc & 0xfffffff) % size; int idx = (crc & 0xfffffff) % size;

View file

@ -3,20 +3,20 @@
* *
* @author ab * @author ab
*/ */
package btools.mapaccess; package btools.util;
final class ByteDataReader public class ByteDataReader
{ {
private byte[] ab; protected byte[] ab;
private int aboffset; protected int aboffset;
public ByteDataReader( byte[] byteArray ) public ByteDataReader( byte[] byteArray )
{ {
ab = byteArray; ab = byteArray;
} }
public int readInt() public final int readInt()
{ {
int i3 = ab[aboffset++]& 0xff; int i3 = ab[aboffset++]& 0xff;
int i2 = ab[aboffset++]& 0xff; int i2 = ab[aboffset++]& 0xff;
@ -25,7 +25,7 @@ final class ByteDataReader
return (i3 << 24) + (i2 << 16) + (i1 << 8) + i0; return (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
} }
public long readLong() public final long readLong()
{ {
long i7 = ab[aboffset++]& 0xff; long i7 = ab[aboffset++]& 0xff;
long i6 = ab[aboffset++]& 0xff; long i6 = ab[aboffset++]& 0xff;
@ -38,26 +38,46 @@ final class ByteDataReader
return (i7 << 56) + (i6 << 48) + (i5 << 40) + (i4 << 32) + (i3 << 24) + (i2 << 16) + (i1 << 8) + i0; return (i7 << 56) + (i6 << 48) + (i5 << 40) + (i4 << 32) + (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
} }
public boolean readBoolean() public final boolean readBoolean()
{ {
int i0 = ab[aboffset++]& 0xff; int i0 = ab[aboffset++]& 0xff;
return i0 != 0; return i0 != 0;
} }
public byte readByte() public final byte readByte()
{ {
int i0 = ab[aboffset++] & 0xff; int i0 = ab[aboffset++] & 0xff;
return (byte)(i0); return (byte)(i0);
} }
public short readShort() public final short readShort()
{ {
int i1 = ab[aboffset++] & 0xff; int i1 = ab[aboffset++] & 0xff;
int i0 = ab[aboffset++] & 0xff; int i0 = ab[aboffset++] & 0xff;
return (short)( (i1 << 8) | i0); return (short)( (i1 << 8) | i0);
} }
public void readFully( byte[] ta ) public final int readVarLengthSigned()
{
int v = readVarLengthUnsigned();
return ( v & 1 ) == 0 ? v >> 1 : -(v >> 1 );
}
public final int readVarLengthUnsigned()
{
int v = 0;
int shift = 0;
for(;;)
{
int i7 = ab[aboffset++] & 0xff;
v |= (( i7 & 0x7f ) << shift);
if ( ( i7 & 0x80 ) == 0 ) break;
shift += 7;
}
return v;
}
public final void readFully( byte[] ta )
{ {
System.arraycopy( ab, aboffset, ta, 0, ta.length ); System.arraycopy( ab, aboffset, ta, 0, ta.length );
aboffset += ta.length; aboffset += ta.length;

View file

@ -1,12 +1,12 @@
/** /**
* fast data-reading from a byte-array * fast data-writing to a byte-array
* *
* @author ab * @author ab
*/ */
package btools.mapaccess; package btools.util;
final class ByteDataWriter public final class ByteDataWriter
{ {
private byte[] ab; private byte[] ab;
private int aboffset; private int aboffset;
@ -58,6 +58,48 @@ final class ByteDataWriter
aboffset += sa.length; aboffset += sa.length;
} }
public void write( byte[] sa, int offset, int len )
{
System.arraycopy( sa, offset, ab, aboffset, len );
aboffset += len;
}
public void ensureCapacity( int len )
{
// TODO
}
public byte[] toByteArray()
{
byte[] c = new byte[aboffset];
System.arraycopy( ab, 0, c, 0, aboffset );
return c;
}
public int writeVarLengthSigned( int v )
{
return writeVarLengthUnsigned( v < 0 ? ( (-v) << 1 ) | 1 : v << 1 );
}
public int writeVarLengthUnsigned( int v )
{
int start = aboffset;
do
{
int i7 = v & 0x7f;
v >>= 7;
if ( v != 0 ) i7 |= 0x80;
ab[aboffset++] = (byte)( i7 & 0xff );
}
while( v != 0 );
return aboffset - start;
}
public int size()
{
return aboffset;
}
@Override @Override
public String toString() public String toString()
{ {

View file

@ -22,7 +22,8 @@ public class Crc32
public static int crc( byte[] ab, int offset, int len ) public static int crc( byte[] ab, int offset, int len )
{ {
int crc = 0xFFFFFFFF; int crc = 0xFFFFFFFF;
for( int j=offset; j<len; j++ ) int end = offset + len;
for( int j=offset; j<end; j++ )
{ {
crc = (crc >>> 8) ^ crctable[(crc ^ ab[j]) & 0xff]; crc = (crc >>> 8) ^ crctable[(crc ^ ab[j]) & 0xff];
} }

View file

@ -0,0 +1,49 @@
/**
* DataInputStream extended by varlength diff coding
*
* @author ab
*/
package btools.util;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
public final class DiffCoderDataInputStream extends DataInputStream
{
private long[] lastValues = new long[10];
public DiffCoderDataInputStream( InputStream is )
{
super( is );
}
public long readDiffed( int idx ) throws IOException
{
long d = readSigned();
long v = lastValues[idx] + d;
lastValues[idx] = v;
return v;
}
public long readSigned() throws IOException
{
long v = readUnsigned();
return ( v & 1 ) == 0 ? v >> 1 : -(v >> 1 );
}
public long readUnsigned() throws IOException
{
long v = 0;
int shift = 0;
for(;;)
{
long i7 = readByte() & 0xff;
v |= (( i7 & 0x7f ) << shift);
if ( ( i7 & 0x80 ) == 0 ) break;
shift += 7;
}
return v;
}
}

View file

@ -0,0 +1,45 @@
/**
* DataOutputStream extended by varlength diff coding
*
* @author ab
*/
package btools.util;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public final class DiffCoderDataOutputStream extends DataOutputStream
{
private long[] lastValues = new long[10];
public DiffCoderDataOutputStream( OutputStream os )
{
super( os );
}
public void writeDiffed( long v, int idx ) throws IOException
{
long d = v - lastValues[idx];
lastValues[idx] = v;
writeSigned( d );
}
public void writeSigned( long v ) throws IOException
{
writeUnsigned( v < 0 ? ( (-v) << 1 ) | 1 : v << 1 );
}
public void writeUnsigned( long v ) throws IOException
{
do
{
long i7 = v & 0x7f;
v >>= 7;
if ( v != 0 ) i7 |= 0x80;
writeByte( (byte)( i7 & 0xff ) );
}
while( v != 0 );
}
}

View file

@ -9,19 +9,19 @@ import org.junit.Test;
public class BitCoderContextTest public class BitCoderContextTest
{ {
@Test @Test
public void distanceEncodeDecodeTest() public void varBitsEncodeDecodeTest()
{ {
byte[] ab = new byte[4000]; byte[] ab = new byte[4000];
BitCoderContext ctx = new BitCoderContext( ab ); BitCoderContext ctx = new BitCoderContext( ab );
for( int i=0; i<1000; i++ ) for( int i=0; i<1000; i++ )
{ {
ctx.encodeDistance( i ); ctx.encodeVarBits( i );
} }
ctx = new BitCoderContext( ab ); ctx = new BitCoderContext( ab );
for( int i=0; i<1000; i++ ) for( int i=0; i<1000; i++ )
{ {
int value = ctx.decodeDistance(); int value = ctx.decodeVarBits();
Assert.assertTrue( "distance value mismatch", value == i ); Assert.assertTrue( "distance value mismatch", value == i );
} }
} }

View file

@ -0,0 +1,28 @@
package btools.util;
import java.util.Random;
import java.util.HashSet;
import org.junit.Assert;
import org.junit.Test;
public class ByteDataIOTest
{
@Test
public void varLengthEncodeDecodeTest()
{
byte[] ab = new byte[4000];
ByteDataWriter w = new ByteDataWriter( ab );
for( int i=0; i<1000; i++ )
{
w.writeVarLengthUnsigned( i );
}
ByteDataReader r = new ByteDataReader( ab );
for( int i=0; i<1000; i++ )
{
int value = r.readVarLengthUnsigned();
Assert.assertTrue( "value mismatch", value == i );
}
}
}