Skip to content

Commit

Permalink
Merge pull request #729 from afischerdev/gen-beeline
Browse files Browse the repository at this point in the history
Enable a dynamic range search for matched way points
  • Loading branch information
afischerdev authored Nov 17, 2024
2 parents 218a088 + 566b693 commit d986ce9
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 23 deletions.
2 changes: 2 additions & 0 deletions brouter-codec/src/main/java/btools/codec/WaypointMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ public interface WaypointMatcher {
void transferNode(int ilon, int ilat);

void end();

boolean hasMatch(int lon, int lat);
}
2 changes: 1 addition & 1 deletion brouter-core/src/main/java/btools/router/FormatJson.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public String format(OsmTrack t) {
.append(sele).append("],\n");
nn = n;
}
sb.deleteCharAt(sb.lastIndexOf(","));
if (t.nodes != null && !t.nodes.isEmpty()) sb.deleteCharAt(sb.lastIndexOf(","));

sb.append(" ]\n");
sb.append(" }\n");
Expand Down
3 changes: 3 additions & 0 deletions brouter-core/src/main/java/btools/router/RoutingContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public String getProfileName() {
public double waypointCatchingRange;
public boolean correctMisplacedViaPoints;
public double correctMisplacedViaPointsDistance;
public boolean useDynamicDistance;

private void setModel(String className) {
if (className == null) {
Expand Down Expand Up @@ -168,6 +169,8 @@ public void readGlobalConfig() {
// Constant power of the biker (in W)
bikerPower = expctxGlobal.getVariableValue("bikerPower", 100.f);

useDynamicDistance = expctxGlobal.getVariableValue("use_dynamic_range", 0f) == 1f;

boolean test = expctxGlobal.getVariableValue("check_start_way", 1f) == 1f;
if (!test) expctxGlobal.freeNoWays();

Expand Down
69 changes: 68 additions & 1 deletion brouter-core/src/main/java/btools/router/RoutingEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class RoutingEngine extends Thread {

private int MAX_STEPS_CHECK = 10;

private int MAX_DYNAMIC_RANGE = 60000;

protected OsmTrack foundTrack = new OsmTrack();
private OsmTrack foundRawTrack = null;
private int alternativeIndex = 0;
Expand Down Expand Up @@ -587,7 +589,13 @@ private OsmTrack tryFindTrack(OsmTrack[] refTracks, OsmTrack[] lastTracks) {
mwp.direct = waypoints.get(i).direct;
matchedWaypoints.add(mwp);
}
int startSize = matchedWaypoints.size();
matchWaypointsToNodes(matchedWaypoints);
if (startSize < matchedWaypoints.size()) {
refTracks = new OsmTrack[matchedWaypoints.size()]; // used ways for alternatives
lastTracks = new OsmTrack[matchedWaypoints.size()];
hasDirectRouting = true;
}

routingContext.checkMatchedWaypointAgainstNogos(matchedWaypoints);

Expand Down Expand Up @@ -615,6 +623,12 @@ private OsmTrack tryFindTrack(OsmTrack[] refTracks, OsmTrack[] lastTracks) {
if (nearbyTrack != null) {
matchedWaypoints.add(nearbyTrack.endPoint);
}
} else {
if (lastTracks.length < matchedWaypoints.size()) {
refTracks = new OsmTrack[matchedWaypoints.size()]; // used ways for alternatives
lastTracks = new OsmTrack[matchedWaypoints.size()];
hasDirectRouting = true;
}
}

OsmPath.seg = 1; // set segment counter
Expand Down Expand Up @@ -968,7 +982,60 @@ private void recalcTrack(OsmTrack t) {
// geometric position matching finding the nearest routable way-section
private void matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints) {
resetCache(false);
nodesCache.matchWaypointsToNodes(unmatchedWaypoints, routingContext.waypointCatchingRange, islandNodePairs);
boolean useDynamicDistance = routingContext.useDynamicDistance;
double range = routingContext.waypointCatchingRange;
boolean ok = nodesCache.matchWaypointsToNodes(unmatchedWaypoints, range, islandNodePairs);
if (!ok && useDynamicDistance) {
logInfo("second check for way points");
resetCache(false);
range = -MAX_DYNAMIC_RANGE;
List<MatchedWaypoint> tmp = new ArrayList<>();
for (MatchedWaypoint mwp : unmatchedWaypoints) {
if (mwp.crosspoint == null) tmp.add(mwp);
}
ok = nodesCache.matchWaypointsToNodes(tmp, range, islandNodePairs);
}
if (!ok) {
for (MatchedWaypoint mwp : unmatchedWaypoints) {
if (mwp.crosspoint == null)
throw new IllegalArgumentException(mwp.name + "-position not mapped in existing datafile");
}
}
if (useDynamicDistance) {
List<MatchedWaypoint> waypoints = new ArrayList<>();
for (int i = 0; i < unmatchedWaypoints.size(); i++) {
MatchedWaypoint wp = unmatchedWaypoints.get(i);
if (wp.waypoint.calcDistance(wp.crosspoint) > routingContext.waypointCatchingRange) {
MatchedWaypoint nmw = new MatchedWaypoint();
if (i == 0) {
OsmNodeNamed onn = new OsmNodeNamed(wp.waypoint);
onn.name = "from";
nmw.waypoint = onn;
nmw.name = onn.name;
nmw.crosspoint = new OsmNode(wp.waypoint.ilon, wp.waypoint.ilat);
nmw.direct = true;
onn = new OsmNodeNamed(wp.crosspoint);
onn.name = wp.name + "_add";
wp.waypoint = onn;
} else {
OsmNodeNamed onn = new OsmNodeNamed(wp.crosspoint);
onn.name = wp.name + "_add";
nmw.waypoint = onn;
nmw.crosspoint = new OsmNode(wp.crosspoint.ilon, wp.crosspoint.ilat);
nmw.node1 = new OsmNode(wp.node1.ilon, wp.node1.ilat);
nmw.node2 = new OsmNode(wp.node2.ilon, wp.node2.ilat);
nmw.direct = true;
wp.crosspoint = new OsmNode(wp.waypoint.ilon, wp.waypoint.ilat);
}
if (wp.name != null) nmw.name = wp.name;
waypoints.add(nmw);
wp.name = wp.name + "_add";
}
waypoints.add(wp);
}
unmatchedWaypoints.clear();
unmatchedWaypoints.addAll(waypoints);
}
}

private OsmTrack searchTrack(MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack) {
Expand Down
35 changes: 23 additions & 12 deletions brouter-mapaccess/src/main/java/btools/mapaccess/NodesCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
import btools.expressions.BExpressionContextWay;

public final class NodesCache {

private int MAX_DYNAMIC_CATCHES = 20; // used with RoutingEngiine MAX_DYNAMIC_RANGE = 60000m

private File segmentDir;
private File secondarySegmentsDir = null;

Expand Down Expand Up @@ -177,7 +180,8 @@ public MicroCache getSegmentFor(int ilon, int ilat) {
}

MicroCache segment = osmf.getMicroCache(ilon, ilat);
if (segment == null) {
// needed for a second chance
if (segment == null || (waypointMatcher != null && ((WaypointMatcherImpl) waypointMatcher).useDynamicRange)) {
checkEnableCacheCleaning();
segment = osmf.createMicroCache(ilon, ilat, dataBuffers, expCtxWay, waypointMatcher, directWeaving ? nodesMap : null);

Expand Down Expand Up @@ -282,15 +286,15 @@ public OsmNode getGraphNode(OsmNode template) {
return existing;
}

public void matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints, double maxDistance, OsmNodePairSet islandNodePairs) {
public boolean matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints, double maxDistance, OsmNodePairSet islandNodePairs) {
waypointMatcher = new WaypointMatcherImpl(unmatchedWaypoints, maxDistance, islandNodePairs);
for (MatchedWaypoint mwp : unmatchedWaypoints) {
int cellsize = 12500;
preloadPosition(mwp.waypoint, cellsize);
preloadPosition(mwp.waypoint, cellsize, 1, false);
// get a second chance
if (mwp.crosspoint == null) {
if (mwp.crosspoint == null || mwp.radius > Math.abs(maxDistance)) {
cellsize = 1000000 / 32;
preloadPosition(mwp.waypoint, cellsize);
preloadPosition(mwp.waypoint, cellsize, maxDistance < 0 ? MAX_DYNAMIC_CATCHES : 2, maxDistance < 0);
}
}

Expand All @@ -305,29 +309,36 @@ public void matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints, doub
mwp.crosspoint = new OsmNode(mwp.waypoint.ilon, mwp.waypoint.ilat);
mwp.direct = true;
} else {
throw new IllegalArgumentException(mwp.name + "-position not mapped in existing datafile");
// do not break here throw new IllegalArgumentException(mwp.name + "-position not mapped in existing datafile");
return false;
}
}
if (unmatchedWaypoints.size() > 1 && i == unmatchedWaypoints.size() - 1 && unmatchedWaypoints.get(i - 1).direct) {
mwp.crosspoint = new OsmNode(mwp.waypoint.ilon, mwp.waypoint.ilat);
mwp.direct = true;
}
}
return true;
}

private void preloadPosition(OsmNode n, int d) {
private void preloadPosition(OsmNode n, int d, int maxscale, boolean bUseDynamicRange) {
first_file_access_failed = false;
first_file_access_name = null;
loadSegmentFor(n.ilon, n.ilat);
if (first_file_access_failed) {
throw new IllegalArgumentException("datafile " + first_file_access_name + " not found");
}
for (int idxLat = -1; idxLat <= 1; idxLat++)
for (int idxLon = -1; idxLon <= 1; idxLon++) {
if (idxLon != 0 || idxLat != 0) {
loadSegmentFor(n.ilon + d * idxLon, n.ilat + d * idxLat);
int scale = 1;
while (scale < maxscale) {
for (int idxLat = -scale; idxLat <= scale; idxLat++)
for (int idxLon = -scale; idxLon <= scale; idxLon++) {
if (idxLon != 0 || idxLat != 0) {
loadSegmentFor(n.ilon + d * idxLon, n.ilat + d * idxLat);
}
}
}
if (bUseDynamicRange && waypointMatcher.hasMatch(n.ilon, n.ilat)) break;
scale++;
}
}

private OsmFile fileForSegment(int lonDegree, int latDegree) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package btools.mapaccess;

import java.util.List;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import btools.codec.WaypointMatcher;
import btools.util.CheapRuler;
import btools.util.CheapAngleMeter;
import btools.util.CheapRuler;

/**
* the WaypointMatcher is feeded by the decoder with geoemtries of ways that are
Expand All @@ -29,13 +29,23 @@ public final class WaypointMatcherImpl implements WaypointMatcher {
private int lonLast;
private int latLast;
boolean useAsStartWay = true;
private int maxWptIdx;
private double maxDistance;
public boolean useDynamicRange = false;

private Comparator<MatchedWaypoint> comparator;

public WaypointMatcherImpl(List<MatchedWaypoint> waypoints, double maxDistance, OsmNodePairSet islandPairs) {
this.waypoints = waypoints;
this.islandPairs = islandPairs;
MatchedWaypoint last = null;
this.maxDistance = maxDistance;
if (maxDistance < 0.) {
this.maxDistance *= -1;
maxDistance *= -1;
useDynamicRange = true;
}

for (MatchedWaypoint mwp : waypoints) {
mwp.radius = maxDistance;
if (last != null && mwp.directionToNext == -1) {
Expand All @@ -50,6 +60,7 @@ public WaypointMatcherImpl(List<MatchedWaypoint> waypoints, double maxDistance,
} else {
last.directionToNext = CheapAngleMeter.getDirection(last.waypoint.ilon, last.waypoint.ilat, waypoints.get(lastidx).waypoint.ilon, waypoints.get(lastidx).waypoint.ilat);
}
maxWptIdx = waypoints.size() - 1;

// sort result list
comparator = new Comparator<>() {
Expand Down Expand Up @@ -79,7 +90,7 @@ private void checkSegment(int lon1, int lat1, int lon2, int lat2) {

//for ( MatchedWaypoint mwp : waypoints )
for (int i = 0; i < waypoints.size(); i++) {
if (!useAsStartWay && i==0) continue;
if (!useAsStartWay && i == 0) continue;
MatchedWaypoint mwp = waypoints.get(i);

if (mwp.direct &&
Expand All @@ -105,7 +116,7 @@ private void checkSegment(int lon1, int lat1, int lon2, int lat2) {
double r22 = x2 * x2 + y2 * y2;
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 s2 = x2 * dx + y2 * dy;

Expand All @@ -115,8 +126,10 @@ private void checkSegment(int lon1, int lat1, int lon2, int lat2) {
}
if (s2 > 0.) {
radius = Math.sqrt(s1 < s2 ? r12 : r22);
if (radius > mwp.radius)

if (radius > mwp.radius) {
continue;
}
}
// new match for that waypoint
mwp.radius = radius; // shortest distance to way
Expand Down Expand Up @@ -226,6 +239,17 @@ public void end() {
}
}

@Override
public boolean hasMatch(int lon, int lat) {
for (MatchedWaypoint mwp : waypoints) {
if (mwp.waypoint.ilon == lon && mwp.waypoint.ilat == lat &&
(mwp.radius < this.maxDistance || mwp.crosspoint != null)) {
return true;
}
}
return false;
}

// check limit of list size (avoid long runs)
void updateWayList(List<MatchedWaypoint> ways, MatchedWaypoint mw) {
ways.add(mw);
Expand Down
2 changes: 2 additions & 0 deletions misc/profiles2/car-vario.brf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ assign avoid_toll = false # %avoid_toll% | Avoid paid roads | boolean
assign avoid_unpaved = false # %avoid_unpaved% | Avoid unpaved roads, if possible | boolean
assign avoid_motorways = false # %avoid_motorways% | Avoid motorways | boolean

assign use_dynamic_range = false # %use_dynamic_range% | Enable distant start/end points | boolean

# Kinematic model parameters
assign vmax = 90 # %vmax% | Target speed (in km/h) | number
assign recup_efficiency = 0.7 # %recup_efficiency% | (ratio) | number
Expand Down
8 changes: 5 additions & 3 deletions misc/profiles2/gravel.brf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ assign turnInstructionRoundabouts true # %turnInstructionRoundabouts% | Special
assign considerTurnRestrictions true
assign turnInstructionMode 1 # %turnInstructionMode% | Mode for the generated turn-by-turn directions | [0=none, 1=auto-choose, 2=locus-style, 3=osmand-style, 4=comment-style, 5=gpsies-style, 6=oruxmaps-style]

assign use_dynamic_range = false # %use_dynamic_range% | Enable distant start/end points | boolean

#assign processUnusedTags true
assign pass1coefficient 4
assign validForBikes true
Expand Down Expand Up @@ -48,7 +50,7 @@ assign uphillcutoff switch bad_when_steep ( min 1.5 uphillcutoff ) uphillcut
assign any_cycleway or cycleway=track|lane|shared_lane|shared
or and cycleway:right=track|lane|shared_lane reversedirection=
and cycleway:left=track|lane|shared_lane reversedirection=yes

assign any_cycleroute or route_bicycle_icn=yes or route_bicycle_ncn=yes or route_bicycle_rcn=yes route_bicycle_lcn=yes

assign turncost switch junction=roundabout 15 65
Expand Down Expand Up @@ -166,7 +168,7 @@ assign is_paved

assign initialcost
multiply initialcost ( switch and prefer_unpaved_paths is_paved 2 1 )

assign smoothnesspenalty
multiply smoothnesspenalty ( switch and prefer_unpaved_paths is_paved 2 1 )

Expand Down Expand Up @@ -231,7 +233,7 @@ assign noforestpenalty
switch estimated_forest_class=6 1.0 1 1

assign townpenalty
switch avoid_towns
switch avoid_towns
switch estimated_town_class= 1.0
switch estimated_town_class=1 1.2
switch estimated_town_class=2 1.4
Expand Down
2 changes: 2 additions & 0 deletions misc/profiles2/hiking-mountain.brf
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ assign initialcost_value 0 # not used now
assign allow_steps true # %allow_steps% | Set to false to disallow steps | boolean
assign allow_ferries true # %allow_ferries% | set to false to disallow ferries | boolean

assign use_dynamic_range false # %use_dynamic_range% | Enable distant start/end points | boolean

assign cost_of_unknown 2 # 2 as default

#
Expand Down
4 changes: 3 additions & 1 deletion misc/profiles2/moped.brf
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ assign uphillcutoff 0
assign validForBikes 1
assign validForCars 1

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 use_dynamic_range = false # %use_dynamic_range% | Enable distant start/end points | boolean

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]

---context:way # following code refers to way-tags

Expand Down
3 changes: 3 additions & 0 deletions misc/profiles2/mtb.brf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

# bstart /global
---context:global

assign use_dynamic_range = false # %use_dynamic_range% | Enable distant start/end points | boolean

assign iswet 0 # 0 as default, *) flag for weather conditions
assign turnInstructionMode = 1 # 0=none, 1=auto-choose, 2=locus-style, 3=osmand-style
assign cycleroutes_pref 0.2 # also CRP *) costfactor penalty for not being cycleroute
Expand Down
2 changes: 2 additions & 0 deletions misc/profiles2/river.brf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

# the elevation parameters

assign use_dynamic_range = false # %use_dynamic_range% | Enable distant start/end points | boolean

assign downhillcost 0
assign downhillcutoff 1.5
assign uphillcost 0
Expand Down
Loading

0 comments on commit d986ce9

Please sign in to comment.