From ba867b477951aa379e90058057d658cee52167a3 Mon Sep 17 00:00:00 2001 From: Arndt Date: Thu, 22 May 2014 20:26:20 +0200 Subject: [PATCH] variable length tag descriptions (second thought) --- .../src/main/java/btools/router/OsmPath.java | 2 +- .../expressions/BExpressionContext.java | 75 +++-- .../btools/expressions/EncodeDecodeTest.java | 12 +- .../src/test/resources/dummy.txt | 1 + .../src/test/resources/lookups.dat | 317 ------------------ .../src/test/resources/trekking.brf | 225 ------------- .../java/btools/mapcreator/OsmCutter.java | 4 +- .../main/java/btools/mapcreator/OsmNodeP.java | 4 +- .../btools/mapcreator/RelationMerger.java | 136 ++++++++ .../java/btools/mapcreator/WayCutter.java | 74 +--- .../java/btools/mapcreator/WayLinker.java | 24 +- .../btools/mapcreator/MapcreatorTest.java | 17 +- .../src/test/resources/car-test.brf | 107 ------ .../src/test/resources/lookups.dat | 317 ------------------ .../src/test/resources/trekking.brf | 225 ------------- .../java/btools/util/BitCoderContext.java | 96 ++++++ .../java/btools/util/BitCoderContextTest.java | 28 ++ .../test/resources => misc/profiles2}/all.brf | 36 +- misc/profiles2/lookups.dat | 6 +- .../profiles2}/softaccess.brf | 0 20 files changed, 372 insertions(+), 1334 deletions(-) create mode 100644 brouter-expressions/src/test/resources/dummy.txt delete mode 100644 brouter-expressions/src/test/resources/lookups.dat delete mode 100644 brouter-expressions/src/test/resources/trekking.brf create mode 100644 brouter-map-creator/src/main/java/btools/mapcreator/RelationMerger.java delete mode 100644 brouter-map-creator/src/test/resources/car-test.brf delete mode 100644 brouter-map-creator/src/test/resources/lookups.dat delete mode 100644 brouter-map-creator/src/test/resources/trekking.brf create mode 100644 brouter-util/src/main/java/btools/util/BitCoderContext.java create mode 100644 brouter-util/src/test/java/btools/util/BitCoderContextTest.java rename {brouter-map-creator/src/test/resources => misc/profiles2}/all.brf (95%) rename {brouter-map-creator/src/test/resources => misc/profiles2}/softaccess.brf (100%) diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java index e63211b..e8fdf2d 100644 --- a/brouter-core/src/main/java/btools/router/OsmPath.java +++ b/brouter-core/src/main/java/btools/router/OsmPath.java @@ -316,7 +316,7 @@ final class OsmPath implements OsmLinkHolder if ( targetNode.nodeDescription != null ) { rc.messageHandler.setCurrentPos( targetNode.ilon, targetNode.ilat ); - rc.expctxNode.evaluate( false, targetNode.nodeDescription, rc.messageHandler ); + rc.expctxNode.evaluate( rc.expctxWay.getNodeAccessGranted() != 0. , targetNode.nodeDescription, rc.messageHandler ); float initialcost = rc.expctxNode.getInitialcost(); if ( initialcost >= 1000000. ) { diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java index ac0c88c..9477abf 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java @@ -17,7 +17,8 @@ import java.util.Map; import java.util.StringTokenizer; import java.util.TreeMap; -import btools.util.Crc32; +import btools.util.*; + public final class BExpressionContext { @@ -61,14 +62,17 @@ public final class BExpressionContext private int costfactorIdx; private int turncostIdx; private int initialcostIdx; + private int nodeaccessgrantedIdx; private float[] _arrayCostfactor; private float[] _arrayTurncost; private float[] _arrayInitialcost; + private float[] _arrayNodeAccessGranted; public float getCostfactor() { return _arrayCostfactor[currentHashBucket]; } public float getTurncost() { return _arrayTurncost[currentHashBucket]; } public float getInitialcost() { return _arrayInitialcost[currentHashBucket]; } + public float getNodeAccessGranted() { return _arrayNodeAccessGranted[currentHashBucket]; } private int linenr; @@ -93,6 +97,7 @@ public final class BExpressionContext _arrayCostfactor = new float[hashSize]; _arrayTurncost = new float[hashSize]; _arrayInitialcost = new float[hashSize]; + _arrayNodeAccessGranted = new float[hashSize]; } @@ -107,59 +112,55 @@ public final class BExpressionContext 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); + BitCoderContext ctx = new BitCoderContext( abBuf ); + ctx.encodeBit( ld[0] != 0 ); + + int skippedTags = 0; // 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 ) + if ( d == 0 ) { - if ( bm == 0x100 ) { bm = 1; abBuf[++idx] = 0; } - if ( (d & im) != 0 ) abBuf[idx] |= bm; - n >>= 1; - bm <<= 1; - im <<= 1; + skippedTags++; + continue; } + int n = lookupValues.get(inum).length - 1; + if ( n == 2 ) { n = 1; d = d == 2 ? 1 : 0; } // 1-bit encoding for booleans + ctx.encodeDistance( skippedTags ); + skippedTags = 0; + ctx.encode( n, d ); } - idx++; - byte[] ab = new byte[idx]; - System.arraycopy( abBuf, 0, ab, 0, idx ); + ctx.encodeDistance( skippedTags ); + int len = ctx.getEncodedLength(); + byte[] ab = new byte[len]; + System.arraycopy( abBuf, 0, ab, 0, len ); return ab; } + + /** * decode a byte-array into a lookup data array */ public void decode( int[] ld, byte[] ab ) { + BitCoderContext ctx = new BitCoderContext(ab); + // 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; + ld[0] = ctx.decodeBit() ? 2 : 0; // all others are generic for( int inum = 1; inum < lookupValues.size(); inum++ ) // loop over lookup names { + int skip = ctx.decodeDistance(); + while ( skip-- > 0 ) ld[inum++] = 0; + if ( inum >= lookupValues.size() ) break; int nv = lookupValues.get(inum).length; int n = nv == 3 ? 1 : nv-1; // 1-bit encoding for booleans - 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; - } + + int d = ctx.decode( n ); if ( nv == 3 && d == 1 ) d = 2; // 1-bit encoding for booleans ld[inum] = d; } @@ -212,7 +213,8 @@ public final class BExpressionContext int parsedLines = 0; boolean ourContext = false; - addLookupValue( "reversedirection", "yes", null ); + if ( "way".equals( context ) ) addLookupValue( "reversedirection", "yes", null ); + else if ( "node".equals( context ) ) addLookupValue( "nodeaccessgranted", "yes", null ); for(;;) { String line = br.readLine(); @@ -237,6 +239,7 @@ public final class BExpressionContext int idx = name.indexOf( ';' ); if ( idx >= 0 ) name = name.substring( 0, idx ); if ( "reversedirection".equals( name ) ) continue; // this is hardcoded + if ( "nodeaccessgranted".equals( name ) ) continue; // this is hardcoded BExpressionLookupValue newValue = addLookupValue( name, value, null ); // add aliases @@ -323,6 +326,7 @@ public final class BExpressionContext _arrayCostfactor[currentHashBucket] = variableData[costfactorIdx]; _arrayTurncost[currentHashBucket] = variableData[turncostIdx]; _arrayInitialcost[currentHashBucket] = variableData[initialcostIdx]; + _arrayNodeAccessGranted[currentHashBucket] = variableData[nodeaccessgrantedIdx]; _receiver = null; } @@ -480,6 +484,12 @@ public final class BExpressionContext lookupData[inum] = valueIndex; } + public boolean getBooleanLookupValue( String name ) + { + Integer num = lookupNumbers.get( name ); + return num != null && lookupData[num.intValue()] != 0; + } + public void parseFile( File file, String readOnlyContext ) { try @@ -500,6 +510,7 @@ public final class BExpressionContext costfactorIdx = getVariableIdx( "costfactor", true ); turncostIdx = getVariableIdx( "turncost", true ); initialcostIdx = getVariableIdx( "initialcost", true ); + nodeaccessgrantedIdx = getVariableIdx( "nodeaccessgranted", true ); expressionList = _parseFile( file ); float[] readOnlyData = variableData; diff --git a/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java b/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java index 1cb2f27..16e919a 100644 --- a/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java +++ b/brouter-expressions/src/test/java/btools/expressions/EncodeDecodeTest.java @@ -12,15 +12,15 @@ 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(); + URL testpurl = this.getClass().getResource( "/dummy.txt" ); + File workingDir = new File(testpurl.getFile()).getParentFile(); + File profileDir = new File( workingDir, "/../../../misc/profiles2" ); + File lookupFile = new File( profileDir, "lookups.dat" ); // read lookup.dat + trekking.brf BExpressionContext expctxWay = new BExpressionContext("way"); expctxWay.readMetaData( lookupFile ); - expctxWay.parseFile( new File( workingDir, "trekking.brf" ), "global" ); + expctxWay.parseFile( new File( profileDir, "trekking.brf" ), "global" ); String[] tags = { "highway=residential", "oneway=yes", "reversedirection=yes" }; @@ -41,6 +41,6 @@ public class EncodeDecodeTest expctxWay.evaluate( false, description, null ); float costfactor = expctxWay.getCostfactor(); - Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.1 ) > 0.00001 ); + Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.15 ) < 0.00001 ); } } diff --git a/brouter-expressions/src/test/resources/dummy.txt b/brouter-expressions/src/test/resources/dummy.txt new file mode 100644 index 0000000..19b2bbb --- /dev/null +++ b/brouter-expressions/src/test/resources/dummy.txt @@ -0,0 +1 @@ +this is just a dummy file to have a test resource location \ No newline at end of file diff --git a/brouter-expressions/src/test/resources/lookups.dat b/brouter-expressions/src/test/resources/lookups.dat deleted file mode 100644 index af197c9..0000000 --- a/brouter-expressions/src/test/resources/lookups.dat +++ /dev/null @@ -1,317 +0,0 @@ ----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 deleted file mode 100644 index 28a59ec..0000000 --- a/brouter-expressions/src/test/resources/trekking.brf +++ /dev/null @@ -1,225 +0,0 @@ -# *** 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/OsmCutter.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java index b3673aa..74f1e02 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java @@ -168,8 +168,9 @@ public class OsmCutter extends MapCreatorBase relsParsed++; checkStats(); + String route = r.getTag( "route" ); // filter out non-cycle relations - if ( ! "bicycle".equals( r.getTag( "route" ) ) ) + if ( route == null ) { return; } @@ -177,6 +178,7 @@ public class OsmCutter extends MapCreatorBase String network = r.getTag( "network" ); if ( network == null ) network = ""; writeId( cyclewayDos, r.rid ); + cyclewayDos.writeUTF( route ); cyclewayDos.writeUTF( network ); for ( int i=0; i public boolean isBorder = false; + public final static int BRIDGE_AND_BIT = 1; + public final static int TUNNEL_AND_BIT = 2; public byte wayAndBits = -1; // use for bridge/tunnel logic @@ -59,7 +61,7 @@ public class OsmNodeP implements Comparable public short getSElev() { // if all bridge or all tunnel, elevation=no-data - return (wayAndBits & 24) == 0 ? selev : Short.MIN_VALUE; + return (wayAndBits & ( BRIDGE_AND_BIT | TUNNEL_AND_BIT ) ) == 0 ? selev : Short.MIN_VALUE; } public double getElev() diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/RelationMerger.java b/brouter-map-creator/src/main/java/btools/mapcreator/RelationMerger.java new file mode 100644 index 0000000..db28f4c --- /dev/null +++ b/brouter-map-creator/src/main/java/btools/mapcreator/RelationMerger.java @@ -0,0 +1,136 @@ +package btools.mapcreator; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.File; +import java.util.HashMap; + +import btools.expressions.BExpressionContext; +import btools.util.CompactLongSet; +import btools.util.FrozenLongSet; + +/** + * RelationMerger does 1 step in map processing: + * + * - enrich ways with relation information + * + * @author ab + */ +public class RelationMerger extends MapCreatorBase +{ + private HashMap routesets; + private CompactLongSet routesetall; + private BExpressionContext expctxReport; + private BExpressionContext expctxCheck; + + private DataOutputStream wayOutStream; + + public static void main(String[] args) throws Exception + { + System.out.println("*** RelationMerger: merge relation bits into ways" ); + if (args.length != 6) + { + System.out.println("usage: java RelationMerger " ); + + return; + } + new RelationMerger().process( new File( args[0] ), new File( args[1] ), new File( args[2] ), new File( args[3] ), new File( args[4] ), new File( args[5] ) ); + } + + public void process( File wayFileIn, File wayFileOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile ) throws Exception + { + // read lookup + profile for relation access-check + expctxReport = new BExpressionContext("way"); + expctxReport.readMetaData( lookupFile ); + expctxReport.parseFile( reportProfile, "global" ); + expctxCheck = new BExpressionContext("way"); + expctxCheck.readMetaData( lookupFile ); + expctxCheck.parseFile( checkProfile, "global" ); + + // *** read the relation file into sets for each processed tag + routesets = new HashMap(); + routesetall = new CompactLongSet(); + DataInputStream dis = createInStream( relationFileIn ); + try + { + for(;;) + { + long rid = readId( dis ); + String route = dis.readUTF(); + String network = dis.readUTF(); + + String tagname = "route_" + route + "_" + network; + CompactLongSet routeset = null; + if ( expctxCheck.getLookupNameIdx(tagname) >= 0 ) + { + routeset = routesets.get( tagname ); + if ( routeset == null ) + { + routeset = new CompactLongSet(); + routesets.put( tagname, routeset ); + } + } + + for(;;) + { + long wid = readId( dis ); + if ( wid == -1 ) break; + if ( routeset != null && !routeset.contains( wid ) ) + { + routeset.add( wid ); + routesetall.add( wid ); + } + } + } + } + catch( EOFException eof ) + { + dis.close(); + } + for( String tagname : routesets.keySet() ) + { + CompactLongSet routeset = new FrozenLongSet( routesets.get( tagname ) ); + routesets.put( tagname, routeset ); + System.out.println( "marked " + routeset.size() + " ways for tag: " + tagname ); + } + + // *** finally process the way-file + wayOutStream = createOutStream( wayFileOut ); + new WayIterator( this, true ).processFile( wayFileIn ); + wayOutStream.close(); + } + + @Override + public void nextWay( WayData data ) throws Exception + { + // propagate the route-bits + if ( routesetall.contains( data.wid ) ) + { + boolean ok = true; + // check access and log a warning for conflicts + expctxReport.evaluate( false, data.description, null ); + boolean warn = expctxReport.getCostfactor() >= 10000.; + if ( warn ) + { + 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 + ")" ); + } + + if ( ok ) + { + for( String tagname : routesets.keySet() ) + { + CompactLongSet routeset = routesets.get( tagname ); + if ( routeset.contains( data.wid ) ) expctxReport.addLookupValue( tagname, 2 ); + } + data.description = expctxReport.encode(); + } + } + + data.writeTo( wayOutStream ); + } + +} 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 e1d5c0b..dceea21 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/WayCutter.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayCutter.java @@ -1,13 +1,8 @@ package btools.mapcreator; -import java.io.DataInputStream; -import java.io.EOFException; import java.io.File; -import btools.expressions.BExpressionContext; -import btools.util.CompactLongSet; import btools.util.DenseLongMap; -import btools.util.FrozenLongSet; import btools.util.TinyDenseLongMap; /** @@ -20,63 +15,24 @@ import btools.util.TinyDenseLongMap; */ public class WayCutter extends MapCreatorBase { - private CompactLongSet cyclewayset; private DenseLongMap tileIndexMap; - private BExpressionContext expctxReport; - private BExpressionContext expctxCheck; public static void main(String[] args) throws Exception { System.out.println("*** WayCutter: Soft-Cut way-data into tiles"); - if (args.length != 7) + if (args.length != 4) { - System.out.println("usage: java WayCutter " ); + System.out.println("usage: java WayCutter " ); return; } - new WayCutter().process( new File( args[0] ), new File( args[1] ), new File( args[2] ), new File( args[3] ), new File( args[4] ), new File( args[5] ), new File( args[6] ) ); + new WayCutter().process( new File( args[0] ), new File( args[1] ), new File( args[2] ), new File( args[3] ) ); } - public void process( File nodeTilesIn, File wayFileIn, File wayTilesOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile ) throws Exception + public void process( File nodeTilesIn, File wayFileIn, File wayTilesOut, File relationFileIn ) throws Exception { this.outTileDir = wayTilesOut; - // read lookup + profile for relation access-check - expctxReport = new BExpressionContext("way"); - expctxReport.readMetaData( lookupFile ); - expctxReport.parseFile( reportProfile, "global" ); - expctxCheck = new BExpressionContext("way"); - expctxCheck.readMetaData( lookupFile ); - expctxCheck.parseFile( checkProfile, "global" ); - - // *** read the relation file into a set (currently cycleway processing only) - cyclewayset = new CompactLongSet(); - DataInputStream dis = createInStream( relationFileIn ); - try - { - for(;;) - { - long rid = readId( dis ); - String network = dis.readUTF(); - boolean goodNetwork = "lcn".equals( network ) || "rcn".equals( network ) || "ncn".equals( network ) || "icn".equals( network ); - - for(;;) - { - long wid = readId( dis ); - if ( wid == -1 ) break; - if ( goodNetwork && !cyclewayset.contains( wid ) ) cyclewayset.add( wid ); - } - } - } - catch( EOFException eof ) - { - dis.close(); - } - - cyclewayset = new FrozenLongSet( cyclewayset ); - System.out.println( "marked cycleways: " + cyclewayset.size() ); - - // *** read all nodes into tileIndexMap tileIndexMap = Boolean.getBoolean( "useDenseMaps" ) ? new DenseLongMap( 6 ) : new TinyDenseLongMap(); new NodeIterator( this, false ).processDir( nodeTilesIn, ".tlf" ); @@ -95,28 +51,6 @@ public class WayCutter extends MapCreatorBase @Override public void nextWay( WayData data ) throws Exception { - // propagate the cycleway-bit - if ( cyclewayset.contains( data.wid ) ) - { - boolean ok = true; - // check access and log a warning for conflicts - expctxReport.evaluate( false, data.description, null ); - boolean warn = expctxReport.getCostfactor() >= 10000.; - if ( warn ) - { - 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 + ")" ); - } - - if ( ok ) - { - expctxReport.addLookupValue( "longdistancecycleway", 2 ); - data.description = expctxReport.encode(); - } - } - long waytileset = 0; int nnodes = data.nodes.size(); 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 5dce724..0aa69dd 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java @@ -1,11 +1,19 @@ package btools.mapcreator; -import java.io.*; -import java.util.*; - -import btools.util.*; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.RandomAccessFile; +import java.util.Collections; +import java.util.List; import btools.expressions.BExpressionContext; +import btools.util.CompactLongMap; +import btools.util.CompactLongSet; +import btools.util.Crc32; +import btools.util.FrozenLongMap; +import btools.util.FrozenLongSet; +import btools.util.LazyArrayOfLists; /** * WayLinker finally puts the pieces together @@ -139,11 +147,13 @@ public class WayLinker extends MapCreatorBase boolean ok = expctxWay.getCostfactor() < 10000.; expctxWay.evaluate( true, description, null ); ok |= expctxWay.getCostfactor() < 10000.; + + byte bridgeTunnel = 0; + if ( expctxWay.getBooleanLookupValue( "bridge" ) ) bridgeTunnel |= OsmNodeP.BRIDGE_AND_BIT; + if ( expctxWay.getBooleanLookupValue( "tunnel" ) ) bridgeTunnel |= OsmNodeP.TUNNEL_AND_BIT; if ( !ok ) return; -// byte lowbyte = (byte)description; - OsmNodeP n1 = null; OsmNodeP n2 = null; for (int i=0; i=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-util/src/main/java/btools/util/BitCoderContext.java b/brouter-util/src/main/java/btools/util/BitCoderContext.java new file mode 100644 index 0000000..1c3bbe0 --- /dev/null +++ b/brouter-util/src/main/java/btools/util/BitCoderContext.java @@ -0,0 +1,96 @@ +package btools.util; + + public final class BitCoderContext + { + private byte[] ab; + private int idx = -1; + private int bm = 0x100 ; // byte mask + private int b; + + public BitCoderContext( byte[] ab ) + { + this.ab = ab; + } + + // encode a distance with a variable bit length + // (poor mans huffman tree) + // 1 -> 0 + // 01 -> 1 + following 1-bit word ( 1..2 ) + // 001 -> 3 + following 2-bit word ( 3..6 ) + // 0001 -> 7 + following 3-bit word ( 7..14 ) etc. + + public void encodeDistance( int value ) + { + int range = 0; + while ( value > range ) + { + encodeBit( false ); + value -= range+1; + range = 2*range + 1; + } + encodeBit( true ); + encode( range, value ); + } + + // twin to encodeDistance + public int decodeDistance() + { + int range = 0; + int value = 0; + while ( !decodeBit() ) + { + value += range+1; + range = 2*range + 1; + } + return value + decode( range ); + } + + public void encodeBit( boolean value ) + { + if ( bm == 0x100 ) { bm = 1; ab[++idx] = 0; } + if ( value ) ab[idx] |= bm; + bm <<= 1; + } + + public boolean decodeBit() + { + if ( bm == 0x100 ) { bm = 1; b = ab[++idx]; } + boolean value = ( (b & bm) != 0 ); + bm <<= 1; + return value; + } + + // encode a symbol with number of bits according to maxvalue + public void encode( int max, int value ) + { + int im = 1; // integer mask + while( max != 0 ) + { + if ( bm == 0x100 ) { bm = 1; ab[++idx] = 0; } + if ( (value & im) != 0 ) ab[idx] |= bm; + max >>= 1; + bm <<= 1; + im <<= 1; + } + } + + public int getEncodedLength() + { + return idx+1; + } + + public int decode( int max ) + { + int value = 0; + int im = 1; // integer mask + while( max != 0 ) + { + if ( bm == 0x100 ) { bm = 1; b = ab[++idx]; } + if ( (b & bm) != 0 ) value |= im; + max >>= 1; + bm <<= 1; + im <<= 1; + } + return value; + } + } diff --git a/brouter-util/src/test/java/btools/util/BitCoderContextTest.java b/brouter-util/src/test/java/btools/util/BitCoderContextTest.java new file mode 100644 index 0000000..735f0c0 --- /dev/null +++ b/brouter-util/src/test/java/btools/util/BitCoderContextTest.java @@ -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 BitCoderContextTest +{ + @Test + public void distanceEncodeDecodeTest() + { + byte[] ab = new byte[4000]; + BitCoderContext ctx = new BitCoderContext( ab ); + for( int i=0; i<1000; i++ ) + { + ctx.encodeDistance( i ); + } + ctx = new BitCoderContext( ab ); + + for( int i=0; i<1000; i++ ) + { + int value = ctx.decodeDistance(); + Assert.assertTrue( "distance value mismatch", value == i ); + } + } +} diff --git a/brouter-map-creator/src/test/resources/all.brf b/misc/profiles2/all.brf similarity index 95% rename from brouter-map-creator/src/test/resources/all.brf rename to misc/profiles2/all.brf index a5258fa..11de5a5 100644 --- a/brouter-map-creator/src/test/resources/all.brf +++ b/misc/profiles2/all.brf @@ -1,18 +1,18 @@ ----context:global # following code refers to global config - -# the elevation parameters - -assign downhillcost 0 -assign downhillcutoff 1.5 -assign uphillcost 0 -assign uphillcutoff 1.5 - ----context:way # following code refers to way-tags - -assign turncost 0 -assign initialcost 0 -assign costfactor 1 - ----context:node # following code refers to node tags - -assign initialcost 0 +---context:global # following code refers to global config + +# the elevation parameters + +assign downhillcost 0 +assign downhillcutoff 1.5 +assign uphillcost 0 +assign uphillcutoff 1.5 + +---context:way # following code refers to way-tags + +assign turncost 0 +assign initialcost 0 +assign costfactor 1 + +---context:node # following code refers to node tags + +assign initialcost 0 diff --git a/misc/profiles2/lookups.dat b/misc/profiles2/lookups.dat index af197c9..e0dcb02 100644 --- a/misc/profiles2/lookups.dat +++ b/misc/profiles2/lookups.dat @@ -179,7 +179,11 @@ lcn;0000018999 yes longdistancecycleway;0000000001 yes -reversedirection;0000000001 yes +route_bicycle_icn;0000000001 yes +route_bicycle_ncn;0000000001 yes +route_bicycle_rcn;0000000001 yes +route_bicycle_lcn;0000000001 yes +route_bicycle_all;0000000001 yes ---context:node diff --git a/brouter-map-creator/src/test/resources/softaccess.brf b/misc/profiles2/softaccess.brf similarity index 100% rename from brouter-map-creator/src/test/resources/softaccess.brf rename to misc/profiles2/softaccess.brf