Merge pull request #494 from afischerdev/update-version
Update lib part three - ignore misplaced via points
This commit is contained in:
commit
2b9a9d5bdd
5 changed files with 245 additions and 15 deletions
|
@ -48,7 +48,7 @@ public final class OsmTrack {
|
|||
|
||||
public List<OsmNodeNamed> pois = new ArrayList<OsmNodeNamed>();
|
||||
|
||||
private static class OsmPathElementHolder {
|
||||
public static class OsmPathElementHolder {
|
||||
public OsmPathElement node;
|
||||
public OsmPathElementHolder nextHolder;
|
||||
}
|
||||
|
@ -928,6 +928,12 @@ public final class OsmTrack {
|
|||
return true;
|
||||
}
|
||||
|
||||
public OsmPathElementHolder getFromDetourMap(long id) {
|
||||
if (detourMap == null)
|
||||
return null;
|
||||
return detourMap.get(id);
|
||||
}
|
||||
|
||||
public void prepareSpeedProfile(RoutingContext rc) {
|
||||
// sendSpeedProfile = rc.keyValues != null && rc.keyValues.containsKey( "vmax" );
|
||||
}
|
||||
|
@ -987,6 +993,17 @@ public final class OsmTrack {
|
|||
return nodes.get(nodes.size() - 1).getTime();
|
||||
}
|
||||
|
||||
public void removeVoiceHint(int i) {
|
||||
if (voiceHints != null) {
|
||||
VoiceHint remove = null;
|
||||
for (VoiceHint vh : voiceHints.list) {
|
||||
if (vh.indexInTrack == i)
|
||||
remove = vh;
|
||||
}
|
||||
if (remove != null)
|
||||
voiceHints.list.remove(remove);
|
||||
}
|
||||
}
|
||||
|
||||
private MessageData startSection(OsmPathElement element, OsmPathElement root) {
|
||||
OsmPathElement e = element;
|
||||
|
|
|
@ -78,6 +78,8 @@ public final class RoutingContext {
|
|||
public boolean transitonly;
|
||||
|
||||
public double waypointCatchingRange;
|
||||
public boolean correctMisplacedViaPoints;
|
||||
public double correctMisplacedViaPointsDistance;
|
||||
|
||||
private void setModel(String className) {
|
||||
if (className == null) {
|
||||
|
@ -114,8 +116,8 @@ public final class RoutingContext {
|
|||
// add parameter to context
|
||||
for (Map.Entry<String, String> e : keyValues.entrySet()) {
|
||||
float f = Float.parseFloat(e.getValue());
|
||||
expctxWay.setVariableValue(e.getKey(), f, false);
|
||||
expctxNode.setVariableValue(e.getKey(), f, false);
|
||||
expctxWay.setVariableValue(e.getKey(), f, true);
|
||||
expctxNode.setVariableValue(e.getKey(), f, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,6 +138,9 @@ public final class RoutingContext {
|
|||
// turn-restrictions not used per default for foot profiles
|
||||
considerTurnRestrictions = 0.f != expctxGlobal.getVariableValue("considerTurnRestrictions", footMode ? 0.f : 1.f);
|
||||
|
||||
correctMisplacedViaPoints = 0.f != expctxGlobal.getVariableValue("correctMisplacedViaPoints", 1.f);
|
||||
correctMisplacedViaPointsDistance = expctxGlobal.getVariableValue("correctMisplacedViaPointsDistance", 40.f);
|
||||
|
||||
// process tags not used in the profile (to have them in the data-tab)
|
||||
processUnusedTags = 0.f != expctxGlobal.getVariableValue("processUnusedTags", 0.f);
|
||||
|
||||
|
@ -457,7 +462,7 @@ public final class RoutingContext {
|
|||
}
|
||||
}
|
||||
}
|
||||
return (int) (d + 1.0);
|
||||
return (int) (d + 0.5);
|
||||
}
|
||||
|
||||
public OsmPathModel pm;
|
||||
|
|
|
@ -16,6 +16,7 @@ import btools.mapaccess.OsmLink;
|
|||
import btools.mapaccess.OsmLinkHolder;
|
||||
import btools.mapaccess.OsmNode;
|
||||
import btools.mapaccess.OsmNodePairSet;
|
||||
import btools.util.CompactLongMap;
|
||||
import btools.util.SortedHeap;
|
||||
import btools.util.StackSampler;
|
||||
|
||||
|
@ -32,6 +33,8 @@ public class RoutingEngine extends Thread {
|
|||
private int MAXNODES_ISLAND_CHECK = 500;
|
||||
private OsmNodePairSet islandNodePairs = new OsmNodePairSet(MAXNODES_ISLAND_CHECK);
|
||||
|
||||
private int MAX_STEPS_CHECK = 10;
|
||||
|
||||
protected OsmTrack foundTrack = new OsmTrack();
|
||||
private OsmTrack foundRawTrack = null;
|
||||
private int alternativeIndex = 0;
|
||||
|
@ -358,15 +361,26 @@ public class RoutingEngine extends Thread {
|
|||
}
|
||||
|
||||
OsmTrack seg;
|
||||
int wptIndex;
|
||||
if (routingContext.inverseRouting) {
|
||||
routingContext.inverseDirection = true;
|
||||
seg = searchTrack(matchedWaypoints.get(i + 1), matchedWaypoints.get(i), null, refTracks[i]);
|
||||
routingContext.inverseDirection = false;
|
||||
wptIndex = i + 1;
|
||||
} else {
|
||||
seg = searchTrack(matchedWaypoints.get(i), matchedWaypoints.get(i + 1), i == matchedWaypoints.size() - 2 ? nearbyTrack : null, refTracks[i]);
|
||||
wptIndex = i;
|
||||
}
|
||||
if (seg == null)
|
||||
return null;
|
||||
|
||||
boolean changed = false;
|
||||
if (routingContext.correctMisplacedViaPoints && !matchedWaypoints.get(i).direct) {
|
||||
changed = snappPathConnection(totaltrack, seg, routingContext.inverseRouting ? matchedWaypoints.get(i + 1) : matchedWaypoints.get(i));
|
||||
}
|
||||
// if (wptIndex > 0)
|
||||
// matchedWaypoints.get(wptIndex).indexInTrack = totaltrack.nodes.size() - 1;
|
||||
|
||||
if (seg == null) return null;
|
||||
totaltrack.appendTrack(seg);
|
||||
lastTracks[i] = seg;
|
||||
}
|
||||
|
@ -375,6 +389,172 @@ public class RoutingEngine extends Thread {
|
|||
return totaltrack;
|
||||
}
|
||||
|
||||
// check for way back on way point
|
||||
private boolean snappPathConnection(OsmTrack tt, OsmTrack t, MatchedWaypoint startWp) {
|
||||
if (!startWp.name.startsWith("via"))
|
||||
return false;
|
||||
|
||||
int ourSize = tt.nodes.size();
|
||||
if (ourSize > 0) {
|
||||
OsmPathElement testPoint = tt.nodes.get(ourSize - 1);
|
||||
if (routingContext.poipoints != null) {
|
||||
for (OsmNodeNamed node : routingContext.poipoints) {
|
||||
|
||||
int lon0 = tt.nodes.get(ourSize - 2).getILon();
|
||||
int lat0 = tt.nodes.get(ourSize - 2).getILat();
|
||||
int lon1 = startWp.crosspoint.ilon;
|
||||
int lat1 = startWp.crosspoint.ilat;
|
||||
int lon2 = node.ilon;
|
||||
int lat2 = node.ilat;
|
||||
double angle3 = routingContext.anglemeter.calcAngle(lon0, lat0, lon1, lat1, lon2, lat2);
|
||||
int dist = node.calcDistance(startWp.crosspoint);
|
||||
if (dist < routingContext.waypointCatchingRange)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ArrayList<OsmPathElement> removeBackList = new ArrayList<>();
|
||||
ArrayList<OsmPathElement> removeForeList = new ArrayList<>();
|
||||
ArrayList<Integer> removeVoiceHintList = new ArrayList<>();
|
||||
int lon0,
|
||||
lat0,
|
||||
lon1,
|
||||
lat1,
|
||||
lon2,
|
||||
lat2;
|
||||
OsmPathElement last = null;
|
||||
OsmPathElement lastJunction = null;
|
||||
CompactLongMap<OsmTrack.OsmPathElementHolder> lastJunctions = new CompactLongMap<>();
|
||||
OsmPathElement newJunction = null;
|
||||
OsmPathElement newTarget = null;
|
||||
OsmPathElement tmpback = null;
|
||||
OsmPathElement tmpfore = null;
|
||||
int indexback = ourSize - 1;
|
||||
int indexfore = 0;
|
||||
int stop = (indexback - MAX_STEPS_CHECK > 1 ? indexback - MAX_STEPS_CHECK : 1);
|
||||
double wayDistance = 0;
|
||||
double nextDist = 0;
|
||||
while (indexback >= 1 && indexback >= stop && indexfore < t.nodes.size()) {
|
||||
int junctions = 0;
|
||||
tmpback = tt.nodes.get(indexback);
|
||||
tmpfore = t.nodes.get(indexfore);
|
||||
int dist = tmpback.calcDistance(tmpfore);
|
||||
if (1 == 1) {
|
||||
OsmTrack.OsmPathElementHolder detours = tt.getFromDetourMap(tmpback.getIdFromPos());
|
||||
OsmTrack.OsmPathElementHolder h = detours;
|
||||
while (h != null) {
|
||||
junctions++;
|
||||
lastJunctions.put(h.node.getIdFromPos(), h);
|
||||
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 || 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;
|
||||
}
|
||||
|
||||
// time hold
|
||||
float atime = 0;
|
||||
float aenergy = 0;
|
||||
if (removeForeList.size() > 1) {
|
||||
atime = t.nodes.get(removeForeList.size() - 2).getTime();
|
||||
aenergy = t.nodes.get(removeForeList.size() - 2).getEnergy();
|
||||
}
|
||||
|
||||
for (OsmPathElement e : removeBackList) {
|
||||
tt.nodes.remove(e);
|
||||
}
|
||||
for (OsmPathElement e : removeForeList) {
|
||||
t.nodes.remove(e);
|
||||
}
|
||||
for (Integer e : removeVoiceHintList) {
|
||||
tt.removeVoiceHint(e);
|
||||
}
|
||||
removeVoiceHintList.clear();
|
||||
removeBackList.clear();
|
||||
removeForeList.clear();
|
||||
|
||||
if (atime > 0f) {
|
||||
for (OsmPathElement e : t.nodes) {
|
||||
e.setTime(e.getTime() - atime);
|
||||
e.setEnergy(e.getEnergy() - aenergy);
|
||||
}
|
||||
}
|
||||
|
||||
if (t.nodes.size() < 2)
|
||||
return true;
|
||||
if (tt.nodes.size() < 1)
|
||||
return true;
|
||||
if (tt.nodes.size() == 1) {
|
||||
last = tt.nodes.get(0);
|
||||
} else {
|
||||
last = tt.nodes.get(tt.nodes.size() - 2);
|
||||
}
|
||||
newJunction = t.nodes.get(0);
|
||||
newTarget = t.nodes.get(1);
|
||||
|
||||
setNewVoiceHint(t, last, lastJunctions, newJunction, newTarget);
|
||||
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// geometric position matching finding the nearest routable way-section
|
||||
private void matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints) {
|
||||
resetCache(false);
|
||||
|
@ -386,7 +566,8 @@ public class RoutingEngine extends Thread {
|
|||
try {
|
||||
boolean calcBeeline = startWp.direct;
|
||||
|
||||
if (!calcBeeline) return searchRoutedTrack(startWp, endWp, nearbyTrack, refTrack);
|
||||
if (!calcBeeline)
|
||||
return searchRoutedTrack(startWp, endWp, nearbyTrack, refTrack);
|
||||
|
||||
// we want a beeline-segment
|
||||
OsmPath path = routingContext.createPath(new OsmLink(null, startWp.crosspoint));
|
||||
|
@ -399,7 +580,10 @@ public class RoutingEngine extends Thread {
|
|||
|
||||
private OsmTrack searchRoutedTrack(MatchedWaypoint startWp, MatchedWaypoint endWp, OsmTrack nearbyTrack, OsmTrack refTrack) {
|
||||
OsmTrack track = null;
|
||||
double[] airDistanceCostFactors = new double[]{routingContext.pass1coefficient, routingContext.pass2coefficient};
|
||||
double[] airDistanceCostFactors = new double[]{
|
||||
routingContext.pass1coefficient,
|
||||
routingContext.pass2coefficient
|
||||
};
|
||||
boolean isDirty = false;
|
||||
IllegalArgumentException dirtyMessage = null;
|
||||
|
||||
|
@ -526,10 +710,14 @@ public class RoutingEngine extends Thread {
|
|||
double minradius = 1e10;
|
||||
for (OsmLink link = n1.firstlink; link != null; link = link.getNext(n1)) {
|
||||
OsmNode nextNode = link.getTarget(n1);
|
||||
if (nextNode.isHollow()) continue; // border node?
|
||||
if (nextNode.firstlink == null) continue; // don't care about dead ends
|
||||
if (nextNode == n1) continue; // ?
|
||||
if (nextNode != n2) continue; // just that link
|
||||
if (nextNode.isHollow())
|
||||
continue; // border node?
|
||||
if (nextNode.firstlink == null)
|
||||
continue; // don't care about dead ends
|
||||
if (nextNode == n1)
|
||||
continue; // ?
|
||||
if (nextNode != n2)
|
||||
continue; // just that link
|
||||
|
||||
wp.radius = 1.5;
|
||||
OsmPath testPath = routingContext.createPath(startPath, link, null, guideTrack != null);
|
||||
|
@ -686,7 +874,6 @@ public class RoutingEngine extends Thread {
|
|||
if (directWeaving && nodesCache.hasHollowLinkTargets(path.getTargetNode())) {
|
||||
if (!memoryPanicMode) {
|
||||
if (!nodesCache.nodesMap.isInMemoryBounds(openSet.getSize(), false)) {
|
||||
// System.out.println( "collecting..." );
|
||||
int nodesBefore = nodesCache.nodesMap.nodesCreated;
|
||||
int pathsBefore = openSet.getSize();
|
||||
|
||||
|
@ -901,7 +1088,8 @@ public class RoutingEngine extends Thread {
|
|||
routingContext.setWaypoint(endPos, true);
|
||||
}
|
||||
OsmPath testPath = routingContext.createPath(otherPath, link, refTrack, guideTrack != null);
|
||||
if (testPath.cost >= 0 && (bestPath == null || testPath.cost < bestPath.cost)) {
|
||||
if (testPath.cost >= 0 && (bestPath == null || testPath.cost < bestPath.cost) &&
|
||||
(testPath.sourceNode.getIdFromPos() != testPath.targetNode.getIdFromPos())) {
|
||||
bestPath = testPath;
|
||||
}
|
||||
} finally {
|
||||
|
@ -962,7 +1150,7 @@ public class RoutingEngine extends Thread {
|
|||
OsmPathElement element = OsmPathElement.create(path, false);
|
||||
|
||||
// for final track, cut endnode
|
||||
if (guideTrack != null) {
|
||||
if (guideTrack != null && element.origin != null) {
|
||||
element = element.origin;
|
||||
}
|
||||
|
||||
|
|
|
@ -834,6 +834,15 @@ public abstract class BExpressionContext implements IByteArrayUnifier {
|
|||
Integer num = variableNumbers.get(name);
|
||||
if (num != null) {
|
||||
variableData[num.intValue()] = value;
|
||||
} else if (create) {
|
||||
num = getVariableIdx(name, create);
|
||||
float[] readOnlyData = variableData;
|
||||
int minWriteIdx = readOnlyData.length;
|
||||
variableData = new float[variableNumbers.size()];
|
||||
for (int i = 0; i < minWriteIdx; i++) {
|
||||
variableData[i] = readOnlyData[i];
|
||||
}
|
||||
variableData[num.intValue()] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@ public class RouteServerTest {
|
|||
InputStream inputStream = httpConnection.getInputStream();
|
||||
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
||||
Assert.assertEquals(2, geoJson.query("/features/0/properties/voicehints/0/1")); // TL
|
||||
Assert.assertEquals(1, geoJson.query("/features/0/properties/voicehints/1/1")); // C
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -145,6 +144,18 @@ public class RouteServerTest {
|
|||
Assert.assertEquals("350", geoJson.query("/features/0/properties/track-length"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void misplacedPoints() throws IOException {
|
||||
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");
|
||||
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("598", geoJson.query("/features/0/properties/track-length"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uploadValidProfile() throws IOException {
|
||||
|
|
Loading…
Reference in a new issue