diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java
index 39adac9..e63211b 100644
--- a/brouter-core/src/main/java/btools/router/OsmPath.java
+++ b/brouter-core/src/main/java/btools/router/OsmPath.java
@@ -83,6 +83,8 @@ final class OsmPath implements OsmLinkHolder
private void addAddionalPenalty(OsmTrack refTrack, boolean recordTransferNodes, OsmPath origin, OsmLink link, RoutingContext rc )
{
+ if ( link.descriptionBitmap == null ) throw new IllegalArgumentException( "null description for class: " + link.getClass() );
+
rc.nogomatch = false;
// extract the 3 positions of the first section
@@ -101,7 +103,7 @@ final class OsmPath implements OsmLinkHolder
OsmTransferNode transferNode = link.decodeFirsttransfer();
OsmNode targetNode = link.targetNode;
- long lastDescription = -1L;
+ byte[] lastDescription = null;
String lastMessage = null;
for(;;)
{
@@ -111,7 +113,7 @@ final class OsmPath implements OsmLinkHolder
int lon2;
int lat2;
short ele2;
- long description;
+ byte[] description;
if ( transferNode == null )
{
@@ -119,6 +121,7 @@ final class OsmPath implements OsmLinkHolder
lat2 = targetNode.ilat;
ele2 = targetNode.selev;
description = link.descriptionBitmap;
+ if ( description == null ) throw new IllegalArgumentException( "null description for class: " + link.getClass() );
}
else
{
@@ -126,6 +129,7 @@ final class OsmPath implements OsmLinkHolder
lat2 = transferNode.ilat;
ele2 = transferNode.selev;
description = transferNode.descriptionBitmap;
+ if ( description == null ) throw new IllegalArgumentException( "null description for class: " + transferNode.getClass() + "/" + link.getClass() + " counterlinkwritten=" + link.counterLinkWritten );
}
// if way description changed, store message
@@ -173,7 +177,7 @@ final class OsmPath implements OsmLinkHolder
linkdisttotal += dist;
rc.messageHandler.setCurrentPos( lon2, lat2 );
- rc.expctxWay.evaluate( description, rc.messageHandler );
+ rc.expctxWay.evaluate( link instanceof OsmLinkReverse, description, rc.messageHandler );
// *** penalty for way-change
if ( origin.originElement != null )
@@ -309,10 +313,10 @@ final class OsmPath implements OsmLinkHolder
}
// finally add node-costs for target node
- if ( targetNode.nodeDescription != 0L )
+ if ( targetNode.nodeDescription != null )
{
rc.messageHandler.setCurrentPos( targetNode.ilon, targetNode.ilat );
- rc.expctxNode.evaluate( targetNode.nodeDescription, rc.messageHandler );
+ rc.expctxNode.evaluate( false, targetNode.nodeDescription, rc.messageHandler );
float initialcost = rc.expctxNode.getInitialcost();
if ( initialcost >= 1000000. )
{
diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java
index e374ab8..cd6574e 100644
--- a/brouter-core/src/main/java/btools/router/RoutingEngine.java
+++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java
@@ -73,7 +73,7 @@ public class RoutingEngine extends Thread
BExpressionContext expctxGlobal = new BExpressionContext( "global" );
expctxGlobal.readMetaData( new File( profileDir, "lookups.dat" ) );
expctxGlobal.parseFile( profileFile, null );
- expctxGlobal.evaluate( 1L, rc.messageHandler );
+ expctxGlobal.evaluate( new int[0] );
rc.readGlobalConfig(expctxGlobal);
rc.expctxWay = new BExpressionContext( "way", 4096 );
diff --git a/brouter-expressions/pom.xml b/brouter-expressions/pom.xml
index 6423fe8..0071e7a 100644
--- a/brouter-expressions/pom.xml
+++ b/brouter-expressions/pom.xml
@@ -17,5 +17,9 @@
brouter-util
${project.version}
+
+ junit
+ junit
+
diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java
index fed9010..ac0c88c 100644
--- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java
+++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java
@@ -40,15 +40,18 @@ public final class BExpressionContext
private int[] lookupData = new int[0];
+ private byte[] abBuf = new byte[256];
+
private Map variableNumbers = new HashMap();
private float[] variableData;
// hash-cache for function results
- private long[] _arrayBitmap;
+ private byte[][] _arrayBitmap;
private int currentHashBucket = -1;
- private long currentBitmap = 0;
+ private byte[] currentByteArray = null;
+ private boolean currentInversion = false;
public List expressionList;
@@ -85,7 +88,7 @@ public final class BExpressionContext
public BExpressionContext( String context, int hashSize )
{
this.context = context;
- _arrayBitmap = new long[hashSize];
+ _arrayBitmap = new byte[hashSize][];
_arrayCostfactor = new float[hashSize];
_arrayTurncost = new float[hashSize];
@@ -94,62 +97,79 @@ public final class BExpressionContext
/**
- * encode lookup data to a 64-bit word
+ * encode lookup data to a byte array
*/
- public long encode( int[] ld )
+ public byte[] encode()
{
- long w = 0;
- for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names
+ return encode( lookupData );
+ }
+
+ public byte[] encode( int[] ld )
+ {
+ // start with first bit hardwired ("reversedirection")
+ int idx = 0;
+ int bm = 2; // byte mask
+ abBuf[0] = (byte)(ld[0] == 0 ? 0 : 1);
+
+ // all others are generic
+ for( int inum = 1; inum < lookupValues.size(); inum++ ) // loop over lookup names
{
int n = lookupValues.get(inum).length - 1;
int d = ld[inum];
+ int im = 1; // integer mask
+
if ( n == 2 ) { n = 1; d = d == 2 ? 1 : 0; } // 1-bit encoding for booleans
-
- while( n != 0 ) { n >>= 1; w <<= 1; }
- w |= (long)d;
+ while( n != 0 )
+ {
+ if ( bm == 0x100 ) { bm = 1; abBuf[++idx] = 0; }
+ if ( (d & im) != 0 ) abBuf[idx] |= bm;
+ n >>= 1;
+ bm <<= 1;
+ im <<= 1;
+ }
}
- return w;
+ idx++;
+ byte[] ab = new byte[idx];
+ System.arraycopy( abBuf, 0, ab, 0, idx );
+ return ab;
}
/**
- * decode a 64-bit word into a lookup data array
+ * decode a byte-array into a lookup data array
*/
- public void decode( int[] ld, long w )
+ public void decode( int[] ld, byte[] ab )
{
- for( int inum = lookupValues.size()-1; inum >= 0; inum-- ) // loop over lookup names
+ // start with first bit hardwired ("reversedirection")
+ int idx = 1;
+ int bm = 2; // byte mask
+ int b = ab[0];
+ ld[0] = (b & 1) == 0 ? 0 : 2;
+
+ // all others are generic
+ for( int inum = 1; inum < lookupValues.size(); inum++ ) // loop over lookup names
{
int nv = lookupValues.get(inum).length;
int n = nv == 3 ? 1 : nv-1; // 1-bit encoding for booleans
- int m = 0;
- long ww = w;
- while( n != 0 ) { n >>= 1; ww >>= 1; m = m<<1 | 1; }
- int d = (int)(w & m);
+ int d = 0;
+ int im = 1; // integer mask
+ while( n != 0 )
+ {
+ if ( bm == 0x100 ) { bm = 1; b = ab[idx++]; }
+ if ( (b & bm) != 0 ) d |= im;
+ n >>= 1;
+ bm <<= 1;
+ im <<= 1;
+ }
if ( nv == 3 && d == 1 ) d = 2; // 1-bit encoding for booleans
ld[inum] = d;
- w = ww;
}
}
- /**
- * much like decode, but just for counting bits
- */
- private void countBits()
- {
- int bits = 0;
- for( int inum = lookupValues.size()-1; inum >= 0; inum-- ) // loop over lookup names
- {
- int nv = lookupValues.get(inum).length;
- int n = nv == 3 ? 1 : nv-1; // 1-bit encoding for booleans
- while( n != 0 ) { n >>= 1; bits++; }
- }
-// System.out.println( "context=" + context + ",bits=" + bits + " keys=" + lookupValues.size() );
- if ( bits > 64 ) throw new IllegalArgumentException( "lookup table for context " + context + " exceeds 64 bits!" );
- }
- public String getCsvDescription( long bitmap )
+ public String getCsvDescription( byte[] ab )
{
StringBuilder sb = new StringBuilder( 200 );
- decode( lookupData, bitmap );
+ decode( lookupData, ab );
for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names
{
BExpressionLookupValue[] va = lookupValues.get(inum);
@@ -168,10 +188,10 @@ public final class BExpressionContext
return sb.toString();
}
- public String getKeyValueDescription( long bitmap )
+ public String getKeyValueDescription( byte[] ab )
{
StringBuilder sb = new StringBuilder( 200 );
- decode( lookupData, bitmap );
+ decode( lookupData, ab );
for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names
{
BExpressionLookupValue[] va = lookupValues.get(inum);
@@ -192,6 +212,7 @@ public final class BExpressionContext
int parsedLines = 0;
boolean ourContext = false;
+ addLookupValue( "reversedirection", "yes", null );
for(;;)
{
String line = br.readLine();
@@ -215,6 +236,7 @@ public final class BExpressionContext
String value = tk.nextToken();
int idx = name.indexOf( ';' );
if ( idx >= 0 ) name = name.substring( 0, idx );
+ if ( "reversedirection".equals( name ) ) continue; // this is hardcoded
BExpressionLookupValue newValue = addLookupValue( name, value, null );
// add aliases
@@ -229,7 +251,6 @@ public final class BExpressionContext
// post-process metadata:
lookupDataFrozen = true;
- countBits();
}
catch( Exception e )
{
@@ -237,7 +258,7 @@ public final class BExpressionContext
}
}
- private void evaluate( int[] lookupData2 )
+ public void evaluate( int[] lookupData2 )
{
lookupData = lookupData2;
for( BExpression exp: expressionList)
@@ -248,27 +269,55 @@ public final class BExpressionContext
- public void evaluate( long bitmap, BExpressionReceiver receiver )
+ public void evaluate( boolean inverseDirection, byte[] ab, BExpressionReceiver receiver )
{
_receiver = receiver;
-
- if ( currentBitmap != bitmap || currentHashBucket < 0 )
+
+ int abLen = ab.length;
+ boolean equalsCurrent = currentHashBucket >= 0 && abLen == currentByteArray.length;
+ if ( equalsCurrent )
{
- // calc hash bucket from crc
- int crc = Crc32.crc( bitmap );
- int hashSize = _arrayBitmap.length;
- currentHashBucket = (crc & 0xfffffff) % hashSize;
- currentBitmap = bitmap;
+ if ( (inverseDirection ? ab[0] ^ 1 : ab[0] ) == currentByteArray[0] )
+ {
+ for( int i=1; i= nvalues ) throw new IllegalArgumentException( "value index out of range for name " + name + ": " + valueIndex );
+ lookupData[inum] = valueIndex;
+ }
+
public void parseFile( File file, String readOnlyContext )
{
try
@@ -423,7 +491,7 @@ public final class BExpressionContext
context = readOnlyContext;
expressionList = _parseFile( file );
variableData = new float[variableNumbers.size()];
- evaluate( 1L, null );
+ evaluate( lookupData ); // lookupData is dummy here - evaluate just to create the variables
context = realContext;
}
linenr = 1;
@@ -592,7 +660,7 @@ public final class BExpressionContext
public void expressionWarning( String message )
{
- _arrayBitmap[currentHashBucket] = 0L; // no caching if warnings
+ _arrayBitmap[currentHashBucket] = null; // no caching if warnings
if ( _receiver != null ) _receiver.expressionWarning( context, message );
}
}
diff --git a/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java b/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java
new file mode 100644
index 0000000..1cb2f27
--- /dev/null
+++ b/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java
@@ -0,0 +1,46 @@
+package btools.expressions;
+
+import java.util.*;
+import java.io.*;
+import java.net.URL;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EncodeDecodeTest
+{
+ @Test
+ public void encodeDecodeTest()
+ {
+ URL lookupurl = this.getClass().getResource( "/lookups.dat" );
+ Assert.assertTrue( "lookup file lookup.dat not found", lookupurl != null );
+ File lookupFile = new File(lookupurl.getFile());
+ File workingDir = lookupFile.getParentFile();
+
+ // read lookup.dat + trekking.brf
+ BExpressionContext expctxWay = new BExpressionContext("way");
+ expctxWay.readMetaData( lookupFile );
+ expctxWay.parseFile( new File( workingDir, "trekking.brf" ), "global" );
+
+ String[] tags = { "highway=residential", "oneway=yes", "reversedirection=yes" };
+
+ // encode the tags into 64 bit description word
+ int[] lookupData = expctxWay.createNewLookupData();
+ for( String arg: tags )
+ {
+ int idx = arg.indexOf( '=' );
+ if ( idx < 0 ) throw new IllegalArgumentException( "bad argument (should be =): " + arg );
+ String key = arg.substring( 0, idx );
+ String value = arg.substring( idx+1 );
+
+ expctxWay.addLookupValue( key, value, lookupData );
+ }
+ byte[] description = expctxWay.encode(lookupData);
+
+ // calculate the cost factor from that description
+ expctxWay.evaluate( false, description, null );
+
+ float costfactor = expctxWay.getCostfactor();
+ Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.1 ) > 0.00001 );
+ }
+}
diff --git a/brouter-expressions/src/test/resources/lookups.dat b/brouter-expressions/src/test/resources/lookups.dat
new file mode 100644
index 0000000..af197c9
--- /dev/null
+++ b/brouter-expressions/src/test/resources/lookups.dat
@@ -0,0 +1,317 @@
+---lookupversion:2
+
+---context:way
+
+highway;0001731794 track
+highway;0001457935 residential
+highway;0000968516 service
+highway;0000756237 footway
+highway;0000521566 path
+highway;0000261772 unclassified
+highway;0000220315 secondary
+highway;0000207585 tertiary
+highway;0000103445 steps
+highway;0000102114 primary
+highway;0000094484 cycleway
+highway;0000090388 living_street
+highway;0000035041 motorway
+highway;0000029965 pedestrian
+highway;0000026875 motorway_link
+highway;0000015054 trunk
+highway;0000014604 primary_link
+highway;0000012211 road
+highway;0000011822 trunk_link
+highway;0000005882 construction
+highway;0000005425 bridleway
+highway;0000005180 secondary_link
+highway;0000003360 platform
+highway;0000002616 proposed abandoned
+highway;0000001374 tertiary_link
+highway;0000000760 ferry
+highway;0000000541 raceway
+highway;0000000346 rest_area
+highway;0000000300 bus_stop
+highway;0000000184 services
+
+tracktype;0000356503 grade2
+tracktype;0000353482 grade3
+tracktype;0000281625 grade1
+tracktype;0000245193 grade4
+tracktype;0000179135 grade5
+
+surface;0000363915 asphalt
+surface;0000303589 paved
+surface;0000196783 gravel
+surface;0000137371 ground
+surface;0000128215 grass
+surface;0000092748 unpaved
+surface;0000086579 paving_stones
+surface;0000066111 cobblestone
+surface;0000042061 dirt
+surface;0000026551 concrete
+surface;0000025631 compacted
+surface;0000019861 sand
+surface;0000009400 pebblestone
+surface;0000003197 fine_gravel
+
+maxspeed;0000402224 30
+maxspeed;0000224685 50
+maxspeed;0000045177 100
+maxspeed;0000037529 70
+maxspeed;0000014237 none
+maxspeed;0000014022 60
+maxspeed;0000011530 80
+maxspeed;0000009951 10
+maxspeed;0000008056 20
+maxspeed;0000005772 120
+maxspeed;0000003165 40
+maxspeed;0000002987 7
+maxspeed;0000002826 signals
+maxspeed;0000001933 130
+
+service;0000221481 parking_aisle
+service;0000157110 driveway
+
+lit;0000132495 yes
+
+lanes;0000098207 2
+lanes;0000042192 1
+lanes;0000018533 3
+lanes;0000004577 4
+lanes;0000000448 5
+lanes;0000000318 1.5
+
+access;0000044859 yes permissive
+access;0000008452 designated official
+access;0000028727 destination customers
+access;0000076985 agricultural forestry
+access;0000116270 private
+access;0000028044 no
+
+foot;0000339384 yes allowed Yes
+foot;0000125339 designated official
+foot;0000018945 no
+foot;0000001562 private
+foot;0000000279 destination
+foot;0000008172 permissive
+
+bicycle;0000302789 yes allowed permissive
+bicycle;0000108056 designated official
+bicycle;0000000265 destination
+bicycle;0000003593 dismount
+bicycle;0000001426 private
+bicycle;0000070179 no
+
+motorcar;0000010111 yes permissive
+motorcar;0000001537 designated official
+motorcar;0000007102 destination
+motorcar;0000016706 agricultural forestry agriculture
+motorcar;0000002178 private
+motorcar;0000077771 no
+
+motor_vehicle;0000013813 yes permissive
+motor_vehicle;0000002098 designated official
+motor_vehicle;0000009792 destination
+motor_vehicle;0000019301 agricultural forestry
+motor_vehicle;0000006563 private
+motor_vehicle;0000025491 no
+
+motorcycle;0000005750 yes permissive
+motorcycle;0000001158 designated official
+motorcycle;0000005805 destination
+motorcycle;0000012401 agricultural forestry
+motorcycle;0000001180 private
+motorcycle;0000053955 no
+
+vehicle;0000000505 yes permissive
+vehicle;0000000027 designated
+vehicle;0000007582 destination
+vehicle;0000004357 agricultural forestry
+vehicle;0000001155 private
+vehicle;0000006487 no
+
+cycleway;0000033575 track
+cycleway;0000012829 no
+cycleway;0000011604 lane
+cycleway;0000008938 opposite
+cycleway;0000001503 none
+cycleway;0000001146 right
+cycleway;0000001031 opposite_track
+cycleway;0000001029 yes
+cycleway;0000000856 opposite_lane
+cycleway;0000000675 both
+cycleway;0000000665 left
+cycleway;0000000521 shared
+cycleway;0000000383 street
+cycleway;0000000176 segregated
+
+mtb:scale;0000043968 0
+mtb:scale;0000019705 1
+mtb:scale;0000006436 2
+mtb:scale;0000002702 3
+mtb:scale;0000001083 4
+mtb:scale;0000000329 5
+
+sac_scale;0000049626 hiking
+sac_scale;0000007933 mountain_hiking
+sac_scale;0000001160 demanding_mountain_hiking
+sac_scale;0000000523 yes
+sac_scale;0000000364 alpine_hiking
+sac_scale;0000000117 demanding_alpine_hiking
+
+noexit;0000058492 yes
+
+motorroad;0000019250 yes
+
+oneway;0000330245 yes
+oneway;0000075148 no
+oneway;0000003679 -1
+oneway;0000000001 true
+oneway;0000000001 1
+
+junction;0000015929 roundabout
+
+bridge;0000182649 yes viaduct true suspension
+
+tunnel;0000031626 yes
+
+lcn;0000018999 yes
+
+longdistancecycleway;0000000001 yes
+
+reversedirection;0000000001 yes
+
+---context:node
+
+highway;0000100947 turning_circle
+highway;0000067645 traffic_signals
+highway;0000047209 crossing
+highway;0000037164 bus_stop
+highway;0000006577 motorway_junction
+highway;0000003811 stop
+highway;0000002331 mini_roundabout
+highway;0000001789 milestone
+highway;0000001692 passing_place
+highway;0000001289 give_way
+highway;0000001092 emergency_access_point
+highway;0000000683 speed_camera
+highway;0000000672 steps
+highway;0000000658 incline_steep
+highway;0000000620 elevator
+highway;0000000506 street_lamp
+highway;0000000490 ford
+highway;0000000458 incline
+highway;0000000135 rest_area
+highway;0000000105 path
+highway;0000000098 emergency_bay
+highway;0000000096 road
+highway;0000000087 platform
+highway;0000000074 services
+highway;0000000058 track
+highway;0000000055 service
+highway;0000000054 footway
+highway;0000000053 traffic_calming
+highway;0000000046 toll_bridge
+highway;0000000037 city_entry
+
+barrier;0000076979 gate
+barrier;0000069308 bollard
+barrier;0000028131 lift_gate
+barrier;0000017332 cycle_barrier
+barrier;0000005693 entrance
+barrier;0000002885 block
+barrier;0000001065 kissing_gate
+barrier;0000000828 cattle_grid
+barrier;0000000602 stile
+barrier;0000000561 turnstile
+barrier;0000000512 no
+barrier;0000000463 fence
+barrier;0000000417 bump_gate
+barrier;0000000324 sally_port
+barrier;0000000283 yes
+barrier;0000000283 hampshire_gate
+barrier;0000000236 swing_gate
+barrier;0000000203 chain
+barrier;0000000181 toll_booth
+barrier;0000000180 door
+barrier;0000000104 chicane
+barrier;0000000096 tree
+barrier;0000000087 border_control
+barrier;0000000077 log
+barrier;0000000076 traffic_crossing_pole
+barrier;0000000063 wall
+barrier;0000000060 fallen_tree
+barrier;0000000052 stone
+barrier;0000000048 ditch
+barrier;0000000031 spikes
+
+access;0000001309 yes permissive
+access;0000000118 designated official
+access;0000000405 destination customers
+access;0000000276 agricultural forestry
+access;0000008574 private
+access;0000002145 no
+
+foot;0000080681 yes permissive
+foot;0000000326 designated official
+foot;0000000023 destination
+foot;0000000156 private
+foot;0000009170 no
+
+bicycle;0000076717 yes permissive
+bicycle;0000000406 designated official
+bicycle;0000000018 destination
+bicycle;0000000081 dismount
+bicycle;0000000051 private
+bicycle;0000016121 no
+
+motorcar;0000005785 yes permissive
+motorcar;0000000026 designated official
+motorcar;0000000080 destination
+motorcar;0000000112 agricultural forestry
+motorcar;0000000171 private
+motorcar;0000001817 no
+
+motor_vehicle;0000000066 yes permissive
+motor_vehicle;0000000000 designated official
+motor_vehicle;0000000030 destination
+motor_vehicle;0000000073 agricultural forestry
+motor_vehicle;0000000136 private
+motor_vehicle;0000000469 no
+
+motorcycle;0000004515 yes permissive
+motorcycle;0000000007 designated official
+motorcycle;0000000054 destination
+motorcycle;0000000027 agricultural forestry
+motorcycle;0000000063 private
+motorcycle;0000001637 no
+
+vehicle;0000000058 yes permissive
+vehicle;0000000000 designated
+vehicle;0000000081 destination
+vehicle;0000000038 agricultural forestry
+vehicle;0000000041 private
+vehicle;0000000271 no
+
+crossing;0000032485 traffic_signals
+crossing;0000014300 uncontrolled
+crossing;0000005086 island
+crossing;0000001565 unmarked
+crossing;0000001066 no
+crossing;0000000333 zebra
+
+railway;0000034039 level_crossing
+railway;0000010175 crossing
+
+noexit;0000043010 yes
+
+entrance;0000015094 yes
+entrance;0000007079 main
+entrance;0000000554 service
+entrance;0000000169 emergency
+entrance;0000000063 exit
+entrance;0000000008 private
+
+lcn;0000018999 yes
+
+longdistancecycleway;0000000001 yes
diff --git a/brouter-expressions/src/test/resources/trekking.brf b/brouter-expressions/src/test/resources/trekking.brf
new file mode 100644
index 0000000..28a59ec
--- /dev/null
+++ b/brouter-expressions/src/test/resources/trekking.brf
@@ -0,0 +1,225 @@
+# *** The trekking profile is for slow travel
+# *** and avoiding car traffic, but still with
+# *** a focus on approaching your destination
+# *** efficiently.
+
+---context:global # following code refers to global config
+
+# Use the following switches to change behaviour
+# (1=yes, 0=no):
+
+assign consider_elevation 1 # set to 0 to ignore elevation in routing
+assign allow_steps 1 # set to 0 to disallow steps
+assign allow_ferries 1 # set to 0 to disallow ferries
+assign ignore_cycleroutes 0 # set to 1 for better elevation results
+assign stick_to_cycleroutes 0 # set to 1 to just follow cycleroutes
+assign avoid_unsafe 0 # set to 1 to avoid standard highways
+
+assign validForBikes 1
+
+# the elevation parameters
+
+assign downhillcost switch consider_elevation 60 0
+assign downhillcutoff 1.5
+assign uphillcost 0
+assign uphillcutoff 1.5
+
+---context:way # following code refers to way-tags
+
+#
+# pre-calculate some logical expressions
+#
+assign is_ldcr and longdistancecycleway=yes not ignore_cycleroutes
+assign isbike or bicycle=yes or bicycle=designated lcn=yes
+assign ispaved or surface=paved or surface=asphalt or surface=concrete surface=paving_stones
+assign isunpaved not or surface= or ispaved or surface=fine_gravel surface=cobblestone
+assign probablyGood or ispaved and isbike not isunpaved
+
+
+#
+# this is the cost (in Meter) for a 90-degree turn
+# The actual cost is calculated as turncost*cos(angle)
+# (Suppressing turncost while following longdistance-cycleways
+# makes them a little bit more magnetic)
+#
+assign turncost switch is_ldcr 0 90
+
+#
+# calculate the initial cost
+# this is added to the total cost each time the costfactor
+# changed
+#
+assign initialcost switch highway=ferry 10000 0
+
+#
+# implicit access here just from the motorroad tag
+# (implicit access rules from highway tag handled elsewhere)
+#
+assign defaultaccess
+ switch access=
+ not motorroad=yes
+ switch or access=private access=no
+ 0
+ 1
+
+#
+# calculate logical bike access
+#
+assign bikeaccess
+ or longdistancecycleway=yes
+ switch bicycle=
+ switch vehicle=
+ defaultaccess
+ switch or vehicle=private vehicle=no
+ 0
+ 1
+ not or bicycle=private or bicycle=no bicycle=dismount
+
+#
+# calculate logical foot access
+#
+assign footaccess
+ or bikeaccess
+ or bicycle=dismount
+ switch foot=
+ defaultaccess
+ not or foot=private foot=no
+
+#
+# if not bike-, but foot-acess, just a moderate penalty,
+# otherwise access is forbidden
+#
+assign accesspenalty
+ switch bikeaccess
+ 0
+ switch footaccess
+ 4
+ 100000
+
+#
+# handle one-ways. On primary roads, wrong-oneways should
+# be close to forbidden, while on other ways we just add
+# 4 to the costfactor (making it at least 5 - you are allowed
+# to push your bike)
+#
+assign oneway
+ switch oneway=
+ junction=roundabout
+ or oneway=yes or oneway=true oneway=1
+assign onewaypenalty
+ switch switch reversedirection=yes oneway oneway=-1
+ switch or cycleway=opposite or cycleway=opposite_lane cycleway=opposite_track 0
+ switch or highway=primary highway=primary_link 50
+ switch or highway=secondary highway=secondary_link 30
+ switch or highway=tertiary highway=tertiary_link 20
+ 4.0
+ 0.0
+
+#
+# calculate the cost-factor, which is the factor
+# by which the distance of a way-segment is multiplied
+# to calculate the cost of that segment. The costfactor
+# must be >=1 and it's supposed to be close to 1 for
+# the type of way the routing profile is searching for
+#
+assign costfactor
+
+ add max onewaypenalty accesspenalty
+
+ #
+ # steps and ferries are special. Note this is handled
+ # before the longdistancecycleway-switch, to be able
+ # to really exlude them be setting cost to infinity
+ #
+ switch highway=steps switch allow_steps 40 100000
+ switch highway=ferry switch allow_ferries 5.67 100000
+
+ #
+ # handle long-distance cycle-routes.
+ #
+ switch is_ldcr 1 # always treated as perfect (=1)
+ add switch stick_to_cycleroutes 0.5 0.05 # everything else somewhat up
+
+ #
+ # some other highway types
+ #
+ switch highway=pedestrian 3
+ switch highway=bridleway 5
+ switch highway=cycleway 1
+ switch or highway=residential highway=living_street switch isunpaved 1.5 1.1
+ switch highway=service switch isunpaved 1.6 1.3
+
+ #
+ # tracks and track-like ways are rated mainly be tracktype/grade
+ # But note that if no tracktype is given (mainly for road/path/footway)
+ # it can be o.k. if there's any other hint for quality
+ #
+ switch or highway=track or highway=road or highway=path highway=footway
+ switch tracktype=grade1 switch probablyGood 1.0 1.3
+ switch tracktype=grade2 switch probablyGood 1.1 2.0
+ switch tracktype=grade3 switch probablyGood 1.5 3.0
+ switch tracktype=grade4 switch probablyGood 2.0 5.0
+ switch tracktype=grade5 switch probablyGood 3.0 5.0
+ switch probablyGood 1.0 5.0
+
+ #
+ # When avoiding unsafe ways, avoid highways without a bike hint
+ #
+ add switch and avoid_unsafe not isbike 2 0
+
+ #
+ # exclude motorways and proposed roads
+ #
+ switch or highway=motorway highway=motorway_link 100000
+ switch highway=proposed 100000
+
+ #
+ # actuals roads are o.k. if we have a bike hint
+ #
+ switch or highway=trunk highway=trunk_link switch isbike 1.5 10
+ switch or highway=primary highway=primary_link switch isbike 1.2 3
+ switch or highway=secondary highway=secondary_link switch isbike 1.1 1.6
+ switch or highway=tertiary highway=tertiary_link switch isbike 1.0 1.4
+ switch highway=unclassified switch isbike 1.0 1.3
+
+ #
+ # default for any other highway type not handled above
+ #
+ 2.0
+
+
+---context:node # following code refers to node tags
+
+assign defaultaccess
+ switch access=
+ 1 # add default barrier restrictions here!
+ switch or access=private access=no
+ 0
+ 1
+
+assign bikeaccess
+ or or longdistancecycleway=yes lcn=yes
+ switch bicycle=
+ switch vehicle=
+ defaultaccess
+ switch or vehicle=private vehicle=no
+ 0
+ 1
+ switch or bicycle=private or bicycle=no bicycle=dismount
+ 0
+ 1
+
+assign footaccess
+ or bicycle=dismount
+ switch foot=
+ defaultaccess
+ switch or foot=private foot=no
+ 0
+ 1
+
+assign initialcost
+ switch bikeaccess
+ 0
+ switch footaccess
+ 100
+ 1000000
diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/NodeData.java b/brouter-map-creator/src/main/java/btools/mapcreator/NodeData.java
index aef65f9..b8937b6 100644
--- a/brouter-map-creator/src/main/java/btools/mapcreator/NodeData.java
+++ b/brouter-map-creator/src/main/java/btools/mapcreator/NodeData.java
@@ -13,7 +13,7 @@ public class NodeData extends MapCreatorBase
public long nid;
public int ilon;
public int ilat;
- public long description;
+ public byte[] description;
public short selev = Short.MIN_VALUE;
public NodeData( long id, double lon, double lat )
@@ -29,18 +29,18 @@ public class NodeData extends MapCreatorBase
ilon = dis.readInt();
ilat = dis.readInt();
int mode = dis.readByte();
- if ( ( mode & 1 ) != 0 ) description = dis.readLong();
+ if ( ( mode & 1 ) != 0 ) { int dlen = dis.readByte(); description = new byte[dlen]; dis.readFully( description ); }
if ( ( mode & 2 ) != 0 ) selev = dis.readShort();
- }
+ }
public void writeTo( DataOutputStream dos ) throws Exception
{
writeId( dos, nid );
dos.writeInt( ilon );
dos.writeInt( ilat );
- int mode = ( description == 0L ? 0 : 1 ) | ( selev == Short.MIN_VALUE ? 0 : 2 );
+ int mode = ( description == null ? 0 : 1 ) | ( selev == Short.MIN_VALUE ? 0 : 2 );
dos.writeByte( (byte)mode );
- if ( ( mode & 1 ) != 0 ) dos.writeLong( description );
+ if ( ( mode & 1 ) != 0 ) { dos.writeByte( description.length ); dos.write( description ); }
if ( ( mode & 2 ) != 0 ) dos.writeShort( selev );
}
}
diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmLinkP.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmLinkP.java
index 141f43c..192fa96 100644
--- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmLinkP.java
+++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmLinkP.java
@@ -6,13 +6,13 @@
package btools.mapcreator;
-public final class OsmLinkP
+public class OsmLinkP
{
/**
* The description bitmap is mainly the way description
* used to calculate the costfactor
*/
- public long descriptionBitmap;
+ public byte[] descriptionBitmap;
/**
* The target is either the next link or the target node
@@ -22,8 +22,8 @@ public final class OsmLinkP
public OsmLinkP next;
- public boolean counterLinkWritten( )
+ public final boolean counterLinkWritten( )
{
- return descriptionBitmap == 0L;
+ return descriptionBitmap == null;
}
}
diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmLinkPReverse.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmLinkPReverse.java
new file mode 100644
index 0000000..3a368da
--- /dev/null
+++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmLinkPReverse.java
@@ -0,0 +1,11 @@
+/**
+ * Dummy child of OsmLinkP just to encode the reverse bit
+ *
+ * @author ab
+ */
+package btools.mapcreator;
+
+
+public class OsmLinkPReverse extends OsmLinkP
+{
+}
diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java
index 7529e81..0b4492d 100644
--- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java
+++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java
@@ -75,9 +75,9 @@ public class OsmNodeP implements Comparable
firstlink = link;
}
- public long getNodeDecsription()
+ public byte[] getNodeDecsription()
{
- return 0L;
+ return null;
}
public void writeNodeData( DataOutputStream os ) throws IOException
@@ -92,7 +92,7 @@ public class OsmNodeP implements Comparable
os2.writeShort( getSElev() );
// hack: write node-desc as link tag (copy cycleway-bits)
- long nodeDescription = getNodeDecsription();
+ byte[] nodeDescription = getNodeDecsription();
for( OsmLinkP link0 = firstlink; link0 != null; link0 = link0.next )
{
@@ -122,13 +122,15 @@ public class OsmNodeP implements Comparable
link = link0;
}
origin = this;
- long lastDescription = 0;
+ byte[] lastDescription = null;
while( link != null )
{
+ if ( link.descriptionBitmap == null && skipDetailBit == 0 ) throw new IllegalArgumentException( "missing way description...");
+
OsmNodeP target = link.targetNode;
int tranferbit = target.isTransferNode() ? TRANSFERNODE_BITMASK : 0;
int writedescbit = link.descriptionBitmap != lastDescription ? WRITEDESC_BITMASK : 0;
- int nodedescbit = nodeDescription != 0L ? NODEDESC_BITMASK : 0;
+ int nodedescbit = nodeDescription != null ? NODEDESC_BITMASK : 0;
if ( skipDetailBit != 0 )
{
@@ -153,12 +155,17 @@ public class OsmNodeP implements Comparable
}
if ( writedescbit != 0 )
{
- os2.writeLong( link.descriptionBitmap );
+ // write the way description, code direction into the first bit
+ byte[] dbytes = link.descriptionBitmap;
+ int len = dbytes.length;
+ os2.writeByte( len );
+ os2.writeByte( link instanceof OsmLinkPReverse ? dbytes[0] | 1 : dbytes[0] );
+ if ( len > 1 ) os2.write( dbytes, 1, len-1 );
}
if ( nodedescbit != 0 )
{
- os2.writeLong( nodeDescription );
- nodeDescription = 0L;
+ os2.writeByte( nodeDescription.length ); os2.write( nodeDescription );
+ nodeDescription = null;
}
lastDescription = link.descriptionBitmap;
@@ -220,7 +227,7 @@ public class OsmNodeP implements Comparable
{
for( OsmLinkP link = firstlink; link != null; link = link.next )
{
- if ( link.targetNode == t) link.descriptionBitmap = 0L;
+ if ( link.targetNode == t) link.descriptionBitmap = null;
}
}
diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodePT.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodePT.java
index 94e048c..989c4d4 100644
--- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodePT.java
+++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodePT.java
@@ -8,7 +8,7 @@ package btools.mapcreator;
public class OsmNodePT extends OsmNodeP
{
- public long descriptionBits;
+ public byte[] descriptionBits;
public byte wayOrBits = 0; // used to propagate bike networks to nodes
@@ -16,15 +16,16 @@ public class OsmNodePT extends OsmNodeP
{
}
- public OsmNodePT( long descriptionBits )
+ public OsmNodePT( byte[] descriptionBits )
{
this.descriptionBits = descriptionBits;
}
@Override
- public long getNodeDecsription()
+ public final byte[] getNodeDecsription()
{
- return descriptionBits | (long)( (wayOrBits & 6) >> 1 );
+ return descriptionBits;
+ // return descriptionBits | (long)( (wayOrBits & 6) >> 1 ); TODO !!!!!!!!!!1
}
@Override
diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/WayCutter.java b/brouter-map-creator/src/main/java/btools/mapcreator/WayCutter.java
index 41d4a08..e1d5c0b 100644
--- a/brouter-map-creator/src/main/java/btools/mapcreator/WayCutter.java
+++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayCutter.java
@@ -100,11 +100,11 @@ public class WayCutter extends MapCreatorBase
{
boolean ok = true;
// check access and log a warning for conflicts
- expctxReport.evaluate( data.description, null );
+ expctxReport.evaluate( false, data.description, null );
boolean warn = expctxReport.getCostfactor() >= 10000.;
if ( warn )
{
- expctxCheck.evaluate( data.description, null );
+ expctxCheck.evaluate( false, data.description, null );
ok = expctxCheck.getCostfactor() < 10000.;
System.out.println( "** relation access conflict for wid = " + data.wid + " tags:" + expctxReport.getKeyValueDescription( data.description ) + " (ok=" + ok + ")" );
@@ -112,7 +112,8 @@ public class WayCutter extends MapCreatorBase
if ( ok )
{
- data.description |= 2;
+ expctxReport.addLookupValue( "longdistancecycleway", 2 );
+ data.description = expctxReport.encode();
}
}
diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/WayData.java b/brouter-map-creator/src/main/java/btools/mapcreator/WayData.java
index 23109d8..d6523cb 100644
--- a/brouter-map-creator/src/main/java/btools/mapcreator/WayData.java
+++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayData.java
@@ -13,7 +13,7 @@ import btools.util.LongList;
public class WayData extends MapCreatorBase
{
public long wid;
- public long description;
+ public byte[] description;
public LongList nodes;
public WayData( long id )
@@ -32,7 +32,7 @@ public class WayData extends MapCreatorBase
{
nodes = new LongList( 16 );
wid = readId( di) ;
- description = di.readLong();
+ int dlen = di.readByte(); description = new byte[dlen]; di.readFully( description );
for (;;)
{
long nid = readId( di );
@@ -44,7 +44,7 @@ public class WayData extends MapCreatorBase
public void writeTo( DataOutputStream dos ) throws Exception
{
writeId( dos, wid );
- dos.writeLong( description );
+ dos.writeByte( description.length ); dos.write( description );
int size = nodes.size();
for( int i=0; i < size; i++ )
{
diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java
index 2c52cb1..5dce724 100644
--- a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java
+++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java
@@ -104,7 +104,7 @@ public class WayLinker extends MapCreatorBase
@Override
public void nextNode( NodeData data ) throws Exception
{
- OsmNodeP n = data.description == 0L ? new OsmNodeP() : new OsmNodePT(data.description);
+ OsmNodeP n = data.description == null ? new OsmNodeP() : new OsmNodePT(data.description);
n.ilon = data.ilon;
n.ilat = data.ilat;
n.selev = data.selev;
@@ -132,18 +132,17 @@ public class WayLinker extends MapCreatorBase
@Override
public void nextWay( WayData way ) throws Exception
{
- long description = way.description;
- long reverseDescription = description | 1L; // (add reverse bit)
+ byte[] description = way.description;
// filter according to profile
- expctxWay.evaluate( description, null );
+ expctxWay.evaluate( false, description, null );
boolean ok = expctxWay.getCostfactor() < 10000.;
- expctxWay.evaluate( reverseDescription, null );
+ expctxWay.evaluate( true, description, null );
ok |= expctxWay.getCostfactor() < 10000.;
if ( !ok ) return;
- byte lowbyte = (byte)description;
+// byte lowbyte = (byte)description;
OsmNodeP n1 = null;
OsmNodeP n2 = null;
@@ -159,16 +158,16 @@ public class WayLinker extends MapCreatorBase
l1.descriptionBitmap = description;
n1.addLink( l1 );
- OsmLinkP l2 = new OsmLinkP();
+ OsmLinkP l2 = new OsmLinkPReverse();
l2.targetNode = n1;
- l2.descriptionBitmap = reverseDescription;
+ l2.descriptionBitmap = description;
n2.addLink( l2 );
}
if ( n2 != null )
{
- n2.wayAndBits &= lowbyte;
- if ( n2 instanceof OsmNodePT ) ((OsmNodePT)n2).wayOrBits |= lowbyte;
+// n2.wayAndBits &= lowbyte;
+// if ( n2 instanceof OsmNodePT ) ((OsmNodePT)n2).wayOrBits |= lowbyte;
}
}
}
diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/ByteDataReader.java b/brouter-mapaccess/src/main/java/btools/mapaccess/ByteDataReader.java
index b1776ff..7ad5e25 100644
--- a/brouter-mapaccess/src/main/java/btools/mapaccess/ByteDataReader.java
+++ b/brouter-mapaccess/src/main/java/btools/mapaccess/ByteDataReader.java
@@ -56,4 +56,20 @@ final class ByteDataReader
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;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder( "[" );
+ for( int i=0; i> 8) & 0xff );
ab[aboffset++] = (byte)( (v ) & 0xff );
}
-}
+
+ public void write( byte[] sa )
+ {
+ System.arraycopy( sa, 0, ab, aboffset, sa.length );
+ aboffset += sa.length;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder( "[" );
+ for( int i=0; i> 16 ) != currentILonHigh )
{
@@ -61,7 +63,7 @@ public final class OsmTransferNode
byte[] ab = new byte[size];
ByteDataWriter os = new ByteDataWriter( ab );
- currentDesc = 0;
+ currentDesc = null;
currentILonHigh = 0;
currentILatHigh = 0;
n = tn;
@@ -84,7 +86,7 @@ public final class OsmTransferNode
currentILatHigh = n.ilat >> 16;
}
os.writeByte( mode);
- if ( (mode & BIT_DESC) != 0 ) os.writeLong( currentDesc );
+ 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 );
@@ -103,19 +105,21 @@ public final class OsmTransferNode
OsmTransferNode firstNode = null;
OsmTransferNode lastNode = null;
- long currentDesc = 0;
+ 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 ) currentDesc = is.readLong();
+ 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;
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java b/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java
index b7014e1..df67b13 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java
@@ -671,7 +671,7 @@ private long startTime = 0L;
BExpressionContext expctxGlobal = new BExpressionContext( "global" );
expctxGlobal.readMetaData( new File( profileDir, "lookups.dat" ) );
expctxGlobal.parseFile( new File( profilePath ), null );
- expctxGlobal.evaluate( 1L, null );
+ expctxGlobal.evaluate( new int[0] );
boolean isFoot = 0.f != expctxGlobal.getVariableValue( "validForFoot" );
boolean isBike = 0.f != expctxGlobal.getVariableValue( "validForBikes" );
boolean isCar = 0.f != expctxGlobal.getVariableValue( "validForCars" );