Compare commits

..

57 commits

Author SHA1 Message Date
c9d70461a5
edited lookups.dat 2025-09-19 09:53:08 -07:00
409d329789
edited README 2025-09-19 09:09:46 -07:00
5d62da4ce2
changed README 2025-09-19 09:07:59 -07:00
f8eb93f462
added lts_score tag to lookups.dat 2025-09-19 09:07:02 -07:00
4c0cef83da
changed process unused to true in profiles 2025-09-19 09:05:16 -07:00
afischerdev
041488b36c
Merge pull request #814 from afischerdev/new-version
Preparing for Version 1.7.8
2025-07-12 10:16:08 +02:00
afischerdev
f019af4938 preparing for version 1.7.8 2025-07-10 11:02:26 +02:00
afischerdev
ecfc417ee0
Merge pull request #779 from afischerdev/docs
Update for the Docs
2025-07-10 10:50:57 +02:00
afischerdev
ce287657d0
Merge pull request #812 from afischerdev/apk-androidv
Apk: Update for Android 16
2025-07-10 10:29:47 +02:00
afischerdev
f93fc0b0e5 added new Android version 2025-07-08 14:26:06 +02:00
afischerdev
c3e6b8a1ac updated for gradle 8.13 2025-07-08 13:56:34 +02:00
afischerdev
1cc1039ec0 updated for Android 16 2025-07-08 10:48:54 +02:00
afischerdev
26925a1e1a
Merge pull request #808 from afischerdev/apk-profileparams
Apk: Use profile parameter
2025-07-07 18:21:33 +02:00
afischerdev
fcc0d5ce60
Merge pull request #806 from afischerdev/lib-workaround
Lib small workaround
2025-07-07 13:02:02 +02:00
afischerdev
585899e797
Merge pull request #811 from afischerdev/profile-change
Profile: switched consider_traffic from hiking-mountain to fastbike
2025-07-07 13:01:06 +02:00
afischerdev
faaa7bf70d
Merge pull request #810 from devemux86/param
Fix ListPreference in RoutingParameterDialog
2025-07-07 12:37:54 +02:00
afischerdev
00d74d930e protect null pointer 2025-07-07 12:32:53 +02:00
afischerdev
30bc66e7fd switched traffic from hike to fastbike 2025-06-30 17:13:13 +02:00
afischerdev
58536be655
Merge pull request #803 from afischerdev/lib-wpterror
Waypoint distance error
2025-06-30 14:16:37 +02:00
afischerdev
dec37e7fab
Merge pull request #793 from afischerdev/db-update
Database scripts updated
2025-06-30 14:15:00 +02:00
Emux
efcfc59d1b
Fix ListPreference in RoutingParameterDialog 2025-06-30 14:58:26 +03:00
afischerdev
ac7ddddb62 added params in timeoutdata 2025-06-30 12:36:30 +02:00
afischerdev
1642b4f5ba
Merge pull request #805 from devemux86/android
Android 16
2025-06-19 14:51:53 +02:00
Emux
714584e39c
Update dependencies 2025-06-19 15:43:02 +03:00
afischerdev
5e68bfdf69 use profile parameter 2025-06-19 10:09:58 +02:00
afischerdev
cfe3ff536a added consumed angle for roundabout 2025-06-17 13:09:17 +02:00
afischerdev
156d5f9f98 made conditions equal 2025-06-17 13:08:30 +02:00
afischerdev
558e8e5955 added new angles 2025-06-17 13:02:41 +02:00
afischerdev
83f78e833d shorter error messages 2025-06-17 13:02:10 +02:00
Emux
8d563e81ae
Android 16 revert Thread.getId improvement 2025-06-11 14:08:16 +03:00
Emux
96f0b0b54f
Android 16 2025-06-11 13:46:47 +03:00
afischerdev
f3bd0032b7 wpt distance check reworked 2025-06-07 15:52:27 +02:00
afischerdev
ebd06681a7
Merge pull request #785 from afischerdev/roundabout
Mismatched point extention for roundabouts
2025-06-07 11:57:19 +02:00
afischerdev
9529c966ef
Merge pull request #802 from devemux86/gradle
Update Android Gradle plugin

@devemux86
Thanks for cooperation
2025-06-05 10:59:20 +02:00
Emux
f340def656
Update Android Gradle plugin 2025-06-05 11:16:20 +03:00
afischerdev
4c824531a2 db scripts pushed to last state 2025-05-27 11:45:23 +02:00
afischerdev
ca70a48044
Merge pull request #787 from devemux86/dependencies
Update Android app dependencies


@devemux86
Thanks for cooperation
2025-05-16 17:32:28 +02:00
afischerdev
d5a625fe4b
Merge pull request #786 from devemux86/gradle
Update Android Gradle plugin

@devemux86
Thanks for cooperation
2025-05-16 17:26:44 +02:00
Emux
466627f18b
Update Android app dependencies 2025-05-16 09:52:13 +03:00
Emux
b7151e779e
Update Android Gradle plugin 2025-05-16 09:50:35 +03:00
afischerdev
4a414b0d1a added test roundabout 2025-05-11 17:00:46 +02:00
afischerdev
3ca25eab04 added mismatched pts on roundabout 2025-05-11 17:00:24 +02:00
afischerdev
dbaab10377 remove mismatched pts array 2025-05-09 16:46:28 +02:00
afischerdev
8528276ffb
Merge pull request #782 from devemux86/gradle
Update Android Gradle plugin

@devemux86
Thanks for the support
2025-04-22 10:03:53 +02:00
Emux
c23fa53ec3
Update Android Gradle plugin 2025-04-22 09:55:45 +03:00
afischerdev
af745d3eee
Merge pull request #781 from devemux86/gradle
Update Gradle

@devemux86

Thanks for contribution
2025-04-18 18:17:00 +02:00
Emux
c68c451151
Update Gradle 2025-04-17 15:48:08 +03:00
afischerdev
e031835592
Merge pull request #780 from devemux86/dependencies
Update Android app dependencies

@devemux86
Many thanks for cooperation
2025-04-17 14:37:44 +02:00
Emux
bffcae48ea
Update Android app dependencies 2025-04-17 14:10:42 +03:00
afischerdev
89be5f58dd
Merge pull request #776 from afischerdev/merge_via
Added export for corrected Via Points
2025-04-12 16:19:39 +02:00
afischerdev
64560d26c0
Merge pull request #774 from afischerdev/avoid-uturns
Added a switch to avoid u-turns
2025-04-12 16:14:25 +02:00
afischerdev
7e117d9675 added export formats 2025-04-05 18:09:15 +02:00
afischerdev
2682981da9 added export for corrected via points 2025-04-05 18:08:46 +02:00
afischerdev
e3361cc113
Merge pull request #775 from Nitue/rfc7230-header-delimiter
RFC7230 compliant HTTP header delimiter

@Nitue
Thank you for your cooperation
2025-04-05 13:00:46 +02:00
afischerdev
02733ffbec reactivated end distance control 2025-04-05 12:29:55 +02:00
Nitue
acbda6c3e7 RFC7230 compliant HTTP header delimiter
Changes HTTP header endings from LF to CRLF.

RFC7230 states that headers are separated by CRLF. Brouter currently
uses only LF. Most recipients probably accept LF only, but some are
strict about this.
2025-04-05 01:00:57 +03:00
afischerdev
68b6edc580 added switch to avoid u-turns 2025-04-02 18:58:31 +02:00
37 changed files with 2192 additions and 948 deletions

View file

@ -1,3 +1,9 @@
Forked from https://github.com/abrensch/brouter
- changed processUnused to true for safety, shortest, and trekking
- added lts_score to lookups.dat
BRouter BRouter
======= =======

View file

@ -197,25 +197,32 @@ public class FormatGpx extends Formatter {
for (int i = 0; i <= t.pois.size() - 1; i++) { for (int i = 0; i <= t.pois.size() - 1; i++) {
OsmNodeNamed poi = t.pois.get(i); OsmNodeNamed poi = t.pois.get(i);
formatWaypointGpx(sb, poi); formatWaypointGpx(sb, poi, "poi");
} }
if (t.exportWaypoints) { if (t.exportWaypoints) {
for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) { for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) {
MatchedWaypoint wt = t.matchedWaypoints.get(i); MatchedWaypoint wt = t.matchedWaypoints.get(i);
sb.append(" <wpt lon=\"").append(formatILon(wt.waypoint.ilon)).append("\" lat=\"")
.append(formatILat(wt.waypoint.ilat)).append("\">\n")
.append(" <name>").append(StringUtils.escapeXml10(wt.name)).append("</name>\n");
if (i == 0) { if (i == 0) {
sb.append(" <type>from</type>\n"); formatWaypointGpx(sb, wt, "from");
} else if (i == t.matchedWaypoints.size() - 1) { } else if (i == t.matchedWaypoints.size() - 1) {
sb.append(" <type>to</type>\n"); formatWaypointGpx(sb, wt, "to");
} else { } else {
sb.append(" <type>via</type>\n"); formatWaypointGpx(sb, wt, "via");
} }
sb.append(" </wpt>\n");
} }
} }
if (t.exportCorrectedWaypoints) {
for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) {
MatchedWaypoint wt = t.matchedWaypoints.get(i);
if (wt.correctedpoint != null) {
OsmNodeNamed n = new OsmNodeNamed(wt.correctedpoint);
n.name = wt.name + "_corr";
formatWaypointGpx(sb, n, "via_corr");
}
}
}
sb.append(" <trk>\n"); sb.append(" <trk>\n");
if (turnInstructionMode == 9 if (turnInstructionMode == 9
|| turnInstructionMode == 2 || turnInstructionMode == 2
@ -454,7 +461,7 @@ public class FormatGpx extends Formatter {
StringWriter sw = new StringWriter(8192); StringWriter sw = new StringWriter(8192);
BufferedWriter bw = new BufferedWriter(sw); BufferedWriter bw = new BufferedWriter(sw);
formatGpxHeader(bw); formatGpxHeader(bw);
formatWaypointGpx(bw, n); formatWaypointGpx(bw, n, null);
formatGpxFooter(bw); formatGpxFooter(bw);
bw.close(); bw.close();
sw.close(); sw.close();
@ -477,7 +484,7 @@ public class FormatGpx extends Formatter {
sb.append("</gpx>\n"); sb.append("</gpx>\n");
} }
public void formatWaypointGpx(BufferedWriter sb, OsmNodeNamed n) throws IOException { public void formatWaypointGpx(BufferedWriter sb, OsmNodeNamed n, String type) throws IOException {
sb.append(" <wpt lon=\"").append(formatILon(n.ilon)).append("\" lat=\"") sb.append(" <wpt lon=\"").append(formatILon(n.ilon)).append("\" lat=\"")
.append(formatILat(n.ilat)).append("\">"); .append(formatILat(n.ilat)).append("\">");
if (n.getSElev() != Short.MIN_VALUE) { if (n.getSElev() != Short.MIN_VALUE) {
@ -489,6 +496,24 @@ public class FormatGpx extends Formatter {
if (n.nodeDescription != null && rc != null) { if (n.nodeDescription != null && rc != null) {
sb.append("<desc>").append(rc.expctxWay.getKeyValueDescription(false, n.nodeDescription)).append("</desc>"); sb.append("<desc>").append(rc.expctxWay.getKeyValueDescription(false, n.nodeDescription)).append("</desc>");
} }
if (type != null) {
sb.append("<type>").append(type).append("</type>");
}
sb.append("</wpt>\n");
}
public void formatWaypointGpx(BufferedWriter sb, MatchedWaypoint wp, String type) throws IOException {
sb.append(" <wpt lon=\"").append(formatILon(wp.waypoint.ilon)).append("\" lat=\"")
.append(formatILat(wp.waypoint.ilat)).append("\">");
if (wp.waypoint.getSElev() != Short.MIN_VALUE) {
sb.append("<ele>").append("" + wp.waypoint.getElev()).append("</ele>");
}
if (wp.name != null) {
sb.append("<name>").append(StringUtils.escapeXml10(wp.name)).append("</name>");
}
if (type != null) {
sb.append("<type>").append(type).append("</type>");
}
sb.append("</wpt>\n"); sb.append("</wpt>\n");
} }

View file

@ -126,7 +126,7 @@ public class FormatJson extends Formatter {
sb.append(" ]\n"); sb.append(" ]\n");
sb.append(" }\n"); sb.append(" }\n");
if (t.exportWaypoints || !t.pois.isEmpty()) { if (t.exportWaypoints || t.exportCorrectedWaypoints || !t.pois.isEmpty()) {
sb.append(" },\n"); sb.append(" },\n");
for (int i = 0; i <= t.pois.size() - 1; i++) { for (int i = 0; i <= t.pois.size() - 1; i++) {
OsmNodeNamed poi = t.pois.get(i); OsmNodeNamed poi = t.pois.get(i);
@ -137,6 +137,7 @@ public class FormatJson extends Formatter {
sb.append(" \n"); sb.append(" \n");
} }
if (t.exportWaypoints) { if (t.exportWaypoints) {
if (!t.pois.isEmpty()) sb.append(" ,\n");
for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) { for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) {
String type; String type;
if (i == 0) { if (i == 0) {
@ -155,6 +156,23 @@ public class FormatJson extends Formatter {
sb.append(" \n"); sb.append(" \n");
} }
} }
if (t.exportCorrectedWaypoints) {
if (t.exportWaypoints) sb.append(" ,\n");
boolean hasCorrPoints = false;
for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) {
String type = "via_corr";
MatchedWaypoint wp = t.matchedWaypoints.get(i);
if (wp.correctedpoint != null) {
if (hasCorrPoints) {
sb.append(",");
}
addFeature(sb, type, wp.name + "_corr", wp.correctedpoint.ilat, wp.correctedpoint.ilon, wp.correctedpoint.getSElev());
sb.append(" \n");
hasCorrPoints = true;
}
}
}
} else { } else {
sb.append(" }\n"); sb.append(" }\n");
} }

View file

@ -1,5 +1,6 @@
package btools.router; package btools.router;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import btools.mapaccess.MatchedWaypoint; import btools.mapaccess.MatchedWaypoint;
@ -43,7 +44,7 @@ public class FormatKml extends Formatter {
sb.append(" </LineString>\n"); sb.append(" </LineString>\n");
sb.append(" </Placemark>\n"); sb.append(" </Placemark>\n");
sb.append(" </Folder>\n"); sb.append(" </Folder>\n");
if (t.exportWaypoints || !t.pois.isEmpty()) { if (t.exportWaypoints || t.exportCorrectedWaypoints || !t.pois.isEmpty()) {
if (!t.pois.isEmpty()) { if (!t.pois.isEmpty()) {
sb.append(" <Folder>\n"); sb.append(" <Folder>\n");
sb.append(" <name>poi</name>\n"); sb.append(" <name>poi</name>\n");
@ -62,6 +63,19 @@ public class FormatKml extends Formatter {
} }
createFolder(sb, "end", t.matchedWaypoints.subList(size - 1, size)); createFolder(sb, "end", t.matchedWaypoints.subList(size - 1, size));
} }
if (t.exportCorrectedWaypoints) {
List<OsmNodeNamed> list = new ArrayList<>();
for (int i = 0; i < t.matchedWaypoints.size(); i++) {
MatchedWaypoint wp = t.matchedWaypoints.get(i);
if (wp.correctedpoint != null) {
OsmNodeNamed n = new OsmNodeNamed(wp.correctedpoint);
n.name = wp.name + "_corr";
list.add(n);
}
}
int size = list.size();
createViaFolder(sb, "via_corr", list.subList(0, size));
}
} }
sb.append(" </Document>\n"); sb.append(" </Document>\n");
sb.append("</kml>\n"); sb.append("</kml>\n");
@ -79,6 +93,17 @@ public class FormatKml extends Formatter {
sb.append(" </Folder>\n"); sb.append(" </Folder>\n");
} }
private void createViaFolder(StringBuilder sb, String type, List<OsmNodeNamed> waypoints) {
if (waypoints.isEmpty()) return;
sb.append(" <Folder>\n");
sb.append(" <name>" + type + "</name>\n");
for (int i = 0; i < waypoints.size(); i++) {
OsmNodeNamed wp = waypoints.get(i);
createPlaceMark(sb, wp.name, wp.ilat, wp.ilon);
}
sb.append(" </Folder>\n");
}
private void createPlaceMark(StringBuilder sb, String name, int ilat, int ilon) { private void createPlaceMark(StringBuilder sb, String name, int ilat, int ilon) {
sb.append(" <Placemark>\n"); sb.append(" <Placemark>\n");
sb.append(" <name>" + StringUtils.escapeXml10(name) + "</name>\n"); sb.append(" <name>" + StringUtils.escapeXml10(name) + "</name>\n");

View file

@ -23,8 +23,8 @@ import btools.util.CompactLongMap;
import btools.util.FrozenLongMap; import btools.util.FrozenLongMap;
public final class OsmTrack { public final class OsmTrack {
final public static String version = "1.7.7"; final public static String version = "1.7.8";
final public static String versionDate = "23072024"; final public static String versionDate = "12072025";
// csv-header-line // csv-header-line
private static final String MESSAGES_HEADER = "Longitude\tLatitude\tElevation\tDistance\tCostPerKm\tElevCost\tTurnCost\tNodeCost\tInitialCost\tWayTags\tNodeTags\tTime\tEnergy"; private static final String MESSAGES_HEADER = "Longitude\tLatitude\tElevation\tDistance\tCostPerKm\tElevCost\tTurnCost\tNodeCost\tInitialCost\tWayTags\tNodeTags\tTime\tEnergy";
@ -62,6 +62,7 @@ public final class OsmTrack {
protected List<MatchedWaypoint> matchedWaypoints; protected List<MatchedWaypoint> matchedWaypoints;
public boolean exportWaypoints = false; public boolean exportWaypoints = false;
public boolean exportCorrectedWaypoints = false;
public void addNode(OsmPathElement node) { public void addNode(OsmPathElement node) {
nodes.add(0, node); nodes.add(0, node);
@ -338,6 +339,7 @@ public final class OsmTrack {
} }
float t0 = ourSize > 0 ? nodes.get(ourSize - 1).getTime() : 0; float t0 = ourSize > 0 ? nodes.get(ourSize - 1).getTime() : 0;
float e0 = ourSize > 0 ? nodes.get(ourSize - 1).getEnergy() : 0; float e0 = ourSize > 0 ? nodes.get(ourSize - 1).getEnergy() : 0;
int c0 = ourSize > 0 ? nodes.get(ourSize - 1).cost : 0;
for (i = 0; i < t.nodes.size(); i++) { for (i = 0; i < t.nodes.size(); i++) {
OsmPathElement e = t.nodes.get(i); OsmPathElement e = t.nodes.get(i);
if (i == 0 && ourSize > 0 && nodes.get(ourSize - 1).getSElev() == Short.MIN_VALUE) if (i == 0 && ourSize > 0 && nodes.get(ourSize - 1).getSElev() == Short.MIN_VALUE)
@ -345,6 +347,7 @@ public final class OsmTrack {
if (i > 0 || ourSize == 0) { if (i > 0 || ourSize == 0) {
e.setTime(e.getTime() + t0); e.setTime(e.getTime() + t0);
e.setEnergy(e.getEnergy() + e0); e.setEnergy(e.getEnergy() + e0);
e.cost = e.cost + c0;
if (e.message != null){ if (e.message != null){
if (!(e.message.lon == e.getILon() && e.message.lat == e.getILat())) { if (!(e.message.lon == e.getILon() && e.message.lat == e.getILat())) {
e.message.lon = e.getILon(); e.message.lon = e.getILon();

View file

@ -77,6 +77,7 @@ public final class RoutingContext {
public double waypointCatchingRange; public double waypointCatchingRange;
public boolean correctMisplacedViaPoints; public boolean correctMisplacedViaPoints;
public double correctMisplacedViaPointsDistance; public double correctMisplacedViaPointsDistance;
public boolean continueStraight;
public boolean useDynamicDistance; public boolean useDynamicDistance;
public boolean buildBeelineOnRange; public boolean buildBeelineOnRange;
@ -126,6 +127,8 @@ public final class RoutingContext {
correctMisplacedViaPoints = 0.f != expctxGlobal.getVariableValue("correctMisplacedViaPoints", 1.f); correctMisplacedViaPoints = 0.f != expctxGlobal.getVariableValue("correctMisplacedViaPoints", 1.f);
correctMisplacedViaPointsDistance = expctxGlobal.getVariableValue("correctMisplacedViaPointsDistance", 0.f); // 0 == don't use distance correctMisplacedViaPointsDistance = expctxGlobal.getVariableValue("correctMisplacedViaPointsDistance", 0.f); // 0 == don't use distance
continueStraight = 0.f != expctxGlobal.getVariableValue("continueStraight", 0.f);
// process tags not used in the profile (to have them in the data-tab) // process tags not used in the profile (to have them in the data-tab)
processUnusedTags = 0.f != expctxGlobal.getVariableValue("processUnusedTags", 0.f); processUnusedTags = 0.f != expctxGlobal.getVariableValue("processUnusedTags", 0.f);
@ -221,6 +224,7 @@ public final class RoutingContext {
public String outputFormat = "gpx"; public String outputFormat = "gpx";
public boolean exportWaypoints = false; public boolean exportWaypoints = false;
public boolean exportCorrectedWaypoints = false;
public OsmPrePath firstPrePath; public OsmPrePath firstPrePath;

View file

@ -23,6 +23,7 @@ import btools.mapaccess.OsmLinkHolder;
import btools.mapaccess.OsmNode; import btools.mapaccess.OsmNode;
import btools.mapaccess.OsmNodePairSet; import btools.mapaccess.OsmNodePairSet;
import btools.mapaccess.OsmPos; import btools.mapaccess.OsmPos;
import btools.util.CheapAngleMeter;
import btools.util.CheapRuler; import btools.util.CheapRuler;
import btools.util.CompactLongMap; import btools.util.CompactLongMap;
import btools.util.SortedHeap; import btools.util.SortedHeap;
@ -262,6 +263,7 @@ public class RoutingEngine extends Thread {
} }
oldTrack = null; oldTrack = null;
track.exportWaypoints = routingContext.exportWaypoints; track.exportWaypoints = routingContext.exportWaypoints;
track.exportCorrectedWaypoints = routingContext.exportCorrectedWaypoints;
filename = outfileBase + i + "." + routingContext.outputFormat; filename = outfileBase + i + "." + routingContext.outputFormat;
switch (routingContext.outputFormat) { switch (routingContext.outputFormat) {
case "gpx": case "gpx":
@ -975,6 +977,10 @@ public class RoutingEngine extends Thread {
hasDirectRouting = true; hasDirectRouting = true;
} }
} }
for (MatchedWaypoint mwp : matchedWaypoints) {
//System.out.println(FormatGpx.getWaypoint(mwp.waypoint.ilon, mwp.waypoint.ilat, mwp.name, null));
//System.out.println(FormatGpx.getWaypoint(mwp.crosspoint.ilon, mwp.crosspoint.ilat, mwp.name+"_cp", null));
}
routingContext.hasDirectRouting = hasDirectRouting; routingContext.hasDirectRouting = hasDirectRouting;
@ -995,7 +1001,7 @@ public class RoutingEngine extends Thread {
} else { } else {
seg = searchTrack(matchedWaypoints.get(i), matchedWaypoints.get(i + 1), i == matchedWaypoints.size() - 2 ? nearbyTrack : null, refTracks[i]); seg = searchTrack(matchedWaypoints.get(i), matchedWaypoints.get(i + 1), i == matchedWaypoints.size() - 2 ? nearbyTrack : null, refTracks[i]);
wptIndex = i; wptIndex = i;
if (engineMode == BROUTER_ENGINEMODE_ROUNDTRIP) { if (routingContext.continueStraight) {
if (i < matchedWaypoints.size() - 2) { if (i < matchedWaypoints.size() - 2) {
OsmNode lastPoint = seg.containsNode(matchedWaypoints.get(i+1).node1) ? matchedWaypoints.get(i+1).node1 : matchedWaypoints.get(i+1).node2; OsmNode lastPoint = seg.containsNode(matchedWaypoints.get(i+1).node1) ? matchedWaypoints.get(i+1).node1 : matchedWaypoints.get(i+1).node2;
OsmNodeNamed nogo = new OsmNodeNamed(lastPoint); OsmNodeNamed nogo = new OsmNodeNamed(lastPoint);
@ -1015,7 +1021,7 @@ public class RoutingEngine extends Thread {
boolean changed = false; boolean changed = false;
if (routingContext.correctMisplacedViaPoints && !matchedWaypoints.get(i).direct && !routingContext.allowSamewayback) { if (routingContext.correctMisplacedViaPoints && !matchedWaypoints.get(i).direct && !routingContext.allowSamewayback) {
changed = snappPathConnection(totaltrack, seg, routingContext.inverseRouting ? matchedWaypoints.get(i + 1) : matchedWaypoints.get(i)); changed = snapPathConnection(totaltrack, seg, routingContext.inverseRouting ? matchedWaypoints.get(i + 1) : matchedWaypoints.get(i));
} }
if (wptIndex > 0) if (wptIndex > 0)
matchedWaypoints.get(wptIndex).indexInTrack = totaltrack.nodes.size() - 1; matchedWaypoints.get(wptIndex).indexInTrack = totaltrack.nodes.size() - 1;
@ -1038,12 +1044,198 @@ public class RoutingEngine extends Thread {
if (routingContext.poipoints != null) if (routingContext.poipoints != null)
totaltrack.pois = routingContext.poipoints; totaltrack.pois = routingContext.poipoints;
totaltrack.matchedWaypoints = matchedWaypoints;
return totaltrack; return totaltrack;
} }
OsmTrack getExtraSegment(OsmPathElement start, OsmPathElement end) {
List<MatchedWaypoint> wptlist = new ArrayList<>();
MatchedWaypoint wpt1 = new MatchedWaypoint();
wpt1.waypoint = new OsmNode(start.getILon(), start.getILat());
wpt1.name = "wptx1";
wpt1.crosspoint = new OsmNode(start.getILon(), start.getILat());
wpt1.node1 = new OsmNode(start.getILon(), start.getILat());
wpt1.node2 = new OsmNode(end.getILon(), end.getILat());
wptlist.add(wpt1);
MatchedWaypoint wpt2 = new MatchedWaypoint();
wpt2.waypoint = new OsmNode(end.getILon(), end.getILat());
wpt2.name = "wptx2";
wpt2.crosspoint = new OsmNode(end.getILon(), end.getILat());
wpt2.node2 = new OsmNode(start.getILon(), start.getILat());
wpt2.node1 = new OsmNode(end.getILon(), end.getILat());
wptlist.add(wpt2);
MatchedWaypoint mwp1 = wptlist.get(0);
MatchedWaypoint mwp2 = wptlist.get(1);
OsmTrack mid = null;
boolean corr = routingContext.correctMisplacedViaPoints;
routingContext.correctMisplacedViaPoints = false;
guideTrack = new OsmTrack();
guideTrack.addNode(start);
guideTrack.addNode(end);
mid = findTrack("getinfo", mwp1, mwp2, null, null, false);
guideTrack = null;
routingContext.correctMisplacedViaPoints = corr;
return mid;
}
private int snapRoundaboutConnection(OsmTrack tt, OsmTrack t, int indexStart, int indexEnd, int indexMeeting, MatchedWaypoint startWp) {
int indexMeetingBack = (indexMeeting == -1 ? tt.nodes.size() - 1 : indexMeeting);
int indexMeetingFore = 0;
int indexStartBack = indexStart;
int indexStartFore = 0;
OsmPathElement ptStart = tt.nodes.get(indexStartBack);
OsmPathElement ptMeeting = tt.nodes.get(indexMeetingBack);
OsmPathElement ptEnd = t.nodes.get(indexEnd);
boolean bMeetingIsOnRoundabout = ptMeeting.message.isRoundabout();
boolean bMeetsRoundaboutStart = false;
int i;
for (i = 0; i < indexEnd; i++) {
OsmPathElement n = t.nodes.get(i);
if (n.positionEquals(ptStart)) {
indexStartFore = i;
bMeetsRoundaboutStart = true;
}
if (n.positionEquals(ptMeeting)) {
indexMeetingFore = i;
}
}
if (!bMeetsRoundaboutStart && bMeetingIsOnRoundabout) {
indexEnd = indexMeetingFore;
}
if (bMeetsRoundaboutStart && bMeetingIsOnRoundabout) {
indexEnd = indexStartFore;
}
List<OsmPathElement> removeList = new ArrayList<>();
if (!bMeetsRoundaboutStart) {
indexStartBack = indexMeetingBack;
while (!tt.nodes.get(indexStartBack).message.isRoundabout()) {
indexStartBack--;
if (indexStartBack == 2) break;
}
}
for (i = indexStartBack + 1; i < tt.nodes.size(); i++) {
OsmPathElement n = tt.nodes.get(i);
OsmTrack.OsmPathElementHolder detours = tt.getFromDetourMap(n.getIdFromPos());
OsmTrack.OsmPathElementHolder h = detours;
while (h != null) {
h = h.nextHolder;
}
removeList.add(n);
}
OsmPathElement ttend = null;
OsmPathElement ttend_next = null;
if (!bMeetingIsOnRoundabout && !bMeetsRoundaboutStart) {
ttend = tt.nodes.get(indexStartBack);
ttend_next = tt.nodes.get(indexStartBack + 1);
OsmTrack.OsmPathElementHolder ttend_detours = tt.getFromDetourMap(ttend.getIdFromPos());
tt.registerDetourForId(ttend.getIdFromPos(), null);
}
for (OsmPathElement e : removeList) {
tt.nodes.remove(e);
}
removeList.clear();
for (i = 0; i < indexEnd; i++) {
OsmPathElement n = t.nodes.get(i);
if (n.positionEquals(bMeetsRoundaboutStart ? ptStart : ptEnd)) break;
if (!bMeetingIsOnRoundabout && !bMeetsRoundaboutStart && n.message.isRoundabout()) break;
OsmTrack.OsmPathElementHolder detours = t.getFromDetourMap(n.getIdFromPos());
OsmTrack.OsmPathElementHolder h = detours;
while (h != null) {
h = h.nextHolder;
}
removeList.add(n);
}
// time hold
float atime = 0;
float aenergy = 0;
int acost = 0;
if (i > 1) {
atime = t.nodes.get(i).getTime();
aenergy = t.nodes.get(i).getEnergy();
acost = t.nodes.get(i).cost;
}
for (OsmPathElement e : removeList) {
t.nodes.remove(e);
}
removeList.clear();
if (atime > 0f) {
for (OsmPathElement e : t.nodes) {
e.setTime(e.getTime() - atime);
e.setEnergy(e.getEnergy() - aenergy);
e.cost = e.cost - acost;
}
}
if (!bMeetingIsOnRoundabout && !bMeetsRoundaboutStart) {
OsmPathElement tstart = t.nodes.get(0);
OsmPathElement tstart_next = null;
OsmTrack.OsmPathElementHolder tstart_detours = t.getFromDetourMap(tstart.getIdFromPos());
OsmTrack.OsmPathElementHolder ttend_detours = tt.getFromDetourMap(ttend.getIdFromPos());
OsmTrack mid = getExtraSegment(ttend, ttend_detours.node);
OsmPathElement tt_end = tt.nodes.get(tt.nodes.size() - 1);
int last_cost = tt_end.cost;
int tmp_cost = 0;
if (mid != null) {
boolean start = false;
for (OsmPathElement e : mid.nodes) {
if (start) {
if (e.positionEquals(ttend_detours.node)) {
tmp_cost = e.cost;
break;
}
e.cost = last_cost + e.cost;
tt.nodes.add(e);
}
if (e.positionEquals(tt_end)) start = true;
}
}
ttend_detours.node.cost = last_cost + tmp_cost;
tt.nodes.add(ttend_detours.node);
t.nodes.add(0, ttend_detours.node);
}
tt.cost = tt.nodes.get(tt.nodes.size()-1).cost;
t.cost = t.nodes.get(t.nodes.size()-1).cost;
startWp.correctedpoint = new OsmNode(ptStart.getILon(), ptStart.getILat());
return (t.nodes.size());
}
// check for way back on way point // check for way back on way point
private boolean snappPathConnection(OsmTrack tt, OsmTrack t, MatchedWaypoint startWp) { private boolean snapPathConnection(OsmTrack tt, OsmTrack t, MatchedWaypoint startWp) {
if (!startWp.name.startsWith("via") && !startWp.name.startsWith("rt")) if (!startWp.name.startsWith("via") && !startWp.name.startsWith("rt"))
return false; return false;
@ -1075,29 +1267,88 @@ public class RoutingEngine extends Thread {
OsmPathElement newTarget = null; OsmPathElement newTarget = null;
OsmPathElement tmpback = null; OsmPathElement tmpback = null;
OsmPathElement tmpfore = null; OsmPathElement tmpfore = null;
OsmPathElement tmpStart = null;
int indexback = ourSize - 1; int indexback = ourSize - 1;
int indexfore = 0; int indexfore = 0;
int stop = (indexback - MAX_STEPS_CHECK > 1 ? indexback - MAX_STEPS_CHECK : 1); int stop = (indexback - MAX_STEPS_CHECK > 1 ? indexback - MAX_STEPS_CHECK : 1);
double wayDistance = 0; double wayDistance = 0;
double nextDist = 0; double nextDist = 0;
boolean bCheckRoundAbout = false;
boolean bBackRoundAbout = false;
boolean bForeRoundAbout = false;
int indexBackFound = 0;
int indexForeFound = 0;
int differentLanePoints = 0;
int indexMeeting = -1;
while (indexback >= 1 && indexback >= stop && indexfore < t.nodes.size()) {
tmpback = tt.nodes.get(indexback);
tmpfore = t.nodes.get(indexfore);
if (!bBackRoundAbout && tmpback.message != null && tmpback.message.isRoundabout()) {
bBackRoundAbout = true;
indexBackFound = indexfore;
}
if (!bForeRoundAbout &&
tmpfore.message != null && tmpfore.message.isRoundabout() ||
(tmpback.positionEquals(tmpfore) && tmpback.message.isRoundabout())) {
bForeRoundAbout = true;
indexForeFound = indexfore;
}
if (indexfore == 0) {
tmpStart = t.nodes.get(0);
} else {
double dirback = CheapAngleMeter.getDirection(tmpStart.getILon(), tmpStart.getILat(), tmpback.getILon(), tmpback.getILat());
double dirfore = CheapAngleMeter.getDirection(tmpStart.getILon(), tmpStart.getILat(), tmpfore.getILon(), tmpfore.getILat());
double dirdiff = CheapAngleMeter.getDifferenceFromDirection(dirback, dirfore);
// walking wrong direction
if (dirdiff > 60 && !bBackRoundAbout && !bForeRoundAbout) break;
}
// seems no roundabout, only on one end
if (bBackRoundAbout != bForeRoundAbout && indexfore - Math.abs(indexForeFound - indexBackFound) > 8) break;
if (!tmpback.positionEquals(tmpfore)) differentLanePoints++;
if (tmpback.positionEquals(tmpfore)) indexMeeting = indexback;
bCheckRoundAbout = bBackRoundAbout && bForeRoundAbout;
if (bCheckRoundAbout) break;
indexback--;
indexfore++;
}
//System.out.println("snap round result " + indexback + ": " + bBackRoundAbout + " - " + indexfore + "; " + bForeRoundAbout + " pts " + differentLanePoints);
if (bCheckRoundAbout) {
tmpback = tt.nodes.get(--indexback);
while (tmpback.message != null && tmpback.message.isRoundabout()) {
tmpback = tt.nodes.get(--indexback);
}
int ifore = ++indexfore;
OsmPathElement testfore = t.nodes.get(ifore);
while (ifore < t.nodes.size() && testfore.message != null && testfore.message.isRoundabout()) {
testfore = t.nodes.get(ifore);
ifore++;
}
snapRoundaboutConnection(tt, t, indexback, --ifore, indexMeeting, startWp);
// remove filled arrays
removeVoiceHintList.clear();
removeBackList.clear();
removeForeList.clear();
return true;
}
indexback = ourSize - 1;
indexfore = 0;
while (indexback >= 1 && indexback >= stop && indexfore < t.nodes.size()) { while (indexback >= 1 && indexback >= stop && indexfore < t.nodes.size()) {
int junctions = 0; int junctions = 0;
tmpback = tt.nodes.get(indexback); tmpback = tt.nodes.get(indexback);
tmpfore = t.nodes.get(indexfore); tmpfore = t.nodes.get(indexfore);
if (tmpback.message != null && tmpback.message.isRoundabout()) { if (tmpback.message != null && tmpback.message.isRoundabout()) {
removeBackList.clear(); bCheckRoundAbout = true;
removeForeList.clear();
removeVoiceHintList.clear();
return false;
} }
if (tmpfore.message != null && tmpfore.message.isRoundabout()) { if (tmpfore.message != null && tmpfore.message.isRoundabout()) {
removeBackList.clear(); bCheckRoundAbout = true;
removeForeList.clear();
removeVoiceHintList.clear();
return false;
} }
int dist = tmpback.calcDistance(tmpfore); {
if (1 == 1) {
int dist = tmpback.calcDistance(tmpfore);
OsmTrack.OsmPathElementHolder detours = tt.getFromDetourMap(tmpback.getIdFromPos()); OsmTrack.OsmPathElementHolder detours = tt.getFromDetourMap(tmpback.getIdFromPos());
OsmTrack.OsmPathElementHolder h = detours; OsmTrack.OsmPathElementHolder h = detours;
while (h != null) { while (h != null) {
@ -1105,48 +1356,56 @@ public class RoutingEngine extends Thread {
lastJunctions.put(h.node.getIdFromPos(), h); lastJunctions.put(h.node.getIdFromPos(), h);
h = h.nextHolder; h = h.nextHolder;
} }
}
if (dist == 1 && indexfore > 0) {
if (indexfore == 1) {
removeBackList.add(tt.nodes.get(tt.nodes.size() - 1)); // last and first should be equal, so drop only on second also equal
removeForeList.add(t.nodes.get(0));
removeBackList.add(tmpback);
removeForeList.add(tmpfore);
removeVoiceHintList.add(tt.nodes.size() - 1);
removeVoiceHintList.add(indexback);
} else {
removeBackList.add(tmpback);
removeForeList.add(tmpfore);
removeVoiceHintList.add(indexback);
}
nextDist = t.nodes.get(indexfore - 1).calcDistance(tmpfore);
wayDistance += nextDist;
} if (dist == 1 && indexfore > 0) {
if (dist > 1 || indexback == 1) { if (indexfore == 1) {
if (removeBackList.size() != 0) { removeBackList.add(tt.nodes.get(tt.nodes.size() - 1)); // last and first should be equal, so drop only on second also equal
// recover last - should be the cross point removeForeList.add(t.nodes.get(0));
removeBackList.remove(removeBackList.get(removeBackList.size() - 1)); removeBackList.add(tmpback);
removeForeList.remove(removeForeList.get(removeForeList.size() - 1)); removeForeList.add(tmpfore);
break; removeVoiceHintList.add(tt.nodes.size() - 1);
} else { removeVoiceHintList.add(indexback);
} else {
removeBackList.add(tmpback);
removeForeList.add(tmpfore);
removeVoiceHintList.add(indexback);
}
nextDist = t.nodes.get(indexfore - 1).calcDistance(tmpfore);
wayDistance += nextDist;
}
if (dist > 1 || indexback == 1) {
if (removeBackList.size() != 0) {
// recover last - should be the cross point
removeBackList.remove(removeBackList.get(removeBackList.size() - 1));
removeForeList.remove(removeForeList.get(removeForeList.size() - 1));
break;
} else {
return false;
}
}
indexback--;
indexfore++;
if (routingContext.correctMisplacedViaPointsDistance > 0 &&
wayDistance > routingContext.correctMisplacedViaPointsDistance) {
removeVoiceHintList.clear();
removeBackList.clear();
removeForeList.clear();
return false; return false;
} }
} }
indexback--;
indexfore++;
if (routingContext.correctMisplacedViaPointsDistance > 0 &&
wayDistance > routingContext.correctMisplacedViaPointsDistance) break;
} }
// time hold // time hold
float atime = 0; float atime = 0;
float aenergy = 0; float aenergy = 0;
int acost = 0;
if (removeForeList.size() > 1) { if (removeForeList.size() > 1) {
atime = t.nodes.get(removeForeList.size() - 2).getTime(); atime = t.nodes.get(indexfore -1).getTime();
aenergy = t.nodes.get(removeForeList.size() - 2).getEnergy(); aenergy = t.nodes.get(indexfore -1).getEnergy();
acost = t.nodes.get(indexfore -1).cost;
} }
for (OsmPathElement e : removeBackList) { for (OsmPathElement e : removeBackList) {
@ -1166,6 +1425,7 @@ public class RoutingEngine extends Thread {
for (OsmPathElement e : t.nodes) { for (OsmPathElement e : t.nodes) {
e.setTime(e.getTime() - atime); e.setTime(e.getTime() - atime);
e.setEnergy(e.getEnergy() - aenergy); e.setEnergy(e.getEnergy() - aenergy);
e.cost = e.cost - acost;
} }
} }
@ -1181,35 +1441,17 @@ public class RoutingEngine extends Thread {
newJunction = t.nodes.get(0); newJunction = t.nodes.get(0);
newTarget = t.nodes.get(1); newTarget = t.nodes.get(1);
setNewVoiceHint(t, last, lastJunctions, newJunction, newTarget); tt.cost = tt.nodes.get(tt.nodes.size()-1).cost;
t.cost = t.nodes.get(t.nodes.size()-1).cost;
// fill to correctedpoint
startWp.correctedpoint = new OsmNode(newJunction.getILon(), newJunction.getILat());
return true; return true;
} }
return false; return false;
} }
private void setNewVoiceHint(OsmTrack t, OsmPathElement last, CompactLongMap<OsmTrack.OsmPathElementHolder> lastJunctiona, OsmPathElement newJunction, OsmPathElement newTarget) {
if (last == null || newJunction == null || newTarget == null)
return;
int lon0,
lat0,
lon1,
lat1,
lon2,
lat2;
lon0 = last.getILon();
lat0 = last.getILat();
lon1 = newJunction.getILon();
lat1 = newJunction.getILat();
lon2 = newTarget.getILon();
lat2 = newTarget.getILat();
// get a new angle
double angle = routingContext.anglemeter.calcAngle(lon0, lat0, lon1, lat1, lon2, lat2);
newTarget.message.turnangle = (float) angle;
}
private void recalcTrack(OsmTrack t) { private void recalcTrack(OsmTrack t) {
int totaldist = 0; int totaldist = 0;
int totaltime = 0; int totaltime = 0;
@ -1553,7 +1795,7 @@ public class RoutingEngine extends Thread {
OsmPath p = getStartPath(n1, n2, new OsmNodeNamed(mwp.crosspoint), endPos, sameSegmentSearch); OsmPath p = getStartPath(n1, n2, new OsmNodeNamed(mwp.crosspoint), endPos, sameSegmentSearch);
// special case: start+end on same segment // special case: start+end on same segment
if (p.cost >= 0 && sameSegmentSearch && endPos != null && endPos.radius < 1.5) { if (p != null && p.cost >= 0 && sameSegmentSearch && endPos != null && endPos.radius < 1.5) {
p.treedepth = 0; // hack: mark for the final-check p.treedepth = 0; // hack: mark for the final-check
} }
return p; return p;
@ -1592,7 +1834,7 @@ public class RoutingEngine extends Thread {
if (bestLink != null) { if (bestLink != null) {
bestLink.addLinkHolder(bestPath, n1); bestLink.addLinkHolder(bestPath, n1);
} }
bestPath.treedepth = 1; if (bestPath != null) bestPath.treedepth = 1;
return bestPath; return bestPath;
} finally { } finally {
@ -1690,6 +1932,9 @@ public class RoutingEngine extends Thread {
logInfo("firstMatchCost from initial match=" + firstMatchCost); logInfo("firstMatchCost from initial match=" + firstMatchCost);
} }
if (startPath1 == null) return null;
if (startPath2 == null) return null;
synchronized (openSet) { synchronized (openSet) {
openSet.clear(); openSet.clear();
addToOpenset(startPath1); addToOpenset(startPath1);

View file

@ -227,6 +227,8 @@ public class RoutingParamCollector {
} }
} else if (key.equals("exportWaypoints")) { } else if (key.equals("exportWaypoints")) {
rctx.exportWaypoints = (Integer.parseInt(value) == 1); rctx.exportWaypoints = (Integer.parseInt(value) == 1);
} else if (key.equals("exportCorrectedWaypoints")) {
rctx.exportCorrectedWaypoints = (Integer.parseInt(value) == 1);
} else if (key.equals("format")) { } else if (key.equals("format")) {
rctx.outputFormat = ((String) value).toLowerCase(); rctx.outputFormat = ((String) value).toLowerCase();
} else if (key.equals("trackFormat")) { } else if (key.equals("trackFormat")) {

View file

@ -580,7 +580,11 @@ public class VoiceHint {
} else if (lowerBadWayAngle >= -100.f && higherBadWayAngle < 45.f) { } else if (lowerBadWayAngle >= -100.f && higherBadWayAngle < 45.f) {
cmd = KL; cmd = KL;
} else { } else {
cmd = C; if (lowerBadWayAngle > -35.f && higherBadWayAngle > 55.f) {
cmd = KR;
} else {
cmd = C;
}
} }
} else if (cmdAngle < 5.f) { } else if (cmdAngle < 5.f) {
if (lowerBadWayAngle > -30.f) { if (lowerBadWayAngle > -30.f) {
@ -597,7 +601,11 @@ public class VoiceHint {
} else if (lowerBadWayAngle > -45.f && higherBadWayAngle <= 100.f) { } else if (lowerBadWayAngle > -45.f && higherBadWayAngle <= 100.f) {
cmd = KR; cmd = KR;
} else { } else {
cmd = C; if (lowerBadWayAngle < -55.f && higherBadWayAngle < 35.f) {
cmd = KL;
} else {
cmd = C;
}
} }
} else if (cmdAngle < 45.f) { } else if (cmdAngle < 45.f) {
cmd = TSLR; cmd = TSLR;

View file

@ -116,6 +116,7 @@ public final class VoiceHintProcessor {
input.angle = roundAboutTurnAngle; input.angle = roundAboutTurnAngle;
input.goodWay.turnangle = roundAboutTurnAngle; input.goodWay.turnangle = roundAboutTurnAngle;
input.distanceToNext = distance; input.distanceToNext = distance;
input.turnAngleConsumed = true;
//input.roundaboutExit = startTurn < 0 ? roundaboutExit : -roundaboutExit; //input.roundaboutExit = startTurn < 0 ? roundaboutExit : -roundaboutExit;
input.roundaboutExit = roundAboutTurnAngle < 0 ? roundaboutExit : -roundaboutExit; input.roundaboutExit = roundAboutTurnAngle < 0 ? roundaboutExit : -roundaboutExit;
float tmpangle = 0; float tmpangle = 0;
@ -314,7 +315,13 @@ public final class VoiceHintProcessor {
input.cmd == VoiceHint.KR || input.cmd == VoiceHint.KR ||
input.cmd == VoiceHint.KL) input.cmd == VoiceHint.KL)
&& !input.goodWay.isLinktType()) { && !input.goodWay.isLinktType()) {
if (input.goodWay.getPrio() < input.maxBadPrio && (inputLastSaved != null && inputLastSaved.distanceToNext > catchingRange)) { if (
((Math.abs(input.lowerBadWayAngle) < 35.f ||
input.higherBadWayAngle < 35.f)
|| input.goodWay.getPrio() < input.maxBadPrio)
&& (inputLastSaved != null && inputLastSaved.distanceToNext > minRange)
&& (input.distanceToNext > minRange)
) {
results.add(input); results.add(input);
} else { } else {
if (inputLast != null) { // when drop add distance to last if (inputLast != null) { // when drop add distance to last

View file

@ -782,7 +782,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier {
public void parseFile(File file, String readOnlyContext, Map<String, String> keyValues) { public void parseFile(File file, String readOnlyContext, Map<String, String> keyValues) {
if (!file.exists()) { if (!file.exists()) {
throw new IllegalArgumentException("profile " + file + " does not exist"); throw new IllegalArgumentException("profile " + file.getName() + " does not exist");
} }
try { try {
if (readOnlyContext != null) { if (readOnlyContext != null) {
@ -813,12 +813,12 @@ public abstract class BExpressionContext implements IByteArrayUnifier {
variableData[i] = readOnlyData[i]; variableData[i] = readOnlyData[i];
} }
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new IllegalArgumentException("ParseException " + file + " at line " + linenr + ": " + e.getMessage()); throw new IllegalArgumentException("ParseException " + file.getName() + " at line " + linenr + ": " + e.getMessage());
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
if (expressionList.size() == 0) { if (expressionList.size() == 0) {
throw new IllegalArgumentException(file.getAbsolutePath() throw new IllegalArgumentException(file.getName()
+ " does not contain expressions for context " + context + " (old version?)"); + " does not contain expressions for context " + context + " (old version?)");
} }
} }

View file

@ -16,6 +16,7 @@ public final class MatchedWaypoint {
public OsmNode node2; public OsmNode node2;
public OsmNode crosspoint; public OsmNode crosspoint;
public OsmNode waypoint; public OsmNode waypoint;
public OsmNode correctedpoint;
public String name; // waypoint name used in error messages public String name; // waypoint name used in error messages
public double radius; // distance in meter between waypoint and crosspoint public double radius; // distance in meter between waypoint and crosspoint
public boolean direct; // from this point go direct to next = beeline routing public boolean direct; // from this point go direct to next = beeline routing

View file

@ -116,7 +116,7 @@ public final class WaypointMatcherImpl implements WaypointMatcher {
double r22 = x2 * x2 + y2 * y2; double r22 = x2 * x2 + y2 * y2;
double radius = Math.abs(r12 < r22 ? y1 * dx - x1 * dy : y2 * dx - x2 * dy) / d; double radius = Math.abs(r12 < r22 ? y1 * dx - x1 * dy : y2 * dx - x2 * dy) / d;
if (radius < mwp.radius) { if (radius <= mwp.radius) {
double s1 = x1 * dx + y1 * dy; double s1 = x1 * dx + y1 * dy;
double s2 = x2 * dx + y2 * dy; double s2 = x2 * dx + y2 * dy;

View file

@ -8,7 +8,7 @@ plugins {
} }
android { android {
compileSdk 35 compileSdk 36
base { base {
archivesName = "BRouterApp." + project.version archivesName = "BRouterApp." + project.version
@ -18,13 +18,13 @@ android {
namespace 'btools.routingapp' namespace 'btools.routingapp'
applicationId "btools.routingapp" applicationId "btools.routingapp"
versionCode 54 versionCode 55
versionName project.version versionName project.version
resValue('string', 'app_version', defaultConfig.versionName) resValue('string', 'app_version', defaultConfig.versionName)
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 34 targetSdkVersion 36
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@ -100,9 +100,9 @@ repositories {
} }
dependencies { dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'androidx.appcompat:appcompat:1.7.1'
implementation "androidx.constraintlayout:constraintlayout:2.1.4" implementation "androidx.constraintlayout:constraintlayout:2.2.1"
implementation 'androidx.work:work-runtime:2.9.0' implementation 'androidx.work:work-runtime:2.10.2'
implementation 'com.google.android.material:material:1.12.0' implementation 'com.google.android.material:material:1.12.0'
implementation project(':brouter-mapaccess') implementation project(':brouter-mapaccess')
@ -115,7 +115,7 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
androidTestImplementation 'androidx.work:work-testing:2.9.0' androidTestImplementation 'androidx.work:work-testing:2.10.2'
} }
gradle.projectsEvaluated { gradle.projectsEvaluated {

View file

@ -30,6 +30,7 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
@ -44,6 +45,8 @@ import btools.router.OsmTrack;
import btools.router.RoutingContext; import btools.router.RoutingContext;
import btools.router.RoutingEngine; import btools.router.RoutingEngine;
import btools.router.RoutingHelper; import btools.router.RoutingHelper;
import btools.router.RoutingParamCollector;
import btools.util.CheapRuler; import btools.util.CheapRuler;
public class BRouterView extends View { public class BRouterView extends View {
@ -437,6 +440,7 @@ public class BRouterView extends View {
public void startProcessing(String profile) { public void startProcessing(String profile) {
rawTrackPath = null; rawTrackPath = null;
String params = null;
if (profile.startsWith("<repeat")) { if (profile.startsWith("<repeat")) {
needsViaSelection = needsNogoSelection = needsWaypointSelection = false; needsViaSelection = needsNogoSelection = needsWaypointSelection = false;
try { try {
@ -446,6 +450,7 @@ public class BRouterView extends View {
rawTrackPath = br.readLine(); rawTrackPath = br.readLine();
wpList = readWpList(br, false); wpList = readWpList(br, false);
nogoList = readWpList(br, true); nogoList = readWpList(br, true);
params = br.readLine();
br.close(); br.close();
} catch (Exception e) { } catch (Exception e) {
AppLogger.log(AppLogger.formatThrowable(e)); AppLogger.log(AppLogger.formatThrowable(e));
@ -494,6 +499,15 @@ public class BRouterView extends View {
rc.localFunction = profilePath; rc.localFunction = profilePath;
rc.turnInstructionMode = cor.getTurnInstructionMode(); rc.turnInstructionMode = cor.getTurnInstructionMode();
if (params != null && params.length() > 2) {
try {
Map<String, String> profileParamsCollection = null;
RoutingParamCollector routingParamCollector = new RoutingParamCollector();
profileParamsCollection = routingParamCollector.getUrlParams(params);
routingParamCollector.setProfileParams(rc, profileParamsCollection);
} catch (Exception e) {}
}
int plain_distance = 0; int plain_distance = 0;
int maxlon = Integer.MIN_VALUE; int maxlon = Integer.MIN_VALUE;
int minlon = Integer.MAX_VALUE; int minlon = Integer.MAX_VALUE;

View file

@ -100,11 +100,19 @@ public class BRouterWorker {
} }
routingParamCollector.setParams(rc, waypoints, theParams); routingParamCollector.setParams(rc, waypoints, theParams);
Map<String, String> profileParamsCollection = null;
try {
if (profileParams != null) {
profileParamsCollection = routingParamCollector.getUrlParams(profileParams);
routingParamCollector.setProfileParams(rc, profileParamsCollection);
}
} catch (UnsupportedEncodingException e) {
// ignore
}
if (params.containsKey("extraParams")) { if (params.containsKey("extraParams")) {
Map<String, String> profileparams = null;
try { try {
profileparams = routingParamCollector.getUrlParams(params.getString("extraParams")); profileParamsCollection = routingParamCollector.getUrlParams(params.getString("extraParams"));
routingParamCollector.setProfileParams(rc, profileparams); routingParamCollector.setProfileParams(rc, profileParamsCollection);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
// ignore // ignore
} }
@ -161,6 +169,7 @@ public class BRouterWorker {
track = cr.getFoundTrack(); track = cr.getFoundTrack();
if (track != null) { if (track != null) {
track.exportWaypoints = rc.exportWaypoints; track.exportWaypoints = rc.exportWaypoints;
track.exportCorrectedWaypoints = rc.exportCorrectedWaypoints;
if (pathToFileResult == null) { if (pathToFileResult == null) {
switch (writeFromat) { switch (writeFromat) {
case OUTPUT_FORMAT_KML: case OUTPUT_FORMAT_KML:
@ -212,6 +221,14 @@ public class BRouterWorker {
bw.write("\n"); bw.write("\n");
writeWPList(bw, waypoints); writeWPList(bw, waypoints);
writeWPList(bw, rc.nogopoints); writeWPList(bw, rc.nogopoints);
if (rc.keyValues != null) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> e : rc.keyValues.entrySet()) {
sb.append(sb.length()>0 ? "&" : "").append(e.getKey()).append("=").append(e.getValue());
}
bw.write(sb.toString());
bw.write("\n");
}
bw.close(); bw.close();
} }

View file

@ -377,8 +377,8 @@ public class RoutingParameterDialog extends AppCompatActivity {
for (String tmp : sa) { for (String tmp : sa) {
// Add the name and address to the ListPreference enties and entyValues // Add the name and address to the ListPreference enties and entyValues
//L.v("AFTrack", "device: "+device.getName() + " -- " + device.getAddress()); //L.v("AFTrack", "device: "+device.getName() + " -- " + device.getAddress());
entryValues[i] = "" + i;
entries[i] = tmp.trim(); entries[i] = tmp.trim();
entryValues[i] = entries[i].split("=")[0].trim();
if (entryValues[i].equals(s)) ii = i; if (entryValues[i].equals(s)) ii = i;
i++; i++;
} }
@ -394,11 +394,14 @@ public class RoutingParameterDialog extends AppCompatActivity {
listPref.setSummary(p.description); listPref.setSummary(p.description);
listPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> { listPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> {
p.value = (String) newValue; p.value = (String) newValue;
int iii = Integer.decode(p.value); for (int iii = 0; iii < entryValues.length; iii++) {
listPref.setTitle(p.name + ": " + entries[iii]); String entryValue = entryValues[iii];
if (entryValue.equals(p.value)) {
listPref.setTitle(p.name + ": " + entries[iii]);
break;
}
}
return true; return true;
}); });
gpsPrefCat.addPreference(listPref); gpsPrefCat.addPreference(listPref);

View file

@ -160,8 +160,8 @@ public class RouteServer extends Thread implements Comparable<RouteServer> {
} else if (url.startsWith(PROFILE_UPLOAD_URL)) { } else if (url.startsWith(PROFILE_UPLOAD_URL)) {
if (getline.startsWith("OPTIONS")) { if (getline.startsWith("OPTIONS")) {
// handle CORS preflight request (Safari) // handle CORS preflight request (Safari)
String corsHeaders = "Access-Control-Allow-Methods: GET, POST\n" String corsHeaders = "Access-Control-Allow-Methods: GET, POST\r\n"
+ "Access-Control-Allow-Headers: Content-Type\n"; + "Access-Control-Allow-Headers: Content-Type\r\n";
writeHttpHeader(bw, "text/plain", null, corsHeaders, HTTP_STATUS_OK); writeHttpHeader(bw, "text/plain", null, corsHeaders, HTTP_STATUS_OK);
bw.flush(); bw.flush();
return; return;
@ -220,7 +220,7 @@ public class RouteServer extends Thread implements Comparable<RouteServer> {
// no zip for this engineMode // no zip for this engineMode
encodings = null; encodings = null;
} }
String headers = encodings == null || encodings.indexOf("gzip") < 0 ? null : "Content-Encoding: gzip\n"; String headers = encodings == null || encodings.indexOf("gzip") < 0 ? null : "Content-Encoding: gzip\r\n";
writeHttpHeader(bw, handler.getMimeType(), handler.getFileName(), headers, HTTP_STATUS_OK); writeHttpHeader(bw, handler.getMimeType(), handler.getFileName(), headers, HTTP_STATUS_OK);
if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUTING || if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUTING ||
engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUNDTRIP) { engineMode == RoutingEngine.BROUTER_ENGINEMODE_ROUNDTRIP) {
@ -407,17 +407,17 @@ public class RouteServer extends Thread implements Comparable<RouteServer> {
private static void writeHttpHeader(BufferedWriter bw, String mimeType, String fileName, String headers, String status) throws IOException { private static void writeHttpHeader(BufferedWriter bw, String mimeType, String fileName, String headers, String status) throws IOException {
// http-header // http-header
bw.write(String.format("HTTP/1.1 %s\n", status)); bw.write(String.format("HTTP/1.1 %s\r\n", status));
bw.write("Connection: close\n"); bw.write("Connection: close\r\n");
bw.write("Content-Type: " + mimeType + "; charset=utf-8\n"); bw.write("Content-Type: " + mimeType + "; charset=utf-8\r\n");
if (fileName != null) { if (fileName != null) {
bw.write("Content-Disposition: attachment; filename=\"" + fileName + "\"\n"); bw.write("Content-Disposition: attachment; filename=\"" + fileName + "\"\r\n");
} }
bw.write("Access-Control-Allow-Origin: *\n"); bw.write("Access-Control-Allow-Origin: *\r\n");
if (headers != null) { if (headers != null) {
bw.write(headers); bw.write(headers);
} }
bw.write("\n"); bw.write("\r\n");
} }
private static void cleanupThreadQueue(Queue<RouteServer> threadQueue) { private static void cleanupThreadQueue(Queue<RouteServer> threadQueue) {

View file

@ -78,6 +78,10 @@ public class ServerHandler extends RequestHandler {
if (exportWaypointsStr != null && Integer.parseInt(exportWaypointsStr) != 0) { if (exportWaypointsStr != null && Integer.parseInt(exportWaypointsStr) != 0) {
track.exportWaypoints = true; track.exportWaypoints = true;
} }
exportWaypointsStr = params.get("exportCorrectedWaypoints");
if (exportWaypointsStr != null && Integer.parseInt(exportWaypointsStr) != 0) {
track.exportCorrectedWaypoints = true;
}
if (format == null || "gpx".equals(format)) { if (format == null || "gpx".equals(format)) {
result = new FormatGpx(rc).format(track); result = new FormatGpx(rc).format(track);

View file

@ -14,6 +14,8 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
@ -28,7 +30,7 @@ public class RouteServerTest {
public static TemporaryFolder profileDir = new TemporaryFolder(); public static TemporaryFolder profileDir = new TemporaryFolder();
@BeforeClass @BeforeClass
public static void setupServer() throws IOException, InterruptedException { public static void setupServer() throws IOException, InterruptedException, URISyntaxException {
File workingDir = new File(".").getCanonicalFile(); File workingDir = new File(".").getCanonicalFile();
File segmentDir = new File(workingDir, "../brouter-map-creator/build/resources/test/tmp/segments"); File segmentDir = new File(workingDir, "../brouter-map-creator/build/resources/test/tmp/segments");
File profileSourceDir = new File(workingDir, "../misc/profiles2"); File profileSourceDir = new File(workingDir, "../misc/profiles2");
@ -41,7 +43,7 @@ public class RouteServerTest {
try { try {
RouteServer.main(new String[]{segmentDir.getAbsolutePath(), profileDir.getRoot().getAbsolutePath(), customProfileDir, port, "1"}); RouteServer.main(new String[]{segmentDir.getAbsolutePath(), profileDir.getRoot().getAbsolutePath(), customProfileDir, port, "1"});
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace(System.out);
} }
}; };
@ -49,7 +51,7 @@ public class RouteServerTest {
thread.start(); thread.start();
// Busy-wait for server startup // Busy-wait for server startup
URL requestUrl = new URL(baseUrl); URL requestUrl = new URI(baseUrl).toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
for (int i = 20; i >= 0; i--) { for (int i = 20; i >= 0; i--) {
try { try {
@ -66,8 +68,8 @@ public class RouteServerTest {
} }
@Test @Test
public void defaultRouteTrekking() throws IOException { public void defaultRouteTrekking() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "brouter?lonlats=8.723037,50.000491|8.712737,50.002899&nogos=&profile=trekking&alternativeidx=0&format=geojson"); URL requestUrl = new URI(baseUrl + "brouter?lonlats=8.723037,50.000491%7C8.712737,50.002899&nogos=&profile=trekking&alternativeidx=0&format=geojson").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect(); httpConnection.connect();
@ -82,8 +84,8 @@ public class RouteServerTest {
} }
@Test @Test
public void overrideParameter() throws IOException { public void overrideParameter() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "brouter?lonlats=8.723037,50.000491|8.712737,50.002899&nogos=&profile=trekking&alternativeidx=0&format=geojson&profile:avoid_unsafe=1"); URL requestUrl = new URI(baseUrl + "brouter?lonlats=8.723037,50.000491%7C8.712737,50.002899&nogos=&profile=trekking&alternativeidx=0&format=geojson&profile:avoid_unsafe=1").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect(); httpConnection.connect();
@ -95,8 +97,8 @@ public class RouteServerTest {
} }
@Test @Test
public void voiceHints() throws IOException { public void voiceHints() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "brouter?lonlats=8.705796,50.003124|8.705859,50.0039599&nogos=&profile=trekking&alternativeidx=0&format=geojson&timode=2"); URL requestUrl = new URI(baseUrl + "brouter?lonlats=8.705796,50.003124%7C8.705859,50.0039599&nogos=&profile=trekking&alternativeidx=0&format=geojson&timode=2").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect(); httpConnection.connect();
@ -108,8 +110,8 @@ public class RouteServerTest {
} }
@Test @Test
public void directRoutingFirst() throws IOException { public void directRoutingFirst() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "brouter?lonlats=8.718354,50.001514|8.718917,50.001361|8.716986,50.000105|8.718306,50.00145&nogos=&profile=trekking&alternativeidx=0&format=geojson&straight=0&timode=3"); URL requestUrl = new URI(baseUrl + "brouter?lonlats=8.718354,50.001514%7C8.718917,50.001361%7C8.716986,50.000105%7C8.718306,50.00145&nogos=&profile=trekking&alternativeidx=0&format=geojson&straight=0&timode=3").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect(); httpConnection.connect();
@ -121,8 +123,8 @@ public class RouteServerTest {
} }
@Test @Test
public void directRoutingLast() throws IOException { public void directRoutingLast() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "brouter?lonlats=8.718306,50.00145|8.717464,50.000405|8.718917,50.001361|8.718354,50.001514&nogos=&profile=trekking&alternativeidx=0&format=geojson&straight=2&timode=3"); URL requestUrl = new URI(baseUrl + "brouter?lonlats=8.718306,50.00145%7C8.717464,50.000405%7C8.718917,50.001361%7C8.718354,50.001514&nogos=&profile=trekking&alternativeidx=0&format=geojson&straight=2&timode=3").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect(); httpConnection.connect();
@ -134,8 +136,8 @@ public class RouteServerTest {
} }
@Test @Test
public void directRoutingMiddle() throws IOException { public void directRoutingMiddle() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "brouter?lonlats=8.718539,50.006581|8.718198,50.006065,d|8.71785,50.006034|8.7169,50.004456&nogos=&profile=trekking&alternativeidx=0&format=geojson&timode=3"); URL requestUrl = new URI(baseUrl + "brouter?lonlats=8.718539,50.006581%7C8.718198,50.006065,d%7C8.71785,50.006034%7C8.7169,50.004456&nogos=&profile=trekking&alternativeidx=0&format=geojson&timode=3").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect(); httpConnection.connect();
@ -147,8 +149,8 @@ public class RouteServerTest {
} }
@Test @Test
public void misplacedPoints() throws IOException { public void misplacedPoints() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "brouter?lonlats=8.708678,49.999188|8.71145,49.999761|8.715801,50.00065&nogos=&profile=trekking&alternativeidx=0&format=geojson&correctMisplacedViaPoints=1&timode=3"); URL requestUrl = new URI(baseUrl + "brouter?lonlats=8.708678,49.999188%7C8.71145,49.999761%7C8.715801,50.00065&nogos=&profile=trekking&alternativeidx=0&format=geojson&correctMisplacedViaPoints=1&timode=3").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect(); httpConnection.connect();
@ -160,8 +162,21 @@ public class RouteServerTest {
} }
@Test @Test
public void uploadValidProfile() throws IOException { public void misplacedPointsRoundabout() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "brouter/profile"); URL requestUrl = new URI(baseUrl + "brouter?lonlats=8.699487,50.001257%7C8.701569,50.000092%7C8.704873,49.998898&nogos=&profile=trekking&alternativeidx=0&format=geojson&profile:correctMisplacedViaPoints=1&timode=3").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect();
Assert.assertEquals(HttpURLConnection.HTTP_OK, httpConnection.getResponseCode());
InputStream inputStream = httpConnection.getInputStream();
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
Assert.assertEquals("482", geoJson.query("/features/0/properties/track-length"));
}
@Test
public void uploadValidProfile() throws IOException, URISyntaxException {
URL requestUrl = new URI(baseUrl + "brouter/profile").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.setRequestMethod("POST"); httpConnection.setRequestMethod("POST");
@ -192,8 +207,8 @@ public class RouteServerTest {
} }
@Test @Test
public void uploadInvalidProfile() throws IOException { public void uploadInvalidProfile() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "brouter/profile"); URL requestUrl = new URI(baseUrl + "brouter/profile").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.setRequestMethod("POST"); httpConnection.setRequestMethod("POST");
@ -214,8 +229,8 @@ public class RouteServerTest {
} }
@Test @Test
public void robots() throws IOException { public void robots() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "robots.txt"); URL requestUrl = new URI(baseUrl + "robots.txt").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect(); httpConnection.connect();
@ -226,8 +241,8 @@ public class RouteServerTest {
} }
@Test @Test
public void invalidUrl() throws IOException { public void invalidUrl() throws IOException, URISyntaxException {
URL requestUrl = new URL(baseUrl + "invalid"); URL requestUrl = new URI(baseUrl + "invalid").toURL();
HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection) requestUrl.openConnection();
httpConnection.connect(); httpConnection.connect();

View file

@ -12,7 +12,7 @@ import java.util.Map;
import java.util.Random; import java.util.Random;
public class StackSampler extends Thread { public class StackSampler extends Thread {
private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS", new Locale("en", "US")); private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS", new Locale.Builder().setLanguage("en").setRegion("US").build());
private BufferedWriter bw; private BufferedWriter bw;
private Random rand = new Random(); private Random rand = new Random();

View file

@ -6,13 +6,13 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:8.7.3' classpath 'com.android.tools.build:gradle:8.10.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }
} }
task clean(type: Delete) { tasks.register('clean', Delete) {
delete rootProject.buildDir delete rootProject.layout.buildDirectory
} }

View file

@ -4,4 +4,4 @@
// app: build.gradle (versionCode only) // app: build.gradle (versionCode only)
// OsmTrack (version and versionDate) // OsmTrack (version and versionDate)
// docs revisions.md (version and versionDate) // docs revisions.md (version and versionDate)
version '1.7.7' version '1.7.8'

View file

@ -2,7 +2,7 @@
(ZIP-Archives including APK, readme + profiles) (ZIP-Archives including APK, readme + profiles)
### next version ### [brouter-1.7.8.zip](../brouter_bin/brouter-1.7.8.zip) (current revision, 12.07.2025)
Android Android
@ -10,6 +10,8 @@ Android
- use parameter changed in the BRouter app - use parameter changed in the BRouter app
- reuse parameter for repeat:profile function - reuse parameter for repeat:profile function
- use unordered values for profile listbox (e.g. fastbike profile) - use unordered values for profile listbox (e.g. fastbike profile)
- Android 16
Library Library
@ -26,7 +28,7 @@ Library
[Solved issues](https://github.com/abrensch/brouter/issues?q=is%3Aissue+milestone%3A%22Version+1.7.8%22+is%3Aclosed) [Solved issues](https://github.com/abrensch/brouter/issues?q=is%3Aissue+milestone%3A%22Version+1.7.8%22+is%3Aclosed)
### [brouter-1.7.7.zip](../brouter_bin/brouter-1.7.7.zip) (current revision, 23.07.2024) ### [brouter-1.7.7.zip](../brouter_bin/brouter-1.7.7.zip) (23.07.2024)
- new Android API 34 - new Android API 34

Binary file not shown.

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

8
gradlew vendored
View file

@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# SPDX-License-Identifier: Apache-2.0
#
############################################################################## ##############################################################################
# #
@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
@ -84,7 +86,7 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@ -203,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.

2
gradlew.bat vendored
View file

@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################

View file

@ -2,7 +2,7 @@
/car-fast.brf /car-fast.brf
/fastbike-asia-pacific.brf /fastbike-asia-pacific.brf
/fastbike-lowtraffic.brf /fastbike-lowtraffic.brf
/safety.brf #/safety.brf
/trekking-ignore-cr.brf /trekking-ignore-cr.brf
/trekking-noferries.brf /trekking-noferries.brf
/trekking-nosteps.brf /trekking-nosteps.brf

View file

@ -23,7 +23,7 @@ assign allow_steps = true # %allow_steps% | Set to false to disallow
assign allow_ferries = true # %allow_ferries% | set to false to disallow ferries | boolean assign allow_ferries = true # %allow_ferries% | set to false to disallow ferries | boolean
assign allow_motorways = false # %allow_motorways% | Set to true to allow motorways (useful in Asia / Oceania for example) | boolean assign allow_motorways = false # %allow_motorways% | Set to true to allow motorways (useful in Asia / Oceania for example) | boolean
assign consider_traffic = false # %consider_traffic% | Activate to avoid traffic | boolean assign consider_traffic = 1 # %consider_traffic% | how do you plan to drive the tour? | [1=as cyclist alone in the week, 0.5=as cyclist alone at weekend, 0.3 =with a group of cyclists, 0.1=with a group of cyclists at week-end, 0.0=do not consider traffic]
assign consider_noise = false # %consider_noise% | Activate to prefer a low-noise route | boolean assign consider_noise = false # %consider_noise% | Activate to prefer a low-noise route | boolean
assign consider_river = false # %consider_river% | Activate to prefer a route along rivers, lakes, etc. | boolean assign consider_river = false # %consider_river% | Activate to prefer a route along rivers, lakes, etc. | boolean
assign consider_forest = false # %consider_forest% | Activate to prefer a route in forest or parks | boolean assign consider_forest = false # %consider_forest% | Activate to prefer a route in forest or parks | boolean
@ -154,43 +154,14 @@ assign onewaypenalty =
assign hascycleway = not assign hascycleway = not
and ( or cycleway= cycleway=no|none ) and ( or cycleway:left= cycleway:left=no ) ( or cycleway:right= cycleway:right=no ) and ( or cycleway= cycleway=no|none ) and ( or cycleway:left= cycleway:left=no ) ( or cycleway:right= cycleway:right=no )
assign trafficpenalty0 =
if consider_traffic then
(
if highway=primary|primary_link then
(
if estimated_traffic_class=4 then 0.2
else if estimated_traffic_class=5 then 0.4
else if estimated_traffic_class=6|7 then 0.6
else 0
)
else if highway=secondary|secondary_link then
(
if estimated_traffic_class=3 then 0.2
else if estimated_traffic_class=4 then 0.4
else if estimated_traffic_class=5 then 0.6
else if estimated_traffic_class=6|7 then 1
else 0
)
else if highway=tertiary|tertiary_link then
(
if estimated_traffic_class=2 then 0.1
else if estimated_traffic_class=3 then 0.3
else if estimated_traffic_class=4 then 0.5
else if estimated_traffic_class=5|6|7 then 1
else 0
)
else 0
)
else 0
assign trafficpenalty = assign trafficpenalty =
if consider_traffic then if estimated_traffic_class=|1|2 then 0
( else if estimated_traffic_class=3 then multiply 0.3 consider_traffic
if hascycleway then min 0.3 trafficpenalty0 else if estimated_traffic_class=4 then multiply 0.6 consider_traffic
else trafficpenalty0 else if estimated_traffic_class=5 then multiply 0.9 consider_traffic
) else if estimated_traffic_class=6|7 then multiply 1.5 consider_traffic
else 0 else 0
assign isresidentialorliving = or highway=residential|living_street living_street=yes assign isresidentialorliving = or highway=residential|living_street living_street=yes

View file

@ -15,7 +15,6 @@ assign consider_noise = false # %consider_noise% | Activate to prefe
assign consider_river = false # %consider_river% | Activate to prefer a route along rivers, lakes, etc. | boolean assign consider_river = false # %consider_river% | Activate to prefer a route along rivers, lakes, etc. | boolean
assign consider_forest = false # %consider_forest% | Activate to prefer a route in forest or green areas| boolean assign consider_forest = false # %consider_forest% | Activate to prefer a route in forest or green areas| boolean
assign consider_town = false # %consider_town% | Activate to bypass cities / big towns as far as possible | boolean assign consider_town = false # %consider_town% | Activate to bypass cities / big towns as far as possible | boolean
assign consider_traffic = 1 # %consider_traffic% | how do you plan to drive the tour? | [1=as cyclist alone in the week, 0.5=as cyclist alone at weekend, 0.3 =with a group of cyclists, 0.1=with a group of cyclists at week-end]
assign shortest_way 0 # 0 as default, duplicate shortest standard profile, SAC access limit ignored for now assign shortest_way 0 # 0 as default, duplicate shortest standard profile, SAC access limit ignored for now
@ -359,36 +358,7 @@ assign town_penalty
switch estimated_town_class=5 1.4 switch estimated_town_class=5 1.4
switch estimated_town_class=6 1.6 99 0 switch estimated_town_class=6 1.6 99 0
assign trafficpenalty = assign trafficpenalty = 0
# if any_cycleway then 0
# else
if highway=primary|primary_link then
(
if estimated_traffic_class=1|2 then 0
else if estimated_traffic_class=3 then multiply 0.4 consider_traffic
else if estimated_traffic_class=4 then multiply 0.8 consider_traffic
else if estimated_traffic_class=5 then multiply 1 consider_traffic
else if estimated_traffic_class=6|7 then multiply 2 consider_traffic
else multiply 0.6 consider_traffic
)
else if highway=secondary|secondary_link then
(
if estimated_traffic_class=1|2 then multiply 0.1 consider_traffic
else if estimated_traffic_class=3 then multiply 0.3 consider_traffic
else if estimated_traffic_class=4 then multiply 0.7 consider_traffic
else if estimated_traffic_class=5 then multiply 1 consider_traffic
else if estimated_traffic_class=6|7 then multiply 1.5 consider_traffic
else multiply 0.2 consider_traffic
)
else if highway=tertiary|tertiary_link then
(
if estimated_traffic_class=1|2 then multiply 0.1 consider_traffic
else if estimated_traffic_class=3 then multiply 0.2 consider_traffic
else if estimated_traffic_class=4 then multiply 0.5 consider_traffic
else multiply if estimated_traffic_class=5|6|7 then multiply 1 consider_traffic
else 0.1 consider_traffic
)
else 0
assign costfactor assign costfactor
add town_penalty add town_penalty

View file

@ -711,6 +711,11 @@ estimated_town_class;0000000001 4
estimated_town_class;0000000001 5 estimated_town_class;0000000001 5
estimated_town_class;0000000001 6 estimated_town_class;0000000001 6
lts_score;2000000001 1
lts_score;2000000002 2
lts_score;2000000003 3
lts_score;2000000004 4
---context:node ---context:node

403
misc/profiles2/safety.brf Normal file
View file

@ -0,0 +1,403 @@
# *** 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
# Bike profile
assign validForBikes = true
# Use the following switches to change behaviour
assign allow_steps = true # %allow_steps% | Set false to disallow steps | boolean
assign allow_ferries = true # %allow_ferries% | Set false to disallow ferries | boolean
assign ignore_cycleroutes = false # %ignore_cycleroutes% | Set true for better elevation results | boolean
assign stick_to_cycleroutes = false # %stick_to_cycleroutes% | Set true to just follow cycleroutes | boolean
assign avoid_unsafe = true # %avoid_unsafe% | Set true to avoid standard highways | boolean
assign add_beeline = false # %add_beeline% | Enable beeline on distant start/end points | boolean
assign consider_noise = false # %consider_noise% | Activate to prefer a low-noise route | boolean
assign consider_river = false # %consider_river% | Activate to prefer a route along rivers, lakes, etc. | boolean
assign consider_forest = false # %consider_forest% | Activate to prefer a route in forest or parks | boolean
assign consider_town = false # %consider_town% | Activate to bypass cities / big towns as far as possible | boolean
assign consider_traffic = false # %consider_traffic% | Activate to consider traffic estimates | boolean
# Change elevation parameters
assign consider_elevation = true # %consider_elevation% | Set true to favor a route with few elevation meters | boolean
assign downhillcost = 60 # %downhillcost% | Cost for going downhill | number
assign downhillcutoff = 1.5 # %downhillcutoff% | Gradients below this value in percents are not counted. | number
assign uphillcost = 0 # %uphillcost% | Cost for going uphill | number
assign uphillcutoff = 1.5 # %uphillcutoff% | Gradients below this value in percents are not counted. | number
assign downhillcost = if consider_elevation then downhillcost else 0
assign uphillcost = if consider_elevation then uphillcost else 0
# Kinematic model parameters (travel time computation)
assign totalMass = 90 # %totalMass% | Mass (in kg) of the bike + biker, for travel time computation | number
assign maxSpeed = 45 # %maxSpeed% | Absolute maximum speed (in km/h), for travel time computation | number
assign S_C_x = 0.225 # %S_C_x% | Drag coefficient times the reference area (in m^2), for travel time computation | number
assign C_r = 0.01 # %C_r% | Rolling resistance coefficient (dimensionless), for travel time computation | number
assign bikerPower = 100 # %bikerPower% | Average power (in W) provided by the biker, for travel time computation | number
# Turn instructions settings
assign turnInstructionMode = 1 # %turnInstructionMode% | Mode for the generated turn instructions | [0=none, 1=auto-choose, 2=locus-style, 3=osmand-style, 4=comment-style, 5=gpsies-style, 6=orux-style, 7=locus-old-style]
assign turnInstructionCatchingRange = 40 # %turnInstructionCatchingRange% | Within this distance (in m) several turning instructions are combined into one and the turning angles are better approximated to the general direction | number
assign turnInstructionRoundabouts = true # %turnInstructionRoundabouts% | Set "false" to avoid generating special turning instructions for roundabouts | boolean
assign considerTurnRestrictions = true # %considerTurnRestrictions% | Set true to take turn restrictions into account | boolean
assign processUnusedTags = true # %processUnusedTags% | Set true to output unused tags in data tab | boolean
---context:way # following code refers to way-tags
# classifier constants
assign classifier_none = 1
assign classifier_ferry = 2
#
# pre-calculate some logical expressions
#
assign any_cycleroute =
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 nodeaccessgranted =
if any_cycleroute then true
else lcn=yes
assign is_ldcr =
if ignore_cycleroutes then false
else any_cycleroute
assign isbike = or bicycle_road=yes or bicycle=yes or or bicycle=permissive bicycle=designated lcn=yes
assign ispaved = surface=paved|asphalt|concrete|paving_stones|sett
assign isunpaved = not or surface= or ispaved surface=fine_gravel|cobblestone
assign probablyGood = or ispaved and ( or isbike highway=footway ) 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 = if is_ldcr then 0
else if junction=roundabout then 0
else 90
#
# for any change in initialclassifier, initialcost is added once
#
assign initialclassifier =
if route=ferry then classifier_ferry
else classifier_none
#
# calculate the initial cost
# this is added to the total cost each time the costfactor
# changed
#
assign initialcost =
if ( equal initialclassifier classifier_ferry ) then 10000
else 0
#
# implicit access here just from the motorroad tag
# (implicit access rules from highway tag handled elsewhere)
#
assign defaultaccess =
if access= then not motorroad=yes
else if access=private|no then false
else true
#
# calculate logical bike access
#
assign bikeaccess =
if bicycle= then
(
if bicycle_road=yes then true
else if vehicle= then ( if highway=footway then false else defaultaccess )
else not vehicle=private|no
)
else not bicycle=private|no|dismount|use_sidepath
#
# calculate logical foot access
#
assign footaccess =
if bicycle=dismount then true
else if foot= then defaultaccess
else not foot=private|no|use_sidepath
#
# if not bike-, but foot-acess, just a moderate penalty,
# otherwise access is forbidden
#
assign accesspenalty =
if bikeaccess then 0
else if footaccess then 4
else if any_cycleroute then 15
else 10000
#
# 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 badoneway =
if reversedirection=yes then
if oneway:bicycle=yes then true
else if oneway= then junction=roundabout
else oneway=yes|true|1
else oneway=-1
assign onewaypenalty =
if ( badoneway ) then
(
if ( cycleway=opposite|opposite_lane|opposite_track ) then 0
else if ( cycleway:left=opposite|opposite_lane|opposite_track ) then 0
else if ( cycleway:right=opposite|opposite_lane|opposite_track ) then 0
else if ( oneway:bicycle=no ) then 0
else if ( cycleway:left:oneway=no ) then 0
else if ( cycleway:right:oneway=no ) then 0
else if ( not footaccess ) then 100
else if ( junction=roundabout|circular ) then 60
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
# add estimate tags
assign traffic_penalty
switch consider_traffic
switch estimated_traffic_class= 0
switch estimated_traffic_class=1|2 0.2
switch estimated_traffic_class=3 0.4
switch estimated_traffic_class=4 0.6
switch estimated_traffic_class=5 0.8
switch estimated_traffic_class=6|7 1 99 0
assign noise_penalty
switch consider_noise
switch estimated_noise_class= 0
switch estimated_noise_class=1 0.3
switch estimated_noise_class=2 0.5
switch estimated_noise_class=3 0.8
switch estimated_noise_class=4 1.4
switch estimated_noise_class=5 1.7
switch estimated_noise_class=6 2 0 0
assign no_river_penalty
switch consider_river
switch estimated_river_class= 2
switch estimated_river_class=1 1.3
switch estimated_river_class=2 1
switch estimated_river_class=3 0.7
switch estimated_river_class=4 0.4
switch estimated_river_class=5 0.1
switch estimated_river_class=6 0 99 0
assign no_forest_penalty
switch consider_forest
switch estimated_forest_class= 1
switch estimated_forest_class=1 0.5
switch estimated_forest_class=2 0.4
switch estimated_forest_class=3 0.25
switch estimated_forest_class=4 0.15
switch estimated_forest_class=5 0.1
switch estimated_forest_class=6 0 99 0
assign town_penalty
switch consider_town
switch estimated_town_class= 0
switch estimated_town_class=1 0.5
switch estimated_town_class=2 0.9
switch estimated_town_class=3 1.2
switch estimated_town_class=4 1.3
switch estimated_town_class=5 1.4
switch estimated_town_class=6 1.6 99 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 isresidentialorliving = or highway=residential|living_street living_street=yes
assign costfactor
#
# exclude rivers, rails etc.
#
if ( and highway= not route=ferry ) then 10000
#
# exclude motorways and proposed roads
#
else if ( highway=motorway|motorway_link ) then 10000
else if ( highway=proposed|abandoned ) then 10000
#
# all other exclusions below (access, steps, ferries,..)
# should not be deleted by the decoder, to be available
# in voice-hint-processing
#
else min 9999
add town_penalty
add no_forest_penalty
add no_river_penalty
add noise_penalty
add traffic_penalty
#
# apply oneway-and access-penalties
#
add max onewaypenalty accesspenalty
#
# steps and ferries are special. Note this is handled
# before the cycleroute-switch, to be able
# to really exclude them be setting cost to infinity
#
if ( highway=steps ) then ( if allow_steps then 40 else 10000 )
else if ( route=ferry ) then ( if allow_ferries then 5.67 else 10000 )
#
# handle long-distance cycle-routes.
#
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
#
if ( highway=pedestrian ) then 3
else if ( highway=bridleway ) then 5
else if ( highway=cycleway ) then 1
else if ( isresidentialorliving ) 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
#
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
#
else add ( if ( and avoid_unsafe not isbike ) then 2 else 0 )
#
# actuals roads are o.k. if we have a bike hint
#
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
#
else 2.0
# way priorities used for voice hint generation
assign priorityclassifier =
if ( highway=motorway ) then 30
else if ( highway=motorway_link ) then 29
else if ( highway=trunk ) then 28
else if ( highway=trunk_link ) then 27
else if ( highway=primary ) then 26
else if ( highway=primary_link ) then 25
else if ( highway=secondary ) then 24
else if ( highway=secondary_link ) then 23
else if ( highway=tertiary ) then 22
else if ( highway=tertiary_link ) then 21
else if ( highway=unclassified ) then 20
else if ( isresidentialorliving ) then 6
else if ( highway=service ) then 6
else if ( highway=cycleway ) then 6
else if ( or bicycle=designated bicycle_road=yes ) then 6
else if ( highway=track ) then if tracktype=grade1 then 6 else 4
else if ( highway=bridleway|road|path|footway ) then 4
else if ( highway=steps ) then 2
else if ( highway=pedestrian ) then 2
else 0
# some more classifying bits used for voice hint generation...
assign isbadoneway = not equal onewaypenalty 0
assign isgoodoneway = if reversedirection=yes then oneway=-1
else if oneway= then junction=roundabout else oneway=yes|true|1
assign isroundabout = junction=roundabout
assign islinktype = highway=motorway_link|trunk_link|primary_link|secondary_link|tertiary_link
assign isgoodforcars = if greater priorityclassifier 6 then true
else if ( or isresidentialorliving highway=service ) then true
else if ( and highway=track tracktype=grade1 ) then true
else false
# ... encoded into a bitmask
assign classifiermask add isbadoneway
add multiply isgoodoneway 2
add multiply isroundabout 4
add multiply islinktype 8
multiply isgoodforcars 16
# include `smoothness=` tags in the response's WayTags for track analysis
assign dummyUsage = smoothness=
---context:node # following code refers to node tags
assign defaultaccess =
if ( access= ) then true # add default barrier restrictions here!
else if ( access=private|no ) then false
else true
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 =
if bicycle=dismount then true
else if foot= then defaultaccess
else not foot=private|no
assign initialcost =
if bikeaccess then 0
else ( if footaccess then 100 else 1000000 )

View file

@ -12,6 +12,9 @@ assign validForFoot 1
---context:way # following code refers to way-tags ---context:way # following code refers to way-tags
# show unused tags
assign processUnusedTags = true
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 or route_bicycle_icn=yes or route_bicycle_ncn=yes or route_bicycle_rcn=yes route_bicycle_lcn=yes
assign nodeaccessgranted or any_cycleroute lcn=yes assign nodeaccessgranted or any_cycleroute lcn=yes

View file

@ -49,7 +49,7 @@ assign turnInstructionCatchingRange = 40 # %turnInstructionCatchingRange% | W
assign turnInstructionRoundabouts = true # %turnInstructionRoundabouts% | Set "false" to avoid generating special turning instructions for roundabouts | boolean assign turnInstructionRoundabouts = true # %turnInstructionRoundabouts% | Set "false" to avoid generating special turning instructions for roundabouts | boolean
assign considerTurnRestrictions = true # %considerTurnRestrictions% | Set true to take turn restrictions into account | boolean assign considerTurnRestrictions = true # %considerTurnRestrictions% | Set true to take turn restrictions into account | boolean
assign processUnusedTags = false # %processUnusedTags% | Set true to output unused tags in data tab | boolean assign processUnusedTags = true # %processUnusedTags% | Set true to output unused tags in data tab | boolean
---context:way # following code refers to way-tags ---context:way # following code refers to way-tags

File diff suppressed because it is too large Load diff

View file

@ -18,6 +18,7 @@ tables.lines = osm2pgsql.define_way_table('lines', {
{ column = 'waterway', type = 'text' }, { column = 'waterway', type = 'text' },
{ column = 'natural', type = 'text' }, { column = 'natural', type = 'text' },
{ column = 'width', type = 'text' }, { column = 'width', type = 'text' },
{ column = 'oneway', type = 'text' },
{ column = 'way', type = 'linestring', projection = srid, not_null = true }, { column = 'way', type = 'linestring', projection = srid, not_null = true },
}) })
@ -43,6 +44,7 @@ tables.polygons = osm2pgsql.define_area_table('polygons', {
tables.cities = osm2pgsql.define_node_table('cities', { tables.cities = osm2pgsql.define_node_table('cities', {
{ column = 'name', type = 'text' }, { column = 'name', type = 'text' },
{ column = 'name_en', type = 'text' },
{ column = 'place', type = 'text' }, { column = 'place', type = 'text' },
{ column = 'admin_level', type = 'text' }, { column = 'admin_level', type = 'text' },
{ column = 'osm_id', type = 'text' }, { column = 'osm_id', type = 'text' },
@ -56,6 +58,7 @@ tables.cities_rel = osm2pgsql.define_relation_table('cities_rel', {
{ column = 'admin_level', type = 'text' }, { column = 'admin_level', type = 'text' },
{ column = 'boundary', type = 'text' }, { column = 'boundary', type = 'text' },
{ column = 'name', type = 'text' }, { column = 'name', type = 'text' },
{ column = 'name_en', type = 'text' },
{ column = 'place', type = 'text' }, { column = 'place', type = 'text' },
{ column = 'osm_id', type = 'text' }, { column = 'osm_id', type = 'text' },
{ column = 'population', type = 'text' }, { column = 'population', type = 'text' },
@ -114,10 +117,11 @@ end
function osm2pgsql.process_node(object) function osm2pgsql.process_node(object)
if (object.tags.place == 'city' or object.tags.place == 'town' or object.tags.place == 'municipality') and has_area_tags(object.tags) then if (object.tags.place == 'city' or object.tags.place == 'town' or object.tags.place == 'village' or object.tags.place == 'municipality') and has_area_tags(object.tags) then
tables.cities:insert({ tables.cities:insert({
osm_id = object.id, osm_id = object.id,
name = object.tags.name, name = object.tags.name,
name_en = object.tags['name:en'],
place = object.tags.place, place = object.tags.place,
admin_level = object.tags.admin_level, admin_level = object.tags.admin_level,
population = object.tags.population, population = object.tags.population,
@ -166,6 +170,7 @@ function osm2pgsql.process_way(object)
natural = object.tags.natural, natural = object.tags.natural,
width = object.tags.width, width = object.tags.width,
maxspeed = object.tags.maxspeed, maxspeed = object.tags.maxspeed,
oneway = object.tags.oneway,
way = object:as_linestring() way = object:as_linestring()
}) })
end end
@ -202,6 +207,7 @@ function osm2pgsql.process_relation(object)
boundary = object.tags.boundary, boundary = object.tags.boundary,
admin_level = object.tags.admin_level, admin_level = object.tags.admin_level,
name = object.tags.name, name = object.tags.name,
name_en = object.tags['name:en'],
place = object.tags.place, place = object.tags.place,
population = object.tags.population, population = object.tags.population,
osm_id = object.id, osm_id = object.id,