This commit is contained in:
Arndt 2015-04-03 11:09:09 +02:00
commit 53c3df66f5
9 changed files with 359 additions and 150 deletions

View file

@ -26,6 +26,9 @@ import btools.util.FrozenLongMap;
public final class OsmTrack public final class OsmTrack
{ {
// csv-header-line
private static final String MESSAGES_HEADER = "Longitude\tLatitude\tElevation\tDistance\tCostPerKm\tElevCost\tTurnCost\tNodeCost\tInitialCost\tOsmTags";
public MatchedWaypoint endPoint; public MatchedWaypoint endPoint;
public long[] nogoChecksums; public long[] nogoChecksums;
@ -220,7 +223,7 @@ public final class OsmTrack
sb.append( " xmlns=\"http://www.topografix.com/GPX/1/1\" \n" ); sb.append( " xmlns=\"http://www.topografix.com/GPX/1/1\" \n" );
sb.append( " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" ); sb.append( " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" );
sb.append( " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n" ); sb.append( " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n" );
sb.append( " creator=\"BRouter-1.1\" version=\"1.1\">\n" ); sb.append( " creator=\"BRouter-1.2\" version=\"1.1\">\n" );
sb.append( " <trk>\n" ); sb.append( " <trk>\n" );
sb.append(" <name>").append(name).append("</name>\n"); sb.append(" <name>").append(name).append("</name>\n");
sb.append( " <trkseg>\n" ); sb.append( " <trkseg>\n" );
@ -304,7 +307,19 @@ public final class OsmTrack
sb.append( " \"track-length\": \"" ).append( distance ).append( "\",\n" ); sb.append( " \"track-length\": \"" ).append( distance ).append( "\",\n" );
sb.append( " \"filtered ascend\": \"" ).append( ascend ).append( "\",\n" ); sb.append( " \"filtered ascend\": \"" ).append( ascend ).append( "\",\n" );
sb.append( " \"plain-ascend\": \"" ).append( plainAscend ).append( "\",\n" ); sb.append( " \"plain-ascend\": \"" ).append( plainAscend ).append( "\",\n" );
sb.append( " \"cost\": \"" ).append( cost ).append( "\"\n" ); sb.append( " \"cost\": \"" ).append( cost ).append( "\",\n" );
sb.append( " \"messages\": [\n" );
sb.append( " [\"").append( MESSAGES_HEADER.replaceAll("\t", "\", \"") ).append( "\"],\n" );
for( OsmPathElement n : nodes )
{
if ( n.message != null )
{
sb.append( " [\"").append( n.message.replaceAll("\t", "\", \"") ).append( "\"],\n" );
}
}
sb.deleteCharAt( sb.lastIndexOf( "," ) );
sb.append( " ]\n" );
sb.append( " },\n" ); sb.append( " },\n" );
if ( iternity != null ) if ( iternity != null )
@ -361,10 +376,7 @@ public final class OsmTrack
public void writeMessages( BufferedWriter bw, RoutingContext rc ) throws Exception public void writeMessages( BufferedWriter bw, RoutingContext rc ) throws Exception
{ {
// csv-header-line dumpLine( bw, MESSAGES_HEADER );
String header = "Longitude\tLatitude\tElevation\tDistance\tCostPerKm\tElevCost\tTurnCost\tNodeCost\tInitialCost\tOsmTags";
dumpLine( bw, header );
for( OsmPathElement n : nodes ) for( OsmPathElement n : nodes )
{ {
if ( n.message != null ) if ( n.message != null )

View file

@ -1,5 +1,6 @@
package btools.expressions; package btools.expressions;
import java.util.StringTokenizer;
final class BExpression final class BExpression
{ {
@ -26,12 +27,28 @@ final class BExpression
private float numberValue; private float numberValue;
private int variableIdx; private int variableIdx;
private int lookupNameIdx; private int lookupNameIdx;
private int lookupValueIdx; private int[] lookupValueIdxArray;
// Parse the expression and all subexpression // Parse the expression and all subexpression
public static BExpression parse( BExpressionContext ctx, int level ) throws Exception public static BExpression parse( BExpressionContext ctx, int level ) throws Exception
{ {
return parse( ctx, level, null );
}
private static BExpression parse( BExpressionContext ctx, int level, String optionalToken ) throws Exception
{
boolean brackets = false;
String operator = ctx.parseToken(); String operator = ctx.parseToken();
if ( optionalToken != null && optionalToken.equals( operator ) )
{
operator = ctx.parseToken();
}
if ( "(".equals( operator ) )
{
brackets = true;
operator = ctx.parseToken();
}
if ( operator == null ) if ( operator == null )
{ {
if ( level == 0 ) return null; if ( level == 0 ) return null;
@ -48,11 +65,17 @@ final class BExpression
BExpression exp = new BExpression(); BExpression exp = new BExpression();
int nops = 3; int nops = 3;
boolean ifThenElse = false;
if ( "switch".equals( operator ) ) if ( "switch".equals( operator ) )
{ {
exp.typ = SWITCH_EXP; exp.typ = SWITCH_EXP;
} }
else if ( "if".equals( operator ) )
{
exp.typ = SWITCH_EXP;
ifThenElse = true;
}
else else
{ {
nops = 2; // check binary expressions nops = 2; // check binary expressions
@ -105,24 +128,42 @@ final class BExpression
{ {
exp.typ = LOOKUP_EXP; exp.typ = LOOKUP_EXP;
String name = operator.substring( 0, idx ); String name = operator.substring( 0, idx );
String value = operator.substring( idx+1 ); String values = operator.substring( idx+1 );
exp.lookupNameIdx = ctx.getLookupNameIdx( name ); exp.lookupNameIdx = ctx.getLookupNameIdx( name );
if ( exp.lookupNameIdx < 0 ) if ( exp.lookupNameIdx < 0 )
{ {
throw new IllegalArgumentException( "unknown lookup name: " + name ); throw new IllegalArgumentException( "unknown lookup name: " + name );
} }
exp.lookupValueIdx = ctx.getLookupValueIdx( exp.lookupNameIdx, value ); StringTokenizer tk = new StringTokenizer( values, "|" );
if ( exp.lookupValueIdx < 0 ) int nt = tk.countTokens();
int nt2 = nt == 0 ? 1 : nt;
exp.lookupValueIdxArray = new int[nt2];
for( int ti=0; ti<nt2; ti++ )
{
String value = ti < nt ? tk.nextToken() : "";
exp.lookupValueIdxArray[ti] = ctx.getLookupValueIdx( exp.lookupNameIdx, value );
if ( exp.lookupValueIdxArray[ti] < 0 )
{ {
throw new IllegalArgumentException( "unknown lookup value: " + value ); throw new IllegalArgumentException( "unknown lookup value: " + value );
} }
} }
}
else if ( (idx = ctx.getVariableIdx( operator, false )) >= 0 ) else if ( (idx = ctx.getVariableIdx( operator, false )) >= 0 )
{ {
exp.typ = VARIABLE_EXP; exp.typ = VARIABLE_EXP;
exp.variableIdx = idx; exp.variableIdx = idx;
} }
else if ( "true".equals( operator ) )
{
exp.numberValue = 1.f;
exp.typ = NUMBER_EXP;
}
else if ( "false".equals( operator ) )
{
exp.numberValue = 0.f;
exp.typ = NUMBER_EXP;
}
else else
{ {
try try
@ -139,12 +180,36 @@ final class BExpression
} }
} }
// parse operands // parse operands
if ( nops > 0 ) exp.op1 = BExpression.parse( ctx, level+1 ); if ( nops > 0 )
if ( nops > 1 ) exp.op2 = BExpression.parse( ctx, level+1 ); {
if ( nops > 2 ) exp.op3 = BExpression.parse( ctx, level+1 ); exp.op1 = BExpression.parse( ctx, level+1, exp.typ == ASSIGN_EXP ? "=" : null );
}
if ( nops > 1 )
{
if ( ifThenElse ) checkExpectedToken( ctx, "then" );
exp.op2 = BExpression.parse( ctx, level+1, null );
}
if ( nops > 2 )
{
if ( ifThenElse ) checkExpectedToken( ctx, "else" );
exp.op3 = BExpression.parse( ctx, level+1, null );
}
if ( brackets )
{
checkExpectedToken( ctx, ")" );
}
return exp; return exp;
} }
private static void checkExpectedToken( BExpressionContext ctx, String expected ) throws Exception
{
String token = ctx.parseToken();
if ( ! expected.equals( token ) )
{
throw new IllegalArgumentException( "unexpected token: " + token + ", expected: " + expected );
}
}
// Evaluate the expression // Evaluate the expression
public float evaluate( BExpressionContext ctx ) public float evaluate( BExpressionContext ctx )
{ {
@ -157,7 +222,7 @@ final class BExpression
case MAX_EXP: return max( op1.evaluate(ctx), op2.evaluate(ctx) ); case MAX_EXP: return max( op1.evaluate(ctx), op2.evaluate(ctx) );
case SWITCH_EXP: return op1.evaluate(ctx) != 0.f ? op2.evaluate(ctx) : op3.evaluate(ctx); case SWITCH_EXP: return op1.evaluate(ctx) != 0.f ? op2.evaluate(ctx) : op3.evaluate(ctx);
case ASSIGN_EXP: return ctx.assign( variableIdx, op1.evaluate(ctx) ); case ASSIGN_EXP: return ctx.assign( variableIdx, op1.evaluate(ctx) );
case LOOKUP_EXP: return ctx.getLookupMatch( lookupNameIdx, lookupValueIdx ); case LOOKUP_EXP: return ctx.getLookupMatch( lookupNameIdx, lookupValueIdxArray );
case NUMBER_EXP: return numberValue; case NUMBER_EXP: return numberValue;
case VARIABLE_EXP: return ctx.getVariableValue( variableIdx ); case VARIABLE_EXP: return ctx.getVariableValue( variableIdx );
case NOT_EXP: return op1.evaluate(ctx) == 0.f ? 1.f : 0.f; case NOT_EXP: return op1.evaluate(ctx) == 0.f ? 1.f : 0.f;

View file

@ -19,6 +19,7 @@ import java.util.TreeMap;
import btools.util.BitCoderContext; import btools.util.BitCoderContext;
import btools.util.Crc32; import btools.util.Crc32;
import java.util.Random;
public final class BExpressionContext public final class BExpressionContext
@ -172,7 +173,7 @@ public final class BExpressionContext
decode( ld2, false, ab ); decode( ld2, false, ab );
for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names
{ {
if ( ld2[inum] != ld[inum] ) throw new RuntimeException( "assertion failed encoding " + getKeyValueDescription(false, ab) ); if ( ld2[inum] != ld[inum] ) throw new RuntimeException( "assertion failed encoding inum=" + inum + " val=" + ld[inum] + " " + getKeyValueDescription(false, ab) );
} }
return ab; return ab;
@ -469,6 +470,51 @@ public final class BExpressionContext
return null; return null;
} }
/**
* generate random values for regression testing
*/
public int[] generateRandomValues( Random rnd )
{
int[] data = createNewLookupData();
data[0] = 2*rnd.nextInt( 2 ); // reverse-direction = 0 or 2
for( int inum = 1; inum < data.length; inum++ )
{
int nvalues = lookupValues.get( inum ).length;
data[inum] = 0;
if ( inum > 1 && rnd.nextInt( 10 ) > 0 ) continue; // tags other than highway only 10%
data[inum] = rnd.nextInt( nvalues );
}
lookupDataValid = true;
return data;
}
public void assertAllVariablesEqual( BExpressionContext other )
{
int nv = variableData.length;
int nv2 = other.variableData.length;
if ( nv != nv2 ) throw new RuntimeException( "mismatch in variable-count: " + nv + "<->" + nv2 );
for( int i=0; i<nv; i++ )
{
if ( variableData[i] != other.variableData[i] )
{
throw new RuntimeException( "mismatch in variable " + variableName(i) + " " + variableData[i] + "<->" + other.variableData[i]
+ "\ntags = " + getKeyValueDescription( false, encode() ) );
}
}
}
private String variableName( int idx )
{
for( Map.Entry<String,Integer> e : variableNumbers.entrySet() )
{
if ( e.getValue().intValue() == idx )
{
return e.getKey();
}
}
throw new RuntimeException( "no variable for index" + idx );
}
/** /**
* add a new lookup-value for the given name to the given lookupData array. * add a new lookup-value for the given name to the given lookupData array.
* If no array is given (null value passed), the value is added to * If no array is given (null value passed), the value is added to
@ -705,9 +751,16 @@ public final class BExpressionContext
return minWriteIdx; return minWriteIdx;
} }
float getLookupMatch( int nameIdx, int valueIdx ) float getLookupMatch( int nameIdx, int[] valueIdxArray )
{ {
return lookupData[nameIdx] == valueIdx ? 1.0f : 0.0f; for( int i=0; i<valueIdxArray.length; i++ )
{
if ( lookupData[nameIdx] == valueIdxArray[i] )
{
return 1.0f;
}
}
return 0.0f;
} }
public int getLookupNameIdx( String name ) public int getLookupNameIdx( String name )

View file

@ -0,0 +1,59 @@
package btools.expressions;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import btools.util.BitCoderContext;
import btools.util.Crc32;
import java.util.Random;
public final class ProfileComparator
{
public static void main( String[] args )
{
if ( args.length != 4 )
{
System.out.println( "usage: java ProfileComparator <lookup-file> <profile1> <profile2> <nsamples>" );
return;
}
File lookupFile = new File( args[0] );
File profile1File = new File( args[1] );
File profile2File = new File( args[2] );
int nsamples = Integer.parseInt( args[3] );
testContext( lookupFile, profile1File, profile2File, nsamples, "way" );
testContext( lookupFile, profile1File, profile2File, nsamples, "node" );
}
private static void testContext( File lookupFile, File profile1File, File profile2File, int nsamples, String contextName )
{
// read lookup.dat + profiles
BExpressionMetaData meta1 = new BExpressionMetaData();
BExpressionMetaData meta2 = new BExpressionMetaData();
BExpressionContext expctx1 = new BExpressionContext(contextName, 4096, meta1 );
BExpressionContext expctx2 = new BExpressionContext(contextName, 4096, meta2 );
meta1.readMetaData( lookupFile );
meta2.readMetaData( lookupFile );
expctx1.parseFile( profile1File, "global" );
expctx2.parseFile( profile2File, "global" );
Random rnd = new Random();
for( int i=0; i<nsamples; i++ )
{
int[] data = expctx1.generateRandomValues( rnd );
expctx1.evaluate( data );
expctx2.evaluate( data );
expctx1.assertAllVariablesEqual( expctx2 );
}
}
}

View file

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

View file

@ -536,7 +536,7 @@ private long startTime = 0L;
} }
else else
{ {
String result = "version = BRouter-1.1\n" String result = "version = BRouter-1.2\n"
+ "distance = " + cr.getDistance()/1000. + " km\n" + "distance = " + cr.getDistance()/1000. + " km\n"
+ "filtered ascend = " + cr.getAscend() + " m\n" + "filtered ascend = " + cr.getAscend() + " m\n"
+ "plain ascend = " + cr.getPlainAscend(); + "plain ascend = " + cr.getPlainAscend();

View file

@ -66,6 +66,17 @@ public class RouteServer extends Thread
handler = new ServerHandler( serviceContext, params ); handler = new ServerHandler( serviceContext, params );
} }
else if ( url.startsWith( PROFILE_UPLOAD_URL ) ) else if ( url.startsWith( PROFILE_UPLOAD_URL ) )
{
if ( getline.startsWith("OPTIONS") )
{
// handle CORS preflight request (Safari)
String corsHeaders = "Access-Control-Allow-Methods: GET, POST\n"
+ "Access-Control-Allow-Headers: Content-Type\n";
writeHttpHeader( bw, "text/plain", null, corsHeaders );
bw.flush();
return;
}
else
{ {
writeHttpHeader(bw, "application/json"); writeHttpHeader(bw, "application/json");
@ -82,6 +93,7 @@ public class RouteServer extends Thread
bw.flush(); bw.flush();
return; return;
} }
}
else else
{ {
throw new IllegalArgumentException( "unknown request syntax: " + getline ); throw new IllegalArgumentException( "unknown request syntax: " + getline );
@ -126,7 +138,7 @@ public class RouteServer extends Thread
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception
{ {
System.out.println("BRouter 1.1 / 27122014"); System.out.println("BRouter 1.2 / 07022015");
if ( args.length != 5 ) if ( args.length != 5 )
{ {
System.out.println("serve BRouter protocol"); System.out.println("serve BRouter protocol");
@ -213,6 +225,11 @@ public class RouteServer extends Thread
} }
private static void writeHttpHeader( BufferedWriter bw, String mimeType, String fileName ) throws IOException private static void writeHttpHeader( BufferedWriter bw, String mimeType, String fileName ) throws IOException
{
writeHttpHeader( bw, mimeType, fileName, null);
}
private static void writeHttpHeader( BufferedWriter bw, String mimeType, String fileName, String headers ) throws IOException
{ {
// http-header // http-header
bw.write( "HTTP/1.1 200 OK\n" ); bw.write( "HTTP/1.1 200 OK\n" );
@ -223,6 +240,10 @@ public class RouteServer extends Thread
bw.write( "Content-Disposition: attachment; filename=" + fileName + "\n" ); bw.write( "Content-Disposition: attachment; filename=" + fileName + "\n" );
} }
bw.write( "Access-Control-Allow-Origin: *\n" ); bw.write( "Access-Control-Allow-Origin: *\n" );
if ( headers != null )
{
bw.write( headers );
}
bw.write( "\n" ); bw.write( "\n" );
} }
} }

View file

@ -8,21 +8,21 @@
# Use the following switches to change behaviour # Use the following switches to change behaviour
# (1=yes, 0=no): # (1=yes, 0=no):
assign consider_elevation 1 # set to 0 to ignore elevation in routing assign consider_elevation = true # set to false to ignore elevation in routing
assign allow_steps 1 # set to 0 to disallow steps assign allow_steps = true # set to false to disallow steps
assign allow_ferries 1 # set to 0 to disallow ferries assign allow_ferries = true # set to false to disallow ferries
assign ignore_cycleroutes 0 # set to 1 for better elevation results assign ignore_cycleroutes = false # set to true for better elevation results
assign stick_to_cycleroutes 0 # set to 1 to just follow cycleroutes assign stick_to_cycleroutes = false # set to true to just follow cycleroutes
assign avoid_unsafe 0 # set to 1 to avoid standard highways assign avoid_unsafe = false # set to true to avoid standard highways
assign validForBikes 1 assign validForBikes = true
# the elevation parameters # the elevation parameters
assign downhillcost switch consider_elevation 60 0 assign downhillcost = if consider_elevation then 60 else 0
assign downhillcutoff 1.5 assign downhillcutoff = 1.5
assign uphillcost 0 assign uphillcost = 0
assign uphillcutoff 1.5 assign uphillcutoff = 1.5
---context:way # following code refers to way-tags ---context:way # following code refers to way-tags
@ -30,14 +30,25 @@ assign uphillcutoff 1.5
# pre-calculate some logical expressions # pre-calculate some logical expressions
# #
assign any_cycleroute or route_bicycle_icn=yes or route_bicycle_ncn=yes or route_bicycle_rcn=yes route_bicycle_lcn=yes assign any_cycleroute =
assign nodeaccessgranted or any_cycleroute lcn=yes if route_bicycle_icn=yes then true
else if route_bicycle_ncn=yes then true
else if route_bicycle_rcn=yes then true
else if route_bicycle_lcn=yes then true
else false
assign is_ldcr and any_cycleroute not ignore_cycleroutes assign nodeaccessgranted =
assign isbike or bicycle=yes or or bicycle=permissive bicycle=designated lcn=yes if any_cycleroute then true
assign ispaved or surface=paved or surface=asphalt or surface=concrete surface=paving_stones else lcn=yes
assign isunpaved not or surface= or ispaved or surface=fine_gravel surface=cobblestone
assign probablyGood or ispaved and isbike not isunpaved assign is_ldcr =
if ignore_cycleroutes then false
else any_cycleroute
assign isbike = or bicycle=yes or or bicycle=permissive bicycle=designated lcn=yes
assign ispaved = surface=paved|asphalt|concrete|paving_stones
assign isunpaved = not or surface= or ispaved surface=fine_gravel|cobblestone
assign probablyGood = or ispaved and isbike not isunpaved
# #
@ -46,59 +57,53 @@ assign probablyGood or ispaved and isbike not isunpaved
# (Suppressing turncost while following longdistance-cycleways # (Suppressing turncost while following longdistance-cycleways
# makes them a little bit more magnetic) # makes them a little bit more magnetic)
# #
assign turncost switch is_ldcr 0 90 assign turncost = if is_ldcr then 0 else 90
# #
# calculate the initial cost # calculate the initial cost
# this is added to the total cost each time the costfactor # this is added to the total cost each time the costfactor
# changed # changed
# #
assign initialcost switch route=ferry 10000 0 assign initialcost = if route=ferry then 10000 else 0
# #
# implicit access here just from the motorroad tag # implicit access here just from the motorroad tag
# (implicit access rules from highway tag handled elsewhere) # (implicit access rules from highway tag handled elsewhere)
# #
assign defaultaccess assign defaultaccess =
switch access= if access= then not motorroad=yes
not motorroad=yes else if access=private|no then false
switch or access=private access=no else true
0
1
# #
# calculate logical bike access # calculate logical bike access
# #
assign bikeaccess assign bikeaccess =
or any_cycleroute if any_cycleroute then true
switch bicycle= else if bicycle= then
switch vehicle= (
defaultaccess if vehicle= then defaultaccess
switch or vehicle=private vehicle=no else not vehicle=private|no
0 )
1 else not bicycle=private|no|dismount
not or bicycle=private or bicycle=no bicycle=dismount
# #
# calculate logical foot access # calculate logical foot access
# #
assign footaccess assign footaccess =
or bikeaccess if bikeaccess then true
or bicycle=dismount else if bicycle=dismount then true
switch foot= else if foot= then defaultaccess
defaultaccess else not foot=private|no
not or foot=private foot=no
# #
# if not bike-, but foot-acess, just a moderate penalty, # if not bike-, but foot-acess, just a moderate penalty,
# otherwise access is forbidden # otherwise access is forbidden
# #
assign accesspenalty assign accesspenalty =
switch bikeaccess if bikeaccess then 0
0 else if footaccess then 4
switch footaccess else 100000
4
100000
# #
# handle one-ways. On primary roads, wrong-oneways should # handle one-ways. On primary roads, wrong-oneways should
@ -106,19 +111,21 @@ assign accesspenalty
# 4 to the costfactor (making it at least 5 - you are allowed # 4 to the costfactor (making it at least 5 - you are allowed
# to push your bike) # to push your bike)
# #
assign oneway assign oneway =
switch oneway= if oneway= then junction=roundabout else oneway=yes|true|1
junction=roundabout
or oneway=yes or oneway=true oneway=1 assign onewaypenalty =
if ( if reversedirection=yes then oneway else oneway=-1 ) then
(
if ( cycleway=opposite|opposite_lane|opposite_track ) then 0
else if ( oneway:bicycle=no ) then 0
else if ( highway=primary|primary_link ) then 50
else if ( highway=secondary|secondary_link ) then 30
else if ( highway=tertiary|tertiary_link ) then 20
else 4.0
)
else 0.0
assign onewaypenalty
switch switch reversedirection=yes oneway oneway=-1
switch or cycleway=opposite or cycleway=opposite_lane or cycleway=opposite_track oneway:bicycle=no 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 # calculate the cost-factor, which is the factor
@ -127,106 +134,98 @@ assign onewaypenalty
# must be >=1 and it's supposed to be close to 1 for # must be >=1 and it's supposed to be close to 1 for
# the type of way the routing profile is searching for # the type of way the routing profile is searching for
# #
assign costfactor assign costfactor =
add max onewaypenalty accesspenalty add ( max onewaypenalty accesspenalty )
switch and highway= not route=ferry 100000 if ( and highway= not route=ferry ) then 100000
# #
# steps and ferries are special. Note this is handled # steps and ferries are special. Note this is handled
# before the cycleroute-switch, to be able # before the cycleroute-switch, to be able
# to really exlude them be setting cost to infinity # to really exlude them be setting cost to infinity
# #
switch highway=steps switch allow_steps 40 100000 else if ( highway=steps ) then ( if allow_steps then 40 else 100000 )
switch route=ferry switch allow_ferries 5.67 100000 else if ( route=ferry ) then ( if allow_ferries then 5.67 else 100000 )
# #
# handle long-distance cycle-routes. # handle long-distance cycle-routes.
# #
switch is_ldcr 1 # always treated as perfect (=1) else if ( is_ldcr ) then 1 # always treated as perfect (=1)
add switch stick_to_cycleroutes 0.5 0.05 # everything else somewhat up else
add ( if stick_to_cycleroutes then 0.5 else 0.05 ) # everything else somewhat up
# #
# some other highway types # some other highway types
# #
switch highway=pedestrian 3 if ( highway=pedestrian ) then 3
switch highway=bridleway 5 else if ( highway=bridleway ) then 5
switch highway=cycleway 1 else if ( highway=cycleway ) then 1
switch or highway=residential highway=living_street switch isunpaved 1.5 1.1 else if ( highway=residential|living_street ) then ( if isunpaved then 1.5 else 1.1 )
switch highway=service switch isunpaved 1.6 1.3 else if ( highway=service ) then ( if isunpaved then 1.6 else 1.3 )
# #
# tracks and track-like ways are rated mainly be tracktype/grade # tracks and track-like ways are rated mainly be tracktype/grade
# But note that if no tracktype is given (mainly for road/path/footway) # 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 # 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 else if ( highway=track|road|path|footway ) then
switch tracktype=grade1 switch probablyGood 1.0 1.3 (
switch tracktype=grade2 switch probablyGood 1.1 2.0 if ( tracktype=grade1 ) then ( if probablyGood then 1.0 else 1.3 )
switch tracktype=grade3 switch probablyGood 1.5 3.0 else if ( tracktype=grade2 ) then ( if probablyGood then 1.1 else 2.0 )
switch tracktype=grade4 switch probablyGood 2.0 5.0 else if ( tracktype=grade3 ) then ( if probablyGood then 1.5 else 3.0 )
switch tracktype=grade5 switch probablyGood 3.0 5.0 else if ( tracktype=grade4 ) then ( if probablyGood then 2.0 else 5.0 )
switch probablyGood 1.0 5.0 else if ( tracktype=grade5 ) then ( if probablyGood then 3.0 else 5.0 )
else ( if probablyGood then 1.0 else 5.0 )
)
# #
# When avoiding unsafe ways, avoid highways without a bike hint # When avoiding unsafe ways, avoid highways without a bike hint
# #
add switch and avoid_unsafe not isbike 2 0 else add ( if ( and avoid_unsafe not isbike ) then 2 else 0 )
# #
# exclude motorways and proposed roads # exclude motorways and proposed roads
# #
switch or highway=motorway highway=motorway_link 100000 if ( highway=motorway|motorway_link ) then 100000
switch or highway=proposed highway=abandoned 100000 else if ( highway=proposed|abandoned ) then 100000
# #
# actuals roads are o.k. if we have a bike hint # actuals roads are o.k. if we have a bike hint
# #
switch or highway=trunk highway=trunk_link switch isbike 1.5 10 else if ( highway=trunk|trunk_link ) then ( if isbike then 1.5 else 10 )
switch or highway=primary highway=primary_link switch isbike 1.2 3 else if ( highway=primary|primary_link ) then ( if isbike then 1.2 else 3 )
switch or highway=secondary highway=secondary_link switch isbike 1.1 1.6 else if ( highway=secondary|secondary_link ) then ( if isbike then 1.1 else 1.6 )
switch or highway=tertiary highway=tertiary_link switch isbike 1.0 1.4 else if ( highway=tertiary|tertiary_link ) then ( if isbike then 1.0 else 1.4 )
switch highway=unclassified switch isbike 1.0 1.3 else if ( highway=unclassified ) then ( if isbike then 1.0 else 1.3 )
# #
# default for any other highway type not handled above # default for any other highway type not handled above
# #
2.0 else 2.0
---context:node # following code refers to node tags ---context:node # following code refers to node tags
assign defaultaccess assign defaultaccess =
switch access= if ( access= ) then true # add default barrier restrictions here!
1 # add default barrier restrictions here! else if ( access=private|no ) then false
switch or access=private access=no else true
0
1
assign bikeaccess assign bikeaccess =
or nodeaccessgranted=yes if nodeaccessgranted=yes then true
switch bicycle= else if bicycle= then
switch vehicle= (
defaultaccess if vehicle= then defaultaccess
switch or vehicle=private vehicle=no else not vehicle=private|no
0 )
1 else not bicycle=private|no|dismount
switch or bicycle=private or bicycle=no bicycle=dismount
0
1
assign footaccess assign footaccess =
or bicycle=dismount if bicycle=dismount then true
switch foot= else if foot= then defaultaccess
defaultaccess else not foot=private|no
switch or foot=private foot=no
0
1
assign initialcost assign initialcost =
switch bikeaccess if bikeaccess then 0
0 else ( if footaccess then 100 else 1000000 )
switch footaccess
100
1000000

View file

@ -66,7 +66,7 @@ is usually the one with the most space available.
However, on Android 4.4, write access to the external card However, on Android 4.4, write access to the external card
is restricted, and usually you will not get a proposal to use is restricted, and usually you will not get a proposal to use
the external card. Here you should accespt to go with the the external card. Here you should accept to go with the
internal card - later on you can setup a "secondary" data internal card - later on you can setup a "secondary" data
directory on the external card where you can move the datafiles directory on the external card where you can move the datafiles
to. to.