Merge pull request #498 from afischerdev/update-version
Update lib part four - recalculation at end of track
This commit is contained in:
commit
2387513a1f
5 changed files with 422 additions and 42 deletions
|
@ -36,6 +36,10 @@ public class OsmPathElement implements OsmPos {
|
||||||
return selev;
|
return selev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void setSElev(short s) {
|
||||||
|
selev = s;
|
||||||
|
}
|
||||||
|
|
||||||
public final double getElev() {
|
public final double getElev() {
|
||||||
return selev / 4.;
|
return selev / 4.;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +64,12 @@ public class OsmPathElement implements OsmPos {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void setAngle(float e) {
|
||||||
|
if (message != null) {
|
||||||
|
message.turnangle = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final long getIdFromPos() {
|
public final long getIdFromPos() {
|
||||||
return ((long) ilon) << 32 | ilat;
|
return ((long) ilon) << 32 | ilat;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +83,7 @@ public class OsmPathElement implements OsmPos {
|
||||||
// construct a path element from a path
|
// construct a path element from a path
|
||||||
public static final OsmPathElement create(OsmPath path, boolean countTraffic) {
|
public static final OsmPathElement create(OsmPath path, boolean countTraffic) {
|
||||||
OsmNode n = path.getTargetNode();
|
OsmNode n = path.getTargetNode();
|
||||||
OsmPathElement pe = create(n.getILon(), n.getILat(), path.selev, path.originElement, countTraffic);
|
OsmPathElement pe = create(n.getILon(), n.getILat(), n.getSElev(), path.originElement, countTraffic);
|
||||||
pe.cost = path.cost;
|
pe.cost = path.cost;
|
||||||
pe.message = path.message;
|
pe.message = path.message;
|
||||||
return pe;
|
return pe;
|
||||||
|
@ -98,6 +108,10 @@ public class OsmPathElement implements OsmPos {
|
||||||
return ilon + "_" + ilat;
|
return ilon + "_" + ilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean positionEquals(OsmPathElement e) {
|
||||||
|
return this.ilat == e.ilat && this.ilon == e.ilon;
|
||||||
|
}
|
||||||
|
|
||||||
public void writeToStream(DataOutput dos) throws IOException {
|
public void writeToStream(DataOutput dos) throws IOException {
|
||||||
dos.writeInt(ilat);
|
dos.writeInt(ilat);
|
||||||
dos.writeInt(ilon);
|
dos.writeInt(ilon);
|
||||||
|
|
|
@ -94,6 +94,64 @@ public final class OsmTrack {
|
||||||
detourMap = source.detourMap == null ? null : new FrozenLongMap<OsmPathElementHolder>(source.detourMap);
|
detourMap = source.detourMap == null ? null : new FrozenLongMap<OsmPathElementHolder>(source.detourMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDetours(OsmTrack source) {
|
||||||
|
if (detourMap != null) {
|
||||||
|
CompactLongMap<OsmPathElementHolder> tmpDetourMap = new CompactLongMap<OsmPathElementHolder>();
|
||||||
|
|
||||||
|
List oldlist = ((FrozenLongMap) detourMap).getValueList();
|
||||||
|
long[] oldidlist = ((FrozenLongMap) detourMap).getKeyArray();
|
||||||
|
for (int i = 0; i < oldidlist.length; i++) {
|
||||||
|
long id = oldidlist[i];
|
||||||
|
OsmPathElementHolder v = detourMap.get(id);
|
||||||
|
|
||||||
|
tmpDetourMap.put(id, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.detourMap != null) {
|
||||||
|
long[] idlist = ((FrozenLongMap) source.detourMap).getKeyArray();
|
||||||
|
for (int i = 0; i < idlist.length; i++) {
|
||||||
|
long id = idlist[i];
|
||||||
|
OsmPathElementHolder v = source.detourMap.get(id);
|
||||||
|
if (!tmpDetourMap.contains(id) && source.nodesMap.contains(id)) {
|
||||||
|
tmpDetourMap.put(id, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detourMap = new FrozenLongMap<OsmPathElementHolder>(tmpDetourMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OsmPathElement lastorigin = null;
|
||||||
|
|
||||||
|
public void appendDetours(OsmTrack source) {
|
||||||
|
if (detourMap == null) {
|
||||||
|
detourMap = source.detourMap == null ? null : new CompactLongMap<OsmPathElementHolder>();
|
||||||
|
}
|
||||||
|
if (source.detourMap != null) {
|
||||||
|
int pos = nodes.size() - source.nodes.size() + 1;
|
||||||
|
OsmPathElement origin = null;
|
||||||
|
if (pos > 0)
|
||||||
|
origin = nodes.get(pos);
|
||||||
|
for (OsmPathElement node : source.nodes) {
|
||||||
|
long id = node.getIdFromPos();
|
||||||
|
OsmPathElementHolder nh = new OsmPathElementHolder();
|
||||||
|
if (node.origin == null && lastorigin != null)
|
||||||
|
node.origin = lastorigin;
|
||||||
|
nh.node = node;
|
||||||
|
lastorigin = node;
|
||||||
|
OsmPathElementHolder h = detourMap.get(id);
|
||||||
|
if (h != null) {
|
||||||
|
while (h.nextHolder != null) {
|
||||||
|
h = h.nextHolder;
|
||||||
|
}
|
||||||
|
h.nextHolder = nh;
|
||||||
|
} else {
|
||||||
|
detourMap.fastPut(id, nh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void buildMap() {
|
public void buildMap() {
|
||||||
nodesMap = new CompactLongMap<OsmPathElementHolder>();
|
nodesMap = new CompactLongMap<OsmPathElementHolder>();
|
||||||
for (OsmPathElement node : nodes) {
|
for (OsmPathElement node : nodes) {
|
||||||
|
@ -275,10 +333,16 @@ public final class OsmTrack {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendTrack(OsmTrack t) {
|
public void appendTrack(OsmTrack t) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
int ourSize = nodes.size();
|
int ourSize = nodes.size();
|
||||||
|
if (ourSize > 0 && t.nodes.size() > 1) {
|
||||||
|
OsmPathElement olde = nodes.get(ourSize - 1);
|
||||||
|
t.nodes.get(1).origin = olde;
|
||||||
|
}
|
||||||
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;
|
||||||
for (int i = 0; i < t.nodes.size(); i++) {
|
for (i = 0; i < t.nodes.size(); i++) {
|
||||||
if (i > 0 || ourSize == 0) {
|
if (i > 0 || ourSize == 0) {
|
||||||
OsmPathElement e = t.nodes.get(i);
|
OsmPathElement e = t.nodes.get(i);
|
||||||
e.setTime(e.getTime() + t0);
|
e.setTime(e.getTime() + t0);
|
||||||
|
@ -298,13 +362,20 @@ public final class OsmTrack {
|
||||||
} else {
|
} else {
|
||||||
voiceHints.list.addAll(t.voiceHints.list);
|
voiceHints.list.addAll(t.voiceHints.list);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (detourMap == null) {
|
||||||
|
//copyDetours( t );
|
||||||
|
detourMap = t.detourMap;
|
||||||
|
} else {
|
||||||
|
addDetours(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
distance += t.distance;
|
distance += t.distance;
|
||||||
ascend += t.ascend;
|
ascend += t.ascend;
|
||||||
plainAscend += t.plainAscend;
|
plainAscend += t.plainAscend;
|
||||||
cost += t.cost;
|
cost += t.cost;
|
||||||
energy += t.energy;
|
energy = (int) nodes.get(nodes.size() - 1).getEnergy();
|
||||||
|
|
||||||
showspeed |= t.showspeed;
|
showspeed |= t.showspeed;
|
||||||
showSpeedProfile |= t.showSpeedProfile;
|
showSpeedProfile |= t.showSpeedProfile;
|
||||||
|
@ -798,6 +869,26 @@ public final class OsmTrack {
|
||||||
sb.append(" }");
|
sb.append(" }");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VoiceHint getVoiceHint(int i) {
|
||||||
|
if (voiceHints == null) return null;
|
||||||
|
for (VoiceHint hint : voiceHints.list) {
|
||||||
|
if (hint.indexInTrack == i) {
|
||||||
|
return hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MatchedWaypoint getMatchedWaypoint(int idx) {
|
||||||
|
if (matchedWaypoints == null) return null;
|
||||||
|
for (MatchedWaypoint wp : matchedWaypoints) {
|
||||||
|
if (idx == wp.indexInTrack) {
|
||||||
|
return wp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private int getVNode(int i) {
|
private int getVNode(int i) {
|
||||||
MessageData m1 = i + 1 < nodes.size() ? nodes.get(i + 1).message : null;
|
MessageData m1 = i + 1 < nodes.size() ? nodes.get(i + 1).message : null;
|
||||||
MessageData m0 = i < nodes.size() ? nodes.get(i).message : null;
|
MessageData m0 = i < nodes.size() ? nodes.get(i).message : null;
|
||||||
|
@ -947,7 +1038,17 @@ public final class OsmTrack {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int nodeNr = nodes.size() - 1;
|
int nodeNr = nodes.size() - 1;
|
||||||
|
int i = nodeNr;
|
||||||
OsmPathElement node = nodes.get(nodeNr);
|
OsmPathElement node = nodes.get(nodeNr);
|
||||||
|
while (node != null) {
|
||||||
|
if (node.origin != null) {
|
||||||
|
}
|
||||||
|
node = node.origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
node = nodes.get(nodeNr);
|
||||||
List<VoiceHint> inputs = new ArrayList<VoiceHint>();
|
List<VoiceHint> inputs = new ArrayList<VoiceHint>();
|
||||||
while (node != null) {
|
while (node != null) {
|
||||||
if (node.origin != null) {
|
if (node.origin != null) {
|
||||||
|
@ -959,15 +1060,18 @@ public final class OsmTrack {
|
||||||
input.indexInTrack = --nodeNr;
|
input.indexInTrack = --nodeNr;
|
||||||
input.goodWay = node.message;
|
input.goodWay = node.message;
|
||||||
input.oldWay = node.origin.message == null ? node.message : node.origin.message;
|
input.oldWay = node.origin.message == null ? node.message : node.origin.message;
|
||||||
|
|
||||||
OsmPathElementHolder detours = detourMap.get(node.origin.getIdFromPos());
|
OsmPathElementHolder detours = detourMap.get(node.origin.getIdFromPos());
|
||||||
if (detours != null) {
|
if (nodeNr >= 0 && detours != null) {
|
||||||
OsmPathElementHolder h = detours;
|
OsmPathElementHolder h = detours;
|
||||||
while (h != null) {
|
while (h != null) {
|
||||||
OsmPathElement e = h.node;
|
OsmPathElement e = h.node;
|
||||||
input.addBadWay(startSection(e, node.origin));
|
input.addBadWay(startSection(e, node.origin));
|
||||||
h = h.nextHolder;
|
h = h.nextHolder;
|
||||||
}
|
}
|
||||||
|
} else if (nodeNr == 0 && detours != null) {
|
||||||
|
OsmPathElementHolder h = detours;
|
||||||
|
OsmPathElement e = h.node;
|
||||||
|
input.addBadWay(startSection(e, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node = node.origin;
|
node = node.origin;
|
||||||
|
@ -975,9 +1079,27 @@ public final class OsmTrack {
|
||||||
|
|
||||||
VoiceHintProcessor vproc = new VoiceHintProcessor(rc.turnInstructionCatchingRange, rc.turnInstructionRoundabouts);
|
VoiceHintProcessor vproc = new VoiceHintProcessor(rc.turnInstructionCatchingRange, rc.turnInstructionRoundabouts);
|
||||||
List<VoiceHint> results = vproc.process(inputs);
|
List<VoiceHint> results = vproc.process(inputs);
|
||||||
|
|
||||||
for (VoiceHint hint : results) {
|
for (VoiceHint hint : results) {
|
||||||
voiceHints.list.add(hint);
|
voiceHints.list.add(hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int getMinDistance() {
|
||||||
|
if (voiceHints != null) {
|
||||||
|
switch (voiceHints.getTransportMode()) {
|
||||||
|
case "car":
|
||||||
|
return 20;
|
||||||
|
case "bike":
|
||||||
|
return 5;
|
||||||
|
case "foot":
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getVoiceHintTime(int i) {
|
private float getVoiceHintTime(int i) {
|
||||||
|
|
|
@ -8,7 +8,11 @@ import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import btools.mapaccess.MatchedWaypoint;
|
import btools.mapaccess.MatchedWaypoint;
|
||||||
import btools.mapaccess.NodesCache;
|
import btools.mapaccess.NodesCache;
|
||||||
|
@ -233,6 +237,119 @@ public class RoutingEngine extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void postElevationCheck(OsmTrack track) {
|
||||||
|
OsmPathElement lastPt = null;
|
||||||
|
OsmPathElement startPt = null;
|
||||||
|
short lastElev = Short.MIN_VALUE;
|
||||||
|
short startElev = Short.MIN_VALUE;
|
||||||
|
short endElev = Short.MIN_VALUE;
|
||||||
|
int startIdx = 0;
|
||||||
|
int endIdx = -1;
|
||||||
|
int dist = 0;
|
||||||
|
for (int idx = 0; idx < track.nodes.size(); idx++) {
|
||||||
|
OsmPathElement n = track.nodes.get(idx);
|
||||||
|
if (n.getSElev() == Short.MIN_VALUE && lastElev != Short.MIN_VALUE) {
|
||||||
|
// start one point before entry point to get better elevation results
|
||||||
|
if (idx > 1)
|
||||||
|
startElev = track.nodes.get(idx - 2).getSElev();
|
||||||
|
if (startElev == Short.MIN_VALUE)
|
||||||
|
startElev = lastElev;
|
||||||
|
startIdx = idx;
|
||||||
|
startPt = lastPt;
|
||||||
|
dist = 0;
|
||||||
|
if (lastPt != null)
|
||||||
|
dist += n.calcDistance(lastPt);
|
||||||
|
} else if (n.getSElev() != Short.MIN_VALUE && lastElev == Short.MIN_VALUE && startElev != Short.MIN_VALUE) {
|
||||||
|
// end one point behind exit point to get better elevation results
|
||||||
|
if (idx + 1 < track.nodes.size())
|
||||||
|
endElev = track.nodes.get(idx + 1).getSElev();
|
||||||
|
if (endElev == Short.MIN_VALUE)
|
||||||
|
endElev = n.getSElev();
|
||||||
|
endIdx = idx;
|
||||||
|
OsmPathElement tmpPt = track.nodes.get(startIdx > 1 ? startIdx - 2 : startIdx - 1);
|
||||||
|
int diffElev = endElev - startElev;
|
||||||
|
dist += tmpPt.calcDistance(startPt);
|
||||||
|
dist += n.calcDistance(lastPt);
|
||||||
|
int distRest = dist;
|
||||||
|
double incline = diffElev / (dist / 100.);
|
||||||
|
String lastMsg = "";
|
||||||
|
double tmpincline = 0;
|
||||||
|
double startincline = 0;
|
||||||
|
double selev = track.nodes.get(startIdx - 2).getSElev();
|
||||||
|
boolean hasInclineTags = false;
|
||||||
|
for (int i = startIdx - 1; i < endIdx + 1; i++) {
|
||||||
|
OsmPathElement tmp = track.nodes.get(i);
|
||||||
|
if (tmp.message != null) {
|
||||||
|
MessageData md = tmp.message.copy();
|
||||||
|
String msg = md.wayKeyValues;
|
||||||
|
if (!msg.equals(lastMsg)) {
|
||||||
|
boolean revers = msg.contains("reversedirection=yes");
|
||||||
|
int pos = msg.indexOf("incline=");
|
||||||
|
if (pos != -1) {
|
||||||
|
hasInclineTags = true;
|
||||||
|
String s = msg.substring(pos + 8);
|
||||||
|
pos = s.indexOf(" ");
|
||||||
|
if (pos != -1)
|
||||||
|
s = s.substring(0, pos);
|
||||||
|
|
||||||
|
if (s.length() > 0) {
|
||||||
|
try {
|
||||||
|
int ind = s.indexOf("%");
|
||||||
|
if (ind != -1)
|
||||||
|
s = s.substring(0, ind);
|
||||||
|
ind = s.indexOf("<EFBFBD>");
|
||||||
|
if (ind != -1)
|
||||||
|
s = s.substring(0, ind);
|
||||||
|
tmpincline = Double.parseDouble(s.trim());
|
||||||
|
if (revers)
|
||||||
|
tmpincline *= -1;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
tmpincline = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tmpincline = 0;
|
||||||
|
}
|
||||||
|
if (startincline == 0) {
|
||||||
|
startincline = tmpincline;
|
||||||
|
} else if (startincline < 0 && tmpincline > 0) {
|
||||||
|
// for the way ?p find the exit point
|
||||||
|
double diff = endElev - selev;
|
||||||
|
tmpincline = diff / (distRest / 100.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastMsg = msg;
|
||||||
|
}
|
||||||
|
int tmpdist = tmp.calcDistance(tmpPt);
|
||||||
|
distRest -= tmpdist;
|
||||||
|
if (hasInclineTags)
|
||||||
|
incline = tmpincline;
|
||||||
|
selev = (selev + (tmpdist / 100. * incline));
|
||||||
|
tmp.setSElev((short) selev);
|
||||||
|
tmp.message.ele = (short) selev;
|
||||||
|
tmpPt = tmp;
|
||||||
|
}
|
||||||
|
dist = 0;
|
||||||
|
} else if (n.getSElev() != Short.MIN_VALUE && lastElev == Short.MIN_VALUE && startIdx == 0) {
|
||||||
|
// fill at start
|
||||||
|
for (int i = 0; i < idx; i++) {
|
||||||
|
track.nodes.get(i).setSElev(n.getSElev());
|
||||||
|
}
|
||||||
|
} else if (n.getSElev() == Short.MIN_VALUE && idx == track.nodes.size() - 1) {
|
||||||
|
// fill at end
|
||||||
|
for (int i = startIdx; i < track.nodes.size(); i++) {
|
||||||
|
track.nodes.get(i).setSElev(startElev);
|
||||||
|
}
|
||||||
|
} else if (n.getSElev() == Short.MIN_VALUE) {
|
||||||
|
if (lastPt != null)
|
||||||
|
dist += n.calcDistance(lastPt);
|
||||||
|
}
|
||||||
|
lastElev = n.getSElev();
|
||||||
|
lastPt = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void logException(Throwable t) {
|
private void logException(Throwable t) {
|
||||||
errorMessage = t instanceof IllegalArgumentException ? t.getMessage() : t.toString();
|
errorMessage = t instanceof IllegalArgumentException ? t.getMessage() : t.toString();
|
||||||
logInfo("Error (linksProcessed=" + linksProcessed + " open paths: " + openSet.getSize() + "): " + errorMessage);
|
logInfo("Error (linksProcessed=" + linksProcessed + " open paths: " + openSet.getSize() + "): " + errorMessage);
|
||||||
|
@ -378,13 +495,24 @@ public class RoutingEngine extends Thread {
|
||||||
if (routingContext.correctMisplacedViaPoints && !matchedWaypoints.get(i).direct) {
|
if (routingContext.correctMisplacedViaPoints && !matchedWaypoints.get(i).direct) {
|
||||||
changed = snappPathConnection(totaltrack, seg, routingContext.inverseRouting ? matchedWaypoints.get(i + 1) : matchedWaypoints.get(i));
|
changed = snappPathConnection(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;
|
||||||
|
|
||||||
totaltrack.appendTrack(seg);
|
totaltrack.appendTrack(seg);
|
||||||
lastTracks[i] = seg;
|
lastTracks[i] = seg;
|
||||||
}
|
}
|
||||||
if (routingContext.poipoints != null) totaltrack.pois = routingContext.poipoints;
|
|
||||||
|
postElevationCheck(totaltrack);
|
||||||
|
|
||||||
|
recalcTrack(totaltrack);
|
||||||
|
|
||||||
|
matchedWaypoints.get(matchedWaypoints.size() - 1).indexInTrack = totaltrack.nodes.size() - 1;
|
||||||
|
totaltrack.matchedWaypoints = matchedWaypoints;
|
||||||
|
totaltrack.processVoiceHints(routingContext);
|
||||||
|
totaltrack.prepareSpeedProfile(routingContext);
|
||||||
|
|
||||||
|
if (routingContext.poipoints != null)
|
||||||
|
totaltrack.pois = routingContext.poipoints;
|
||||||
totaltrack.matchedWaypoints = matchedWaypoints;
|
totaltrack.matchedWaypoints = matchedWaypoints;
|
||||||
return totaltrack;
|
return totaltrack;
|
||||||
}
|
}
|
||||||
|
@ -555,6 +683,136 @@ public class RoutingEngine extends Thread {
|
||||||
newTarget.message.turnangle = (float) angle;
|
newTarget.message.turnangle = (float) angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void recalcTrack(OsmTrack t) {
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
int lon0,
|
||||||
|
lat0,
|
||||||
|
lon1,
|
||||||
|
lat1,
|
||||||
|
lon2,
|
||||||
|
lat2;
|
||||||
|
int totaldist = 0;
|
||||||
|
int totaltime = 0;
|
||||||
|
float lasttime = 0;
|
||||||
|
float lastenergy = 0;
|
||||||
|
float speed_avg = 0;
|
||||||
|
float speed_min = 9999;
|
||||||
|
Map<Integer, Integer> directMap = new HashMap<>();
|
||||||
|
float tmptime = 1;
|
||||||
|
float speed = 1;
|
||||||
|
int dist;
|
||||||
|
double angle;
|
||||||
|
|
||||||
|
double ascend = 0;
|
||||||
|
double ehb = 0.;
|
||||||
|
int ourSize = t.nodes.size();
|
||||||
|
|
||||||
|
short ele_start = Short.MIN_VALUE;
|
||||||
|
short ele_end = Short.MIN_VALUE;
|
||||||
|
double eleFactor = routingContext.inverseRouting ? 0.25 : -0.25;
|
||||||
|
|
||||||
|
for (i = 0; i < ourSize; i++) {
|
||||||
|
OsmPathElement n = t.nodes.get(i);
|
||||||
|
if (n.message == null) n.message = new MessageData();
|
||||||
|
OsmPathElement nLast = null;
|
||||||
|
if (i == 0) {
|
||||||
|
lon0 = t.nodes.get(0).getILon();
|
||||||
|
lat0 = t.nodes.get(0).getILat();
|
||||||
|
lon1 = t.nodes.get(0).getILat();
|
||||||
|
lat1 = t.nodes.get(0).getILat();
|
||||||
|
lon2 = t.nodes.get(i).getILon();
|
||||||
|
lat2 = t.nodes.get(i).getILat();
|
||||||
|
dist = 0;
|
||||||
|
} else if (i == 1) {
|
||||||
|
lon0 = t.nodes.get(0).getILon();
|
||||||
|
lat0 = t.nodes.get(0).getILat();
|
||||||
|
lon1 = t.nodes.get(1).getILon();
|
||||||
|
lat1 = t.nodes.get(1).getILat();
|
||||||
|
lon2 = t.nodes.get(i).getILon();
|
||||||
|
lat2 = t.nodes.get(i).getILat();
|
||||||
|
nLast = t.nodes.get(0);
|
||||||
|
dist = routingContext.calcDistance(lon0, lat0, lon1, lat1);
|
||||||
|
} else {
|
||||||
|
lon0 = t.nodes.get(i - 2).getILon();
|
||||||
|
lat0 = t.nodes.get(i - 2).getILat();
|
||||||
|
lon1 = t.nodes.get(i - 1).getILon();
|
||||||
|
lat1 = t.nodes.get(i - 1).getILat();
|
||||||
|
lon2 = t.nodes.get(i).getILon();
|
||||||
|
lat2 = t.nodes.get(i).getILat();
|
||||||
|
nLast = t.nodes.get(i - 1);
|
||||||
|
dist = routingContext.calcDistance(lon1, lat1, lon2, lat2);
|
||||||
|
}
|
||||||
|
angle = routingContext.anglemeter.calcAngle(lon0, lat0, lon1, lat1, lon2, lat2);
|
||||||
|
n.message.linkdist = dist;
|
||||||
|
n.message.turnangle = (float) angle;
|
||||||
|
totaldist += dist;
|
||||||
|
totaltime += n.getTime();
|
||||||
|
tmptime = (n.getTime() - lasttime);
|
||||||
|
if (dist > 0) {
|
||||||
|
speed = dist / tmptime * 3.6f;
|
||||||
|
speed_min = Math.min(speed_min, speed);
|
||||||
|
}
|
||||||
|
if (tmptime == 1.f) { // no time used here
|
||||||
|
directMap.put(i, dist);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastenergy = n.getEnergy();
|
||||||
|
lasttime = n.getTime();
|
||||||
|
|
||||||
|
short ele = n.getSElev();
|
||||||
|
if (ele != Short.MIN_VALUE)
|
||||||
|
ele_end = ele;
|
||||||
|
if (ele_start == Short.MIN_VALUE)
|
||||||
|
ele_start = ele;
|
||||||
|
|
||||||
|
if (nLast != null) {
|
||||||
|
short ele_last = nLast.getSElev();
|
||||||
|
if (ele_last != Short.MIN_VALUE) {
|
||||||
|
ehb = ehb + (ele_last - ele) * eleFactor;
|
||||||
|
}
|
||||||
|
if (ehb > 10.) {
|
||||||
|
ascend += ehb - 10.;
|
||||||
|
ehb = 10.;
|
||||||
|
} else if (ehb < 0.) {
|
||||||
|
ehb = 0.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ascend += ehb;
|
||||||
|
|
||||||
|
t.ascend = (int) ascend;
|
||||||
|
t.plainAscend = (int) ((ele_start - ele_end) * eleFactor + 0.5);
|
||||||
|
|
||||||
|
t.distance = totaldist;
|
||||||
|
//t.energy = totalenergy;
|
||||||
|
|
||||||
|
SortedSet<Integer> keys = new TreeSet<>(directMap.keySet());
|
||||||
|
for (Integer key : keys) {
|
||||||
|
int value = directMap.get(key);
|
||||||
|
float addTime = (value / (speed_min / 3.6f));
|
||||||
|
|
||||||
|
double addEnergy = 0;
|
||||||
|
if (key < ourSize - 1) {
|
||||||
|
double GRAVITY = 9.81; // in meters per second^(-2)
|
||||||
|
double incline = (t.nodes.get(key).getElev() - t.nodes.get(key + 1).getElev()) / value;
|
||||||
|
double f_roll = routingContext.totalMass * GRAVITY * (routingContext.defaultC_r + incline);
|
||||||
|
double spd = speed_min / 3.6;
|
||||||
|
addEnergy = value * (routingContext.S_C_x * spd * spd + f_roll);
|
||||||
|
}
|
||||||
|
for (int j = key; j < ourSize; j++) {
|
||||||
|
OsmPathElement n = t.nodes.get(j);
|
||||||
|
n.setTime(n.getTime() + addTime);
|
||||||
|
n.setEnergy(n.getEnergy() + (float) addEnergy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logInfo("track-length total = " + t.distance);
|
||||||
|
logInfo("filtered ascend = " + t.ascend);
|
||||||
|
}
|
||||||
|
|
||||||
// geometric position matching finding the nearest routable way-section
|
// geometric position matching finding the nearest routable way-section
|
||||||
private void matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints) {
|
private void matchWaypointsToNodes(List<MatchedWaypoint> unmatchedWaypoints) {
|
||||||
resetCache(false);
|
resetCache(false);
|
||||||
|
@ -646,6 +904,8 @@ public class RoutingEngine extends Thread {
|
||||||
}
|
}
|
||||||
if (track == null) throw new IllegalArgumentException("no track found");
|
if (track == null) throw new IllegalArgumentException("no track found");
|
||||||
|
|
||||||
|
OsmPathElement lastElement = null;
|
||||||
|
|
||||||
boolean wasClean = nearbyTrack != null && !nearbyTrack.isDirty;
|
boolean wasClean = nearbyTrack != null && !nearbyTrack.isDirty;
|
||||||
if (refTrack == null && !(wasClean && isDirty)) // do not overwrite a clean with a dirty track
|
if (refTrack == null && !(wasClean && isDirty)) // do not overwrite a clean with a dirty track
|
||||||
{
|
{
|
||||||
|
@ -1162,18 +1422,18 @@ public class RoutingEngine extends Thread {
|
||||||
track.energy = (int) path.getTotalEnergy();
|
track.energy = (int) path.getTotalEnergy();
|
||||||
|
|
||||||
int distance = 0;
|
int distance = 0;
|
||||||
double ascend = 0;
|
|
||||||
double ehb = 0.;
|
|
||||||
|
|
||||||
short ele_start = Short.MIN_VALUE;
|
|
||||||
short ele_end = Short.MIN_VALUE;
|
|
||||||
|
|
||||||
double eleFactor = routingContext.inverseRouting ? -0.25 : 0.25;
|
double eleFactor = routingContext.inverseRouting ? -0.25 : 0.25;
|
||||||
while (element != null) {
|
while (element != null) {
|
||||||
if (guideTrack != null && element.message == null) {
|
if (guideTrack != null && element.message == null) {
|
||||||
element.message = new MessageData();
|
element.message = new MessageData();
|
||||||
}
|
}
|
||||||
|
OsmPathElement nextElement = element.origin;
|
||||||
|
// ignore double element
|
||||||
|
if (nextElement != null && nextElement.positionEquals(element)) {
|
||||||
|
element = nextElement;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (routingContext.inverseRouting) {
|
if (routingContext.inverseRouting) {
|
||||||
element.setTime(totalTime - element.getTime());
|
element.setTime(totalTime - element.getTime());
|
||||||
element.setEnergy(totalEnergy - element.getEnergy());
|
element.setEnergy(totalEnergy - element.getEnergy());
|
||||||
|
@ -1182,40 +1442,18 @@ public class RoutingEngine extends Thread {
|
||||||
track.nodes.add(0, element);
|
track.nodes.add(0, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
OsmPathElement nextElement = element.origin;
|
|
||||||
|
|
||||||
short ele = element.getSElev();
|
|
||||||
if (ele != Short.MIN_VALUE) ele_start = ele;
|
|
||||||
if (ele_end == Short.MIN_VALUE) ele_end = ele;
|
|
||||||
|
|
||||||
if (nextElement != null) {
|
if (nextElement != null) {
|
||||||
distance += element.calcDistance(nextElement);
|
distance += element.calcDistance(nextElement);
|
||||||
short ele_next = nextElement.getSElev();
|
|
||||||
if (ele_next != Short.MIN_VALUE) {
|
|
||||||
ehb = ehb + (ele - ele_next) * eleFactor;
|
|
||||||
}
|
|
||||||
if (ehb > 10.) {
|
|
||||||
ascend += ehb - 10.;
|
|
||||||
ehb = 10.;
|
|
||||||
} else if (ehb < 0.) {
|
|
||||||
ehb = 0.;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
element = nextElement;
|
element = nextElement;
|
||||||
}
|
}
|
||||||
ascend += ehb;
|
|
||||||
track.distance = distance;
|
track.distance = distance;
|
||||||
track.ascend = (int) ascend;
|
|
||||||
track.plainAscend = (int) ((ele_end - ele_start) * eleFactor + 0.5);
|
|
||||||
logInfo("track-length = " + track.distance);
|
logInfo("track-length = " + track.distance);
|
||||||
logInfo("filtered ascend = " + track.ascend);
|
|
||||||
track.buildMap();
|
track.buildMap();
|
||||||
|
|
||||||
// for final track..
|
// for final track..
|
||||||
if (guideTrack != null) {
|
if (guideTrack != null) {
|
||||||
track.copyDetours(guideTrack);
|
track.copyDetours(guideTrack);
|
||||||
track.processVoiceHints(routingContext);
|
|
||||||
track.prepareSpeedProfile(routingContext);
|
|
||||||
}
|
}
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ package btools.mapaccess;
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public final class MatchedWaypoint {
|
public final class MatchedWaypoint {
|
||||||
public OsmNode node1;
|
public OsmNode node1;
|
||||||
|
@ -17,7 +19,11 @@ public final class MatchedWaypoint {
|
||||||
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
|
||||||
|
public int indexInTrack = 0;
|
||||||
|
public double directionToNext = -1;
|
||||||
|
public double directionDiff = 361;
|
||||||
|
|
||||||
|
public List<MatchedWaypoint> wayNearest = new ArrayList<>();
|
||||||
public boolean hasUpdate;
|
public boolean hasUpdate;
|
||||||
|
|
||||||
public void writeToStream(DataOutput dos) throws IOException {
|
public void writeToStream(DataOutput dos) throws IOException {
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class RouteServerTest {
|
||||||
|
|
||||||
InputStream inputStream = httpConnection.getInputStream();
|
InputStream inputStream = httpConnection.getInputStream();
|
||||||
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
||||||
Assert.assertEquals("1204", geoJson.query("/features/0/properties/track-length"));
|
Assert.assertEquals("1169", geoJson.query("/features/0/properties/track-length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -89,7 +89,7 @@ public class RouteServerTest {
|
||||||
|
|
||||||
InputStream inputStream = httpConnection.getInputStream();
|
InputStream inputStream = httpConnection.getInputStream();
|
||||||
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
||||||
Assert.assertEquals("1902", geoJson.query("/features/0/properties/track-length"));
|
Assert.assertEquals("1866", geoJson.query("/features/0/properties/track-length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -115,7 +115,7 @@ public class RouteServerTest {
|
||||||
|
|
||||||
InputStream inputStream = httpConnection.getInputStream();
|
InputStream inputStream = httpConnection.getInputStream();
|
||||||
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
||||||
Assert.assertEquals("521", geoJson.query("/features/0/properties/track-length"));
|
Assert.assertEquals("505", geoJson.query("/features/0/properties/track-length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -128,7 +128,7 @@ public class RouteServerTest {
|
||||||
|
|
||||||
InputStream inputStream = httpConnection.getInputStream();
|
InputStream inputStream = httpConnection.getInputStream();
|
||||||
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
||||||
Assert.assertEquals("520", geoJson.query("/features/0/properties/track-length"));
|
Assert.assertEquals("506", geoJson.query("/features/0/properties/track-length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -141,7 +141,7 @@ public class RouteServerTest {
|
||||||
|
|
||||||
InputStream inputStream = httpConnection.getInputStream();
|
InputStream inputStream = httpConnection.getInputStream();
|
||||||
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
||||||
Assert.assertEquals("350", geoJson.query("/features/0/properties/track-length"));
|
Assert.assertEquals("347", geoJson.query("/features/0/properties/track-length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -154,7 +154,7 @@ public class RouteServerTest {
|
||||||
|
|
||||||
InputStream inputStream = httpConnection.getInputStream();
|
InputStream inputStream = httpConnection.getInputStream();
|
||||||
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
JSONObject geoJson = new JSONObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
|
||||||
Assert.assertEquals("598", geoJson.query("/features/0/properties/track-length"));
|
Assert.assertEquals("546", geoJson.query("/features/0/properties/track-length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in a new issue