From 1aa62b0b71b16b5a828d0f91ee0154198e8d66f1 Mon Sep 17 00:00:00 2001 From: Arndt Brenschede Date: Mon, 23 Feb 2015 20:47:55 +0100 Subject: [PATCH 1/9] or-syntax for lookup matches --- .../java/btools/expressions/BExpression.java | 21 +++++++++++++------ .../expressions/BExpressionContext.java | 11 ++++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpression.java b/brouter-expressions/src/main/java/btools/expressions/BExpression.java index 80bce4f..f8b590a 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpression.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpression.java @@ -1,5 +1,6 @@ package btools.expressions; +import java.util.StringTokenizer; final class BExpression { @@ -26,7 +27,7 @@ final class BExpression private float numberValue; private int variableIdx; private int lookupNameIdx; - private int lookupValueIdx; + private int[] lookupValueIdxArray; // Parse the expression and all subexpression public static BExpression parse( BExpressionContext ctx, int level ) throws Exception @@ -105,17 +106,25 @@ final class BExpression { exp.typ = LOOKUP_EXP; String name = operator.substring( 0, idx ); - String value = operator.substring( idx+1 ); + String values = operator.substring( idx+1 ); exp.lookupNameIdx = ctx.getLookupNameIdx( name ); if ( exp.lookupNameIdx < 0 ) { throw new IllegalArgumentException( "unknown lookup name: " + name ); } - exp.lookupValueIdx = ctx.getLookupValueIdx( exp.lookupNameIdx, value ); - if ( exp.lookupValueIdx < 0 ) + StringTokenizer tk = new StringTokenizer( values, "|" ); + int nt = tk.countTokens(); + int nt2 = nt == 0 ? 1 : nt; + exp.lookupValueIdxArray = new int[nt2]; + for( int ti=0; ti= 0 ) @@ -157,7 +166,7 @@ final class BExpression 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 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 VARIABLE_EXP: return ctx.getVariableValue( variableIdx ); case NOT_EXP: return op1.evaluate(ctx) == 0.f ? 1.f : 0.f; diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java index 2b6a124..7af539f 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java @@ -706,9 +706,16 @@ public final class BExpressionContext 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 Date: Wed, 25 Feb 2015 09:32:07 +0100 Subject: [PATCH 2/9] if-then-else syntax plus optional brackets --- .../java/btools/expressions/BExpression.java | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpression.java b/brouter-expressions/src/main/java/btools/expressions/BExpression.java index f8b590a..4126a04 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpression.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpression.java @@ -32,7 +32,14 @@ final class BExpression // Parse the expression and all subexpression public static BExpression parse( BExpressionContext ctx, int level ) throws Exception { + boolean brackets = false; String operator = ctx.parseToken(); + if ( "(".equals( operator ) ) + { + brackets = true; + operator = ctx.parseToken(); + } + if ( operator == null ) { if ( level == 0 ) return null; @@ -49,11 +56,17 @@ final class BExpression BExpression exp = new BExpression(); int nops = 3; + boolean ifThenElse = false; if ( "switch".equals( operator ) ) { exp.typ = SWITCH_EXP; } + else if ( "if".equals( operator ) ) + { + exp.typ = SWITCH_EXP; + ifThenElse = true; + } else { nops = 2; // check binary expressions @@ -148,11 +161,35 @@ final class BExpression } } // parse operands - if ( nops > 0 ) exp.op1 = BExpression.parse( ctx, level+1 ); - if ( nops > 1 ) exp.op2 = BExpression.parse( ctx, level+1 ); - if ( nops > 2 ) exp.op3 = BExpression.parse( ctx, level+1 ); + if ( nops > 0 ) + { + exp.op1 = BExpression.parse( ctx, level+1 ); + } + if ( nops > 1 ) + { + if ( ifThenElse ) checkExpectedToken( ctx, "then" ); + exp.op2 = BExpression.parse( ctx, level+1 ); + } + if ( nops > 2 ) + { + if ( ifThenElse ) checkExpectedToken( ctx, "else" ); + exp.op3 = BExpression.parse( ctx, level+1 ); + } + if ( brackets ) + { + checkExpectedToken( ctx, ")" ); + } 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 public float evaluate( BExpressionContext ctx ) From 6811ea524e46e6ed58316b34b0bcf1535cebff7f Mon Sep 17 00:00:00 2001 From: Arndt Date: Sun, 1 Mar 2015 13:04:11 +0100 Subject: [PATCH 3/9] profile syntax: syntactic sugar --- .../src/main/java/btools/router/OsmPath.java | 2 +- .../java/btools/expressions/BExpression.java | 25 +- .../expressions/BExpressionContext.java | 48 +++- .../btools/expressions/ProfileComparator.java | 59 +++++ misc/profiles2/trekking.brf | 233 +++++++++--------- 5 files changed, 245 insertions(+), 122 deletions(-) create mode 100644 brouter-expressions/src/main/java/btools/expressions/ProfileComparator.java diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java index 323156f..035c1f8 100644 --- a/brouter-core/src/main/java/btools/router/OsmPath.java +++ b/brouter-core/src/main/java/btools/router/OsmPath.java @@ -292,7 +292,7 @@ final class OsmPath implements OsmLinkHolder + "\t" + linkturncost + "\t" + linknodecost + "\t" + linkinitcost - + rc.expctxWay.getKeyValueDescription( link.counterLinkWritten, description ); + + "\t" + rc.expctxWay.getKeyValueDescription( link.counterLinkWritten, description ); } if ( stopAtEndpoint ) diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpression.java b/brouter-expressions/src/main/java/btools/expressions/BExpression.java index 4126a04..59bcfb4 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpression.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpression.java @@ -31,9 +31,18 @@ final class BExpression // Parse the expression and all subexpression 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(); + if ( optionalToken != null && optionalToken.equals( operator ) ) + { + operator = ctx.parseToken(); + } if ( "(".equals( operator ) ) { brackets = true; @@ -145,6 +154,16 @@ final class BExpression exp.typ = VARIABLE_EXP; 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 { try @@ -163,17 +182,17 @@ final class BExpression // parse operands if ( nops > 0 ) { - exp.op1 = 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 ); + exp.op2 = BExpression.parse( ctx, level+1, null ); } if ( nops > 2 ) { if ( ifThenElse ) checkExpectedToken( ctx, "else" ); - exp.op3 = BExpression.parse( ctx, level+1 ); + exp.op3 = BExpression.parse( ctx, level+1, null ); } if ( brackets ) { diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java index 7af539f..50be710 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java @@ -19,6 +19,7 @@ import java.util.TreeMap; import btools.util.BitCoderContext; import btools.util.Crc32; +import java.util.Random; public final class BExpressionContext @@ -172,7 +173,7 @@ public final class BExpressionContext decode( ld2, false, ab ); 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; @@ -471,6 +472,51 @@ public final class BExpressionContext 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" + other.variableData[i] + + "\ntags = " + getKeyValueDescription( false, encode() ) ); + } + } + } + + private String variableName( int idx ) + { + for( Map.Entry 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. * If no array is given (null value passed), the value is added to diff --git a/brouter-expressions/src/main/java/btools/expressions/ProfileComparator.java b/brouter-expressions/src/main/java/btools/expressions/ProfileComparator.java new file mode 100644 index 0000000..e525a8d --- /dev/null +++ b/brouter-expressions/src/main/java/btools/expressions/ProfileComparator.java @@ -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 " ); + 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=1 and it's supposed to be close to 1 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 # before the cycleroute-switch, to be able # to really exlude them be setting cost to infinity # - switch highway=steps switch allow_steps 40 100000 - switch route=ferry switch allow_ferries 5.67 100000 + else if ( highway=steps ) then ( if allow_steps then 40 else 100000 ) + else if ( route=ferry ) then ( if allow_ferries then 5.67 else 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 + else if ( is_ldcr ) then 1 # always treated as perfect (=1) + else + add ( if stick_to_cycleroutes then 0.5 else 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 + if ( highway=pedestrian ) then 3 + else if ( highway=bridleway ) then 5 + else if ( highway=cycleway ) then 1 + else if ( highway=residential|living_street ) then ( if isunpaved then 1.5 else 1.1 ) + else if ( highway=service ) then ( if isunpaved then 1.6 else 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 + else if ( highway=track|road|path|footway ) then + ( + if ( tracktype=grade1 ) then ( if probablyGood then 1.0 else 1.3 ) + else if ( tracktype=grade2 ) then ( if probablyGood then 1.1 else 2.0 ) + else if ( tracktype=grade3 ) then ( if probablyGood then 1.5 else 3.0 ) + else if ( tracktype=grade4 ) then ( if probablyGood then 2.0 else 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 # - 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 # - switch or highway=motorway highway=motorway_link 100000 - switch or highway=proposed highway=abandoned 100000 + if ( highway=motorway|motorway_link ) then 100000 + else if ( highway=proposed|abandoned ) then 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 + else if ( highway=trunk|trunk_link ) then ( if isbike then 1.5 else 10 ) + else if ( highway=primary|primary_link ) then ( if isbike then 1.2 else 3 ) + else if ( highway=secondary|secondary_link ) then ( if isbike then 1.1 else 1.6 ) + else if ( highway=tertiary|tertiary_link ) then ( if isbike then 1.0 else 1.4 ) + else if ( highway=unclassified ) then ( if isbike then 1.0 else 1.3 ) # # default for any other highway type not handled above # - 2.0 + else 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 defaultaccess = + if ( access= ) then true # add default barrier restrictions here! + else if ( access=private|no ) then false + else true -assign bikeaccess - or nodeaccessgranted=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 bikeaccess = + if nodeaccessgranted=yes then true + else if bicycle= then + ( + if vehicle= then defaultaccess + else not vehicle=private|no + ) + else not bicycle=private|no|dismount -assign footaccess - or bicycle=dismount - switch foot= - defaultaccess - switch or foot=private foot=no - 0 - 1 +assign footaccess = + if bicycle=dismount then true + else if foot= then defaultaccess + else not foot=private|no -assign initialcost - switch bikeaccess - 0 - switch footaccess - 100 - 1000000 +assign initialcost = + if bikeaccess then 0 + else ( if footaccess then 100 else 1000000 ) From 9e3b6b37c34d9f471c19472db8287dd11d570844 Mon Sep 17 00:00:00 2001 From: Norbert Renner Date: Thu, 5 Mar 2015 19:14:16 +0100 Subject: [PATCH 4/9] include messages (csv data) in GeoJSON response --- .../src/main/java/btools/router/OsmTrack.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/brouter-core/src/main/java/btools/router/OsmTrack.java b/brouter-core/src/main/java/btools/router/OsmTrack.java index 6694fb1..af63b2a 100644 --- a/brouter-core/src/main/java/btools/router/OsmTrack.java +++ b/brouter-core/src/main/java/btools/router/OsmTrack.java @@ -26,6 +26,9 @@ import btools.util.FrozenLongMap; 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 long[] nogoChecksums; @@ -304,7 +307,19 @@ public final class OsmTrack sb.append( " \"track-length\": \"" ).append( distance ).append( "\",\n" ); sb.append( " \"filtered ascend\": \"" ).append( ascend ).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" ); if ( iternity != null ) @@ -361,10 +376,7 @@ public final class OsmTrack public void writeMessages( BufferedWriter bw, RoutingContext rc ) throws Exception { - // csv-header-line - - String header = "Longitude\tLatitude\tElevation\tDistance\tCostPerKm\tElevCost\tTurnCost\tNodeCost\tInitialCost\tOsmTags"; - dumpLine( bw, header ); + dumpLine( bw, MESSAGES_HEADER ); for( OsmPathElement n : nodes ) { if ( n.message != null ) From 22aabd8863ad00c91e56c312217e8b82a03cd680 Mon Sep 17 00:00:00 2001 From: Mateusz Konieczny Date: Sun, 22 Mar 2015 15:10:26 +0100 Subject: [PATCH 5/9] fix typo in README --- misc/readmes/readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/readmes/readme.txt b/misc/readmes/readme.txt index e332b55..3475692 100644 --- a/misc/readmes/readme.txt +++ b/misc/readmes/readme.txt @@ -66,7 +66,7 @@ is usually the one with the most space available. However, on Android 4.4, write access to the external card 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 directory on the external card where you can move the datafiles to. From 057377328771ba7b09c4070d6f7259585e2b8825 Mon Sep 17 00:00:00 2001 From: Arndt Date: Mon, 30 Mar 2015 14:19:00 +0200 Subject: [PATCH 6/9] node-cost fix for csv --- .../main/java/btools/router/MessageData.java | 48 +++++++++++++++ .../src/main/java/btools/router/OsmPath.java | 61 +++++++++---------- 2 files changed, 76 insertions(+), 33 deletions(-) create mode 100644 brouter-core/src/main/java/btools/router/MessageData.java diff --git a/brouter-core/src/main/java/btools/router/MessageData.java b/brouter-core/src/main/java/btools/router/MessageData.java new file mode 100644 index 0000000..3879c03 --- /dev/null +++ b/brouter-core/src/main/java/btools/router/MessageData.java @@ -0,0 +1,48 @@ +/** + * Information on matched way point + * + * @author ab + */ +package btools.router; + +import btools.expressions.BExpressionContext; + + +final class MessageData +{ + int linkdist = 0; + int linkelevationcost = 0; + int linkturncost = 0; + int linknodecost = 0; + int linkinitcost = 0; + + float costfactor; + String wayKeyValues; + String nodeKeyValues; + + int lon; + int lat; + short ele; + + String toMessage() + { + if ( wayKeyValues == null ) + { + return null; + } + + int iCost = (int)(costfactor*1000 + 0.5f); + return (lon-180000000) + "\t" + + (lat-90000000) + "\t" + + ele/4 + "\t" + + linkdist + "\t" + + iCost + "\t" + + linkelevationcost + + "\t" + linkturncost + + "\t" + linknodecost + + "\t" + linkinitcost + + "\t" + wayKeyValues + + "\t" + ( nodeKeyValues == null ? "" : nodeKeyValues ); + } + +} diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java index 035c1f8..8d6dbaa 100644 --- a/brouter-core/src/main/java/btools/router/OsmPath.java +++ b/brouter-core/src/main/java/btools/router/OsmPath.java @@ -84,15 +84,11 @@ final class OsmPath implements OsmLinkHolder short ele1 = origin.selev; int linkdisttotal = 0; - int linkdist = 0; - int linkelevationcost = 0; - int linkturncost = 0; - int linknodecost = 0; - int linkinitcost = 0; + + MessageData msgData = new MessageData(); OsmTransferNode transferNode = link.decodeFirsttransfer(); OsmNode targetNode = link.targetNode; - String lastMessage = null; for(;;) { originLon = lon1; @@ -124,14 +120,10 @@ final class OsmPath implements OsmLinkHolder boolean sameData = rc.expctxWay.evaluate( link.counterLinkWritten, description, rc.messageHandler ); // if way description changed, store message - if ( lastMessage != null && !sameData ) + if ( msgData.wayKeyValues != null && !sameData ) { - originElement.message = lastMessage; - linkdist = 0; - linkelevationcost = 0; - linkturncost = 0; - linknodecost = 0; - linkinitcost = 0; + originElement.message = msgData.toMessage(); + msgData = new MessageData(); } int dist = rc.calcDistance( lon1, lat1, lon2, lat2 ); @@ -165,7 +157,7 @@ final class OsmPath implements OsmLinkHolder } } - linkdist += dist; + msgData.linkdist += dist; linkdisttotal += dist; @@ -176,7 +168,7 @@ final class OsmPath implements OsmLinkHolder double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 ); int turncost = (int)(cos * rc.expctxWay.getTurncost() + 0.2 ); // e.g. turncost=90 -> 90 degree = 90m penalty cost += turncost; - linkturncost += turncost; + msgData.linkturncost += turncost; } // *** penalty for elevation (penalty is for descend! in a way that slow descends give no penalty) @@ -212,7 +204,7 @@ final class OsmPath implements OsmLinkHolder { int elevationCost = reduce/rc.downhillcostdiv; cost += elevationCost; - linkelevationcost += elevationCost; + msgData.linkelevationcost += elevationCost; } } else if ( ehbd < 0 ) @@ -242,7 +234,7 @@ final class OsmPath implements OsmLinkHolder { int elevationCost = reduce/rc.uphillcostdiv; cost += elevationCost; - linkelevationcost += elevationCost; + msgData.linkelevationcost += elevationCost; } } else if ( ehbu < 0 ) @@ -276,23 +268,17 @@ final class OsmPath implements OsmLinkHolder lastCostfactor = newcostfactor; float initialcost = rc.expctxWay.getInitialcost(); int iicost = (int)initialcost; - linkinitcost += iicost; + msgData.linkinitcost += iicost; cost += iicost; } if ( recordTransferNodes ) { - int iCost = (int)(costfactor*1000 + 0.5f); - lastMessage = (lon2-180000000) + "\t" - + (lat2-90000000) + "\t" - + ele2/4 + "\t" - + linkdist + "\t" - + iCost + "\t" - + linkelevationcost - + "\t" + linkturncost - + "\t" + linknodecost - + "\t" + linkinitcost - + "\t" + rc.expctxWay.getKeyValueDescription( link.counterLinkWritten, description ); + msgData.costfactor = costfactor; + msgData.lon = lon2; + msgData.lat = lat2; + msgData.ele = ele2; + msgData.wayKeyValues = rc.expctxWay.getKeyValueDescription( link.counterLinkWritten, description ); } if ( stopAtEndpoint ) @@ -301,7 +287,7 @@ final class OsmPath implements OsmLinkHolder { originElement = new OsmPathElement( rc.ilonshortest, rc.ilatshortest, ele2, originElement ); originElement.cost = cost; - originElement.message = lastMessage; + originElement.message = msgData.toMessage(); } if ( rc.nogomatch ) { @@ -318,7 +304,6 @@ final class OsmPath implements OsmLinkHolder int reftrackcost = linkdisttotal; cost += reftrackcost; } - message = lastMessage; selev = ele2; break; } @@ -347,8 +332,9 @@ final class OsmPath implements OsmLinkHolder // finally add node-costs for target node if ( targetNode.nodeDescription != null ) { + boolean nodeAccessGranted = rc.expctxWay.getNodeAccessGranted() != 0.; rc.messageHandler.setCurrentPos( targetNode.ilon, targetNode.ilat ); - rc.expctxNode.evaluate( rc.expctxWay.getNodeAccessGranted() != 0. , targetNode.nodeDescription, rc.messageHandler ); + rc.expctxNode.evaluate( nodeAccessGranted , targetNode.nodeDescription, rc.messageHandler ); float initialcost = rc.expctxNode.getInitialcost(); if ( initialcost >= 1000000. ) { @@ -356,9 +342,18 @@ final class OsmPath implements OsmLinkHolder return; } int iicost = (int)initialcost; - linknodecost += iicost; + msgData.linknodecost += iicost; + cost += iicost; + + if ( recordTransferNodes ) + { + msgData.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription ); + } } + + message = msgData.toMessage(); + } public int elevationCorrection( RoutingContext rc ) From deb3b0eb0216e25435c0037b0e96a04d40651467 Mon Sep 17 00:00:00 2001 From: Arndt Date: Mon, 30 Mar 2015 14:20:44 +0200 Subject: [PATCH 7/9] fix for csv --- .../main/java/btools/expressions/BExpressionContext.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java index 50be710..54fa55e 100644 --- a/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java +++ b/brouter-expressions/src/main/java/btools/expressions/BExpressionContext.java @@ -282,9 +282,6 @@ public final class BExpressionContext public String getKeyValueDescription( boolean inverseDirection, byte[] ab ) { - int inverseBitByteIndex = meta.readVarLength ? 0 : 7; -// int abLen = ab.length; - StringBuilder sb = new StringBuilder( 200 ); decode( lookupData, inverseDirection, ab ); for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names @@ -293,7 +290,8 @@ public final class BExpressionContext String value = va[lookupData[inum]].toString(); if ( value != null && value.length() > 0 ) { - sb.append( " " + lookupNames.get( inum ) + "=" + value ); + if ( sb.length() > 0 ) sb.append( ' ' ); + sb.append(lookupNames.get( inum ) + "=" + value ); } } return sb.toString(); @@ -617,6 +615,7 @@ public final class BExpressionContext lookupData[inum] = valueIndex; } + /** * special hack for yes/proposed relations: * add a lookup value if not yet a smaller, >1 value was added From 062702c5a36878b275965e1b6a4f4afe7a7c3cf0 Mon Sep 17 00:00:00 2001 From: Arndt Date: Mon, 30 Mar 2015 14:22:19 +0200 Subject: [PATCH 8/9] 1.2 prparations --- brouter-core/src/main/java/btools/router/OsmTrack.java | 2 +- brouter-routing-app/AndroidManifest.xml | 4 ++-- .../src/main/java/btools/routingapp/BRouterView.java | 2 +- brouter-server/src/main/java/btools/server/RouteServer.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/brouter-core/src/main/java/btools/router/OsmTrack.java b/brouter-core/src/main/java/btools/router/OsmTrack.java index af63b2a..fb66d38 100644 --- a/brouter-core/src/main/java/btools/router/OsmTrack.java +++ b/brouter-core/src/main/java/btools/router/OsmTrack.java @@ -223,7 +223,7 @@ public final class OsmTrack 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( " 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( " \n" ); sb.append(" ").append(name).append("\n"); sb.append( " \n" ); diff --git a/brouter-routing-app/AndroidManifest.xml b/brouter-routing-app/AndroidManifest.xml index b45c638..5fcb313 100644 --- a/brouter-routing-app/AndroidManifest.xml +++ b/brouter-routing-app/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="6" + android:versionName="1.2" package="btools.routingapp"> Date: Tue, 31 Mar 2015 15:55:43 +0200 Subject: [PATCH 9/9] handle CORS preflight request for profile upload (Safari) --- .../main/java/btools/server/RouteServer.java | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/brouter-server/src/main/java/btools/server/RouteServer.java b/brouter-server/src/main/java/btools/server/RouteServer.java index 4a715af..01abf05 100644 --- a/brouter-server/src/main/java/btools/server/RouteServer.java +++ b/brouter-server/src/main/java/btools/server/RouteServer.java @@ -67,20 +67,32 @@ public class RouteServer extends Thread } else if ( url.startsWith( PROFILE_UPLOAD_URL ) ) { - writeHttpHeader(bw, "application/json"); - - String profileId = null; - if ( url.length() > PROFILE_UPLOAD_URL.length() + 1 ) + if ( getline.startsWith("OPTIONS") ) { - // e.g. /brouter/profile/custom_1400767688382 - profileId = url.substring(PROFILE_UPLOAD_URL.length() + 1); + // 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"); - ProfileUploadHandler uploadHandler = new ProfileUploadHandler( serviceContext ); - uploadHandler.handlePostRequest( profileId, br, bw ); + String profileId = null; + if ( url.length() > PROFILE_UPLOAD_URL.length() + 1 ) + { + // e.g. /brouter/profile/custom_1400767688382 + profileId = url.substring(PROFILE_UPLOAD_URL.length() + 1); + } - bw.flush(); - return; + ProfileUploadHandler uploadHandler = new ProfileUploadHandler( serviceContext ); + uploadHandler.handlePostRequest( profileId, br, bw ); + + bw.flush(); + return; + } } else { @@ -213,6 +225,11 @@ public class RouteServer extends Thread } 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 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( "Access-Control-Allow-Origin: *\n" ); + if ( headers != null ) + { + bw.write( headers ); + } bw.write( "\n" ); } }