From 1b8c3ccea8ba05006fe4d3a88a46cb97b70bc0c9 Mon Sep 17 00:00:00 2001 From: Arndt Date: Mon, 21 Apr 2014 12:26:06 +0200 Subject: [PATCH] network and access checks on cycle relations --- .../expressions/BExpressionContext.java | 16 ++ .../java/btools/mapcreator/OsmCutter.java | 5 + .../btools/mapcreator/RelationStatistics.java | 74 ++++++ .../java/btools/mapcreator/WayCutter.java | 49 +++- .../java/btools/mapcreator/WayLinker.java | 2 +- .../btools/mapcreator/MapcreatorTest.java | 4 +- .../src/test/resources/softaccess.brf | 21 ++ .../src/test/resources/trekking.brf | 225 ++++++++++++++++++ .../scripts/mapcreation/process_pbf_planet.sh | 2 +- misc/scripts/mapcreation/softaccess.brf | 21 ++ 10 files changed, 409 insertions(+), 10 deletions(-) create mode 100644 brouter-map-creator/src/main/java/btools/mapcreator/RelationStatistics.java create mode 100644 brouter-map-creator/src/test/resources/softaccess.brf create mode 100644 brouter-map-creator/src/test/resources/trekking.brf create mode 100644 misc/scripts/mapcreation/softaccess.brf diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java index e01d9b1..fed9010 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java @@ -168,6 +168,22 @@ public final class BExpressionContext return sb.toString(); } + public String getKeyValueDescription( long bitmap ) + { + StringBuilder sb = new StringBuilder( 200 ); + decode( lookupData, bitmap ); + for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names + { + BExpressionLookupValue[] va = lookupValues.get(inum); + String value = va[lookupData[inum]].toString(); + if ( value != null && value.length() > 0 ) + { + sb.append( " " + lookupNames.get( inum ) + "=" + value ); + } + } + return sb.toString(); + } + public void readMetaData( File lookupsFile ) { try 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 b99d6ae..b3673aa 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java @@ -174,11 +174,16 @@ public class OsmCutter extends MapCreatorBase return; } + String network = r.getTag( "network" ); + if ( network == null ) network = ""; + writeId( cyclewayDos, r.rid ); + cyclewayDos.writeUTF( network ); for ( int i=0; i" ); + + return; + } + new RelationStatistics().process( new File( args[0] ) ); + } + + public void process( File relationFileIn ) throws Exception + { + HashMap relstats = new HashMap(); + + DataInputStream dis = createInStream( relationFileIn ); + try + { + for(;;) + { + long rid = readId( dis ); + String network = dis.readUTF(); + int waycount = 0; + for(;;) + { + long wid = readId( dis ); + if ( wid == -1 ) break; + waycount++; + } + + long[] stat = relstats.get( network ); + if ( stat == null ) + { + stat = new long[2]; + relstats.put( network, stat ); + } + stat[0]++; + stat[1] += waycount; + } + } + catch( EOFException eof ) + { + dis.close(); + } + for( String network : relstats.keySet() ) + { + long[] stat = relstats.get( network ); + System.out.println( "network: " + network + " has " + stat[0] + " relations with " + stat[1] + " ways" ); + } + } + + +} 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 58a94f8..6b39f81 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/WayCutter.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayCutter.java @@ -4,8 +4,10 @@ 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,23 +22,33 @@ 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 != 4) + if (args.length != 7) { - 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 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] ) ); } - public void process( File nodeTilesIn, File wayFileIn, File wayTilesOut, File relationFileIn ) throws Exception + public void process( File nodeTilesIn, File wayFileIn, File wayTilesOut, File relationFileIn, File lookupFile, File reportProfile, File checkProfile ) 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 ); @@ -44,14 +56,24 @@ public class WayCutter extends MapCreatorBase { for(;;) { - long wid = readId( dis ); - if ( !cyclewayset.contains( wid ) ) cyclewayset.add( wid ); + 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() ); @@ -76,7 +98,20 @@ public class WayCutter extends MapCreatorBase // propagate the cycleway-bit if ( cyclewayset.contains( data.wid ) ) { - data.description |= 2; + // check access and log a warning for conflicts + expctxCheck.evaluate( data.description, null ); + boolean ok = expctxCheck.getCostfactor() < 10000.; + expctxReport.evaluate( data.description, null ); + boolean warn = expctxReport.getCostfactor() >= 10000.; + if ( warn ) + { + System.out.println( "** relation access conflict for wid = " + data.wid + " tags:" + expctxReport.getKeyValueDescription( data.description ) + " (ok=" + ok + ")" ); + } + + if ( ok ) + { + data.description |= 2; + } } long waytileset = 0; 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 9c99ed8..2c52cb1 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java @@ -64,7 +64,7 @@ public class WayLinker extends MapCreatorBase this.borderFileIn = borderFileIn; this.dataTilesSuffix = dataTilesSuffix; - // read lookup file to get the lookup-version + // read lookup + profile for lookup-version + access-filter expctxWay = new BExpressionContext("way"); expctxWay.readMetaData( lookupFile ); lookupVersion = expctxWay.lookupVersion; diff --git a/brouter-map-creator/src/test/java/btools/mapcreator/MapcreatorTest.java b/brouter-map-creator/src/test/java/btools/mapcreator/MapcreatorTest.java index 01e9ab5..5075af7 100644 --- a/brouter-map-creator/src/test/java/btools/mapcreator/MapcreatorTest.java +++ b/brouter-map-creator/src/test/java/btools/mapcreator/MapcreatorTest.java @@ -34,9 +34,11 @@ public class MapcreatorTest new NodeFilter().process( nodetiles, wayFile, ftiles ); // run WayCutter + File profileReport = new File( workingDir, "trekking.brf" ); + File profileCheck = new File( workingDir, "softaccess.brf" ); File waytiles = new File( tmpdir, "waytiles" ); waytiles.mkdir(); - new WayCutter().process( ftiles, wayFile, waytiles, relFile ); + new WayCutter().process( ftiles, wayFile, waytiles, relFile, lookupFile, profileReport, profileCheck ); // run WayCutter5 File waytiles55 = new File( tmpdir, "waytiles55" ); diff --git a/brouter-map-creator/src/test/resources/softaccess.brf b/brouter-map-creator/src/test/resources/softaccess.brf new file mode 100644 index 0000000..ee47e41 --- /dev/null +++ b/brouter-map-creator/src/test/resources/softaccess.brf @@ -0,0 +1,21 @@ +# *** soft-access check used to prevent setting the cyclewaybit on motorroads + +---context:global # following code refers to global config + +assign validForBikes 1 + +---context:way # following code refers to way-tags + +assign costfactor + + # + # exclude motorways, proposed roads and motorroads + # + switch or highway=motorway highway=motorway_link 100000 + switch highway=proposed 100000 + switch motorroad=yes 100000 + + 1.0 + +---context:node # following code refers to node tags + diff --git a/brouter-map-creator/src/test/resources/trekking.brf b/brouter-map-creator/src/test/resources/trekking.brf new file mode 100644 index 0000000..28a59ec --- /dev/null +++ b/brouter-map-creator/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/misc/scripts/mapcreation/process_pbf_planet.sh b/misc/scripts/mapcreation/process_pbf_planet.sh index 6bf9af1..56f762f 100644 --- a/misc/scripts/mapcreation/process_pbf_planet.sh +++ b/misc/scripts/mapcreation/process_pbf_planet.sh @@ -20,7 +20,7 @@ mkdir ftiles /java/bin/java -Xmx512M -Xms512M -Xmn32M -cp ../brouter.jar -Ddeletetmpfiles=true -DuseDenseMaps=true btools.mapcreator.NodeFilter nodetiles ways.dat ftiles mkdir waytiles -/java/bin/java -Xmx2600M -Xms2600M -Xmn32M -cp ../brouter.jar -Ddeletetmpfiles=true -DuseDenseMaps=true btools.mapcreator.WayCutter ftiles ways.dat waytiles cycleways.dat +/java/bin/java -Xmx2600M -Xms2600M -Xmn32M -cp ../brouter.jar -Ddeletetmpfiles=true -DuseDenseMaps=true btools.mapcreator.WayCutter ftiles ways.dat waytiles cycleways.dat ../lookups.dat ../trekking.brf ../softaccess.brf mkdir waytiles55 /java/bin/java -Xmx2600M -Xms2600M -Xmn32M -cp ../brouter.jar -Ddeletetmpfiles=true -DuseDenseMaps=true btools.mapcreator.WayCutter5 ftiles waytiles waytiles55 bordernids.dat diff --git a/misc/scripts/mapcreation/softaccess.brf b/misc/scripts/mapcreation/softaccess.brf new file mode 100644 index 0000000..ee47e41 --- /dev/null +++ b/misc/scripts/mapcreation/softaccess.brf @@ -0,0 +1,21 @@ +# *** soft-access check used to prevent setting the cyclewaybit on motorroads + +---context:global # following code refers to global config + +assign validForBikes 1 + +---context:way # following code refers to way-tags + +assign costfactor + + # + # exclude motorways, proposed roads and motorroads + # + switch or highway=motorway highway=motorway_link 100000 + switch highway=proposed 100000 + switch motorroad=yes 100000 + + 1.0 + +---context:node # following code refers to node tags +