diff --git a/brouter-codec/src/main/java/btools/codec/StatCoderContext.java b/brouter-codec/src/main/java/btools/codec/StatCoderContext.java index e268e14..e964839 100644 --- a/brouter-codec/src/main/java/btools/codec/StatCoderContext.java +++ b/brouter-codec/src/main/java/btools/codec/StatCoderContext.java @@ -22,7 +22,7 @@ public final class StatCoderContext extends BitCoderContext */ public void assignBits( String name ) { - long bitpos = getBitPosition(); + long bitpos = getWritingBitPosition(); if ( statsPerName == null ) { statsPerName = new TreeMap(); @@ -88,12 +88,7 @@ public final class StatCoderContext extends BitCoderContext */ public int decodeNoisyNumber( int noisybits ) { - int value = 0; - if ( noisybits > 0 ) - { - int mask = 0xffffffff >>> ( 32 - noisybits ); - value = decodeBounded( mask ); - } + int value = decodeBits( noisybits ); return value | ( decodeVarBits() << noisybits ); } @@ -130,8 +125,7 @@ public final class StatCoderContext extends BitCoderContext int value = 0; if ( noisybits > 0 ) { - int mask = 0xffffffff >>> ( 32 - noisybits ); - value = decodeBounded( mask ) - ( 1 << ( noisybits - 1 ) ); + value = decodeBits( noisybits ) - ( 1 << ( noisybits - 1 ) ); } int val2 = decodeVarBits() << noisybits; if ( val2 != 0 ) diff --git a/brouter-codec/src/main/java/btools/codec/TagValueCoder.java b/brouter-codec/src/main/java/btools/codec/TagValueCoder.java index 63b564e..3818d4e 100644 --- a/brouter-codec/src/main/java/btools/codec/TagValueCoder.java +++ b/brouter-codec/src/main/java/btools/codec/TagValueCoder.java @@ -99,26 +99,33 @@ public final class TagValueCoder node.child2 = decodeTree( bc, buffer, validator ); return node; } - BitCoderContext target = null; + int startpos = bc.getReadingBitPosition(); + boolean hasdata = false; for ( ;; ) { int delta = bc.decodeVarBits(); - if ( target == null ) + if ( !hasdata ) { if ( delta == 0 ) + { return null; - target = new BitCoderContext( buffer ); - target.encodeBit( false ); // dummy reverse bit + } + hasdata = true; } - target.encodeVarBits( delta ); if ( delta == 0 ) + { break; - int data = bc.decodeVarBits(); - target.encodeVarBits( data ); + } + bc.decodeVarBits(); } - int len = target.getEncodedLength(); - byte[] res = new byte[len]; - System.arraycopy( buffer, 0, res, 0, len ); + int endpos = bc.getReadingBitPosition(); + + int bitcount = endpos - startpos; + int bytecount = ( bitcount + 7 ) >> 3; + + bc.setReadingBitPosition( startpos ); + byte[] res = new byte[bytecount]; + bc.copyBitsTo( res, bitcount ); int accessType = validator == null ? 2 : validator.accessType( res ); if ( accessType > 0 ) @@ -165,10 +172,6 @@ public final class TagValueCoder return; } BitCoderContext src = new BitCoderContext( data ); - if ( src.decodeBit() ) - { - throw new IllegalArgumentException( "cannot encode reverse bit!" ); - } for ( ;; ) { int delta = src.decodeVarBits(); diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java index 0696a2d..90a6f8e 100644 --- a/brouter-core/src/main/java/btools/router/OsmPath.java +++ b/brouter-core/src/main/java/btools/router/OsmPath.java @@ -47,7 +47,7 @@ final class OsmPath implements OsmLinkHolder public int originLon; public int originLat; - // the costfactor of the segment just before this paths position + // the classifier of the segment just before this paths position public float lastClassifier; public MessageData message; @@ -129,6 +129,37 @@ final class OsmPath implements OsmLinkHolder MessageData msgData = recordMessageData ? new MessageData() : null; + // evaluate the way tags + rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description ); + + // calculate the costfactor inputs + boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f; + float turncostbase = rc.expctxWay.getTurncost(); + float cfup = rc.expctxWay.getUphillCostfactor(); + float cfdown = rc.expctxWay.getDownhillCostfactor(); + float cf = rc.expctxWay.getCostfactor(); + cfup = cfup == 0.f ? cf : cfup; + cfdown = cfdown == 0.f ? cf : cfdown; + + // *** add initial cost if the classifier changed + float newClassifier = rc.expctxWay.getInitialClassifier(); + if ( newClassifier == 0. ) + { + newClassifier = (cfup + cfdown + cf)/3; + } + float classifierDiff = newClassifier - lastClassifier; + if ( classifierDiff > 0.0005 || classifierDiff < -0.0005 ) + { + lastClassifier = newClassifier; + float initialcost = rc.expctxWay.getInitialcost(); + int iicost = (int)initialcost; + if ( recordMessageData ) + { + msgData.linkinitcost += iicost; + } + cost += iicost; + } + OsmTransferNode transferNode = link.decodeFirsttransfer( p1 ); OsmNode targetNode = link.targetNode; for(;;) @@ -152,10 +183,8 @@ final class OsmPath implements OsmLinkHolder lat2 = transferNode.ilat; ele2 = transferNode.selev; } - - boolean sameData = rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description ); - // if way description changed, store message + // if recording, new MessageData for each section (needed for turn-instructions) if ( recordMessageData && msgData.wayKeyValues != null ) { originElement.message = msgData; @@ -199,18 +228,16 @@ final class OsmPath implements OsmLinkHolder } linkdisttotal += dist; - boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f; - // *** penalty for turning angles if ( !isTrafficBackbone && origin.originElement != null ) { // penalty proportional to direction change 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 - cost += turncost; + int actualturncost = (int)(cos * turncostbase + 0.2 ); // e.g. turncost=90 -> 90 degree = 90m penalty + cost += actualturncost; if ( recordMessageData ) { - msgData.linkturncost += turncost; + msgData.linkturncost += actualturncost; msgData.turnangle = (float)rc.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 ); } } @@ -292,16 +319,8 @@ final class OsmPath implements OsmLinkHolder ehbu = 0; } - // *** penalty for distance - float cfup = rc.expctxWay.getUphillCostfactor(); - float cfdown = rc.expctxWay.getDownhillCostfactor(); - float cf = rc.expctxWay.getCostfactor(); - - cfup = cfup == 0.f ? cf : cfup; - cfdown = cfdown == 0.f ? cf : cfdown; - + // get the effective costfactor (slope dependent) float costfactor = cfup*upweight + cf*(1.f - upweight - downweight) + cfdown*downweight; - if ( isTrafficBackbone ) { costfactor = 0.f; @@ -323,24 +342,6 @@ final class OsmPath implements OsmLinkHolder int cost2 = cost < minDist ? minDist : cost; traffic += dist*rc.expctxWay.getTrafficSourceDensity()*Math.pow(cost2/10000.f,rc.trafficSourceExponent); } - // *** add initial cost if the classifier changed - float newClassifier = rc.expctxWay.getInitialClassifier(); - if ( newClassifier == 0. ) - { - newClassifier = (cfup + cfdown + cf)/3; - } - float classifierDiff = newClassifier - lastClassifier; - if ( classifierDiff > 0.0005 || classifierDiff < -0.0005 ) - { - lastClassifier = newClassifier; - float initialcost = rc.expctxWay.getInitialcost(); - int iicost = (int)initialcost; - if ( recordMessageData ) - { - msgData.linkinitcost += iicost; - } - cost += iicost; - } if ( recordMessageData ) { diff --git a/brouter-core/src/main/java/btools/router/ProfileCache.java b/brouter-core/src/main/java/btools/router/ProfileCache.java index 17d3cdf..3543bc2 100644 --- a/brouter-core/src/main/java/btools/router/ProfileCache.java +++ b/brouter-core/src/main/java/btools/router/ProfileCache.java @@ -63,8 +63,8 @@ public final class ProfileCache BExpressionMetaData meta = new BExpressionMetaData(); BExpressionContextGlobal expctxGlobal = new BExpressionContextGlobal( meta ); - rc.expctxWay = new BExpressionContextWay( rc.serversizing ? 262144 : 8192, meta ); - rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 16384 : 2048, meta ); + rc.expctxWay = new BExpressionContextWay( rc.serversizing ? 262144 : 32768, meta ); + rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 16384 : 4096, meta ); meta.readMetaData( new File( profileDir, "lookups.dat" ) ); diff --git a/brouter-core/src/main/java/btools/router/RoutingContext.java b/brouter-core/src/main/java/btools/router/RoutingContext.java index f494aa5..621380e 100644 --- a/brouter-core/src/main/java/btools/router/RoutingContext.java +++ b/brouter-core/src/main/java/btools/router/RoutingContext.java @@ -12,10 +12,8 @@ import java.util.List; import btools.expressions.BExpressionContext; import btools.expressions.BExpressionContextNode; import btools.expressions.BExpressionContextWay; -import btools.mapaccess.DistanceChecker; -import btools.mapaccess.OsmTransferNode; -public final class RoutingContext implements DistanceChecker +public final class RoutingContext { public void setAlternativeIdx( int idx ) { @@ -349,28 +347,4 @@ public final class RoutingContext implements DistanceChecker return p; } - @Override - public boolean isWithinRadius( int ilon0, int ilat0, OsmTransferNode firstTransfer, int ilon1, int ilat1 ) - { - OsmNodeNamed wp = nogopoints.get(0); - double keepRadius = wp.radius; - try - { - int ilon = ilon0; - int ilat = ilat0; - for( OsmTransferNode trans = firstTransfer; trans != null; trans = trans.next ) - { - calcDistance( ilon, ilat, trans.ilon, trans.ilat ); - ilon = trans.ilon; - ilat = trans.ilat; - } - calcDistance( ilon, ilat, ilon1, ilat1 ); - return wp.radius < keepRadius; - } - finally - { - wp.radius = keepRadius; - } - } - } diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java index 13e29f3..979ce9d 100644 --- a/brouter-core/src/main/java/btools/router/RoutingEngine.java +++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java @@ -226,10 +226,19 @@ public class RoutingEngine extends Thread } finally { - ProfileCache.releaseProfile( routingContext ); + if ( hasInfo() && routingContext.expctxWay != null ) + { + logInfo( "expression cache stats=" + routingContext.expctxWay.cacheStats() ); + } + ProfileCache.releaseProfile( routingContext ); + if ( nodesCache != null ) { + if ( hasInfo() && nodesCache != null ) + { + logInfo( "NodesCache status before close=" + nodesCache.formatStatus() ); + } nodesCache.close(); nodesCache = null; } @@ -544,6 +553,10 @@ public class RoutingEngine extends Thread private void resetCache() { + if ( hasInfo() && nodesCache != null ) + { + logInfo( "NodesCache status before reset=" + nodesCache.formatStatus() ); + } nodesMap = new OsmNodesMap(); nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay, routingContext.carMode, routingContext.forceSecondaryData, nodesCache ); } diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java index 1850044..07357da 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java @@ -49,12 +49,9 @@ public abstract class BExpressionContext // hash-cache for function results private byte[][] _arrayBitmap; - private boolean[] _arrayInverse; private int[] _arrayCrc; private int currentHashBucket = -1; - private byte[] currentByteArray = null; - private boolean currentInverseDirection= false; private List expressionList; @@ -98,17 +95,10 @@ public abstract class BExpressionContext if ( Boolean.getBoolean( "disableExpressionCache" ) ) hashSize = 1; + // create the expression cache _arrayBitmap = new byte[hashSize][]; - _arrayInverse = new boolean[hashSize]; _arrayCrc = new int[hashSize]; - - // create the build-in variables cache - int nBuildInVars = getBuildInVariableNames().length; arrayBuildInVariablesCache = new float[hashSize][]; - for( int hi=0; hi>>= cnt; + bits -= cnt; + return (range >>> 1) + ( cnt > 1 ? decodeBits( cnt-1 ) : 0 ); + } + + public final void encodeBit( boolean value ) { if ( bm == 0x100 ) @@ -65,13 +82,14 @@ public class BitCoderContext public final boolean decodeBit() { - if ( bm == 0x100 ) + if ( bits == 0 ) { - bm = 1; - b = ab[++idx]; + bits = 8; + b = ab[++idx] & 0xff; } - boolean value = ( ( b & bm ) != 0 ); - bm <<= 1; + boolean value = ( ( b & 1 ) != 0 ); + b >>>= 1; + bits--; return value; } @@ -111,19 +129,46 @@ public class BitCoderContext int im = 1; // integer mask while (( value | im ) <= max) { - if ( bm == 0x100 ) + if ( bits == 0 ) { - bm = 1; - b = ab[++idx]; + bits = 8; + b = ab[++idx] & 0xff; } - if ( ( b & bm ) != 0 ) + if ( ( b & 1 ) != 0 ) value |= im; - bm <<= 1; + b >>>= 1; + bits--; im <<= 1; } return value; } + public final int decodeBits( int count ) + { + if ( count == 0 ) + { + return 0; + } + fillBuffer(); + int mask = 0xffffffff >>> ( 32 - count ); + int value = b & mask; + b >>>= count; + bits -= count; + return value; + } + + private void fillBuffer() + { + while (bits < 24) + { + if ( idx < idxMax ) + { + b |= (ab[++idx] & 0xff) << bits; + } + bits += 8; + } + } + /** * @return the encoded length in bytes */ @@ -135,7 +180,7 @@ public class BitCoderContext /** * @return the encoded length in bits */ - public final long getBitPosition() + public final long getWritingBitPosition() { long bitpos = idx << 3; int m = bm; @@ -147,4 +192,53 @@ public class BitCoderContext return bitpos; } + public final int getReadingBitPosition() + { + return (idx << 3) + 8 - bits; + } + + public final void setReadingBitPosition(int pos) + { + idx = pos >>> 3; + bits = (idx << 3) + 8 - pos; + b = ab[idx] & 0xff; + b >>>= (8-bits); + } + + public final void copyBitsTo( byte[] dst, int bitcount ) + { + int dstIdx = 0; + for(;;) + { + if ( bitcount > 8 ) + { + if ( bits < 8 ) + { + b |= (ab[++idx] & 0xff) << bits; + } + else + { + bits -= 8; + } + dst[dstIdx++] = (byte)b; + b >>>= 8; + bitcount -= 8; + } + else + { + if ( bits < bitcount ) + { + b |= (ab[++idx] & 0xff) << bits; + bits += 8; + } + + int mask = 0xff >>> ( 8 - bitcount ); + dst[dstIdx] = (byte)(b & mask); + bits -= bitcount; + b >>>= bitcount; + break; + } + } + } + } diff --git a/brouter-util/src/main/java/btools/util/Crc32.java b/brouter-util/src/main/java/btools/util/Crc32.java index ad4e3ea..760b652 100644 --- a/brouter-util/src/main/java/btools/util/Crc32.java +++ b/brouter-util/src/main/java/btools/util/Crc32.java @@ -30,17 +30,15 @@ public class Crc32 return crc; } - public static int crcWithInverseBit( byte[] ab, int inverseBitByteIndex ) + public static int crcWithInverseBit( byte[] ab, boolean isInverse ) { - int crc = 0xFFFFFFFF; + int crc = 0xFFFFFF ^ ( isInverse ? 0x990951ba : 0x706af48f ); // inverse is webbed into crc... int end = ab.length; for( int j=0; j>> 8) ^ crctable[(crc ^ b) & 0xff]; + crc = (crc >>> 8) ^ crctable[(crc ^ ab[j]) & 0xff]; } - return crc; + return isInverse ? crc | 0x80000000 : crc & 0x7fffffff; // ... and set as high bit } private static int[] crctable = { diff --git a/brouter-util/src/test/java/btools/util/BitCoderContextTest.java b/brouter-util/src/test/java/btools/util/BitCoderContextTest.java index 6e10fa0..9c11e27 100644 --- a/brouter-util/src/test/java/btools/util/BitCoderContextTest.java +++ b/brouter-util/src/test/java/btools/util/BitCoderContextTest.java @@ -19,7 +19,7 @@ public class BitCoderContextTest for ( int i = 0; i < 1000; i++ ) { int value = ctx.decodeVarBits(); - Assert.assertTrue( "distance value mismatch", value == i ); + Assert.assertTrue( "distance value mismatch i=" + i + "v=" + value, value == i ); } }