Fix gpx to route fixes

This commit is contained in:
max-klaus 2020-03-17 18:38:56 +03:00
parent 0e9148ce5b
commit 95087d3b88
8 changed files with 225 additions and 239 deletions

View file

@ -12,6 +12,7 @@ import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@ -99,7 +100,7 @@ public class GPXUtilities {
}
public interface GPXExtensionsReader {
public void readExtensions(GPXFile res, XmlPullParser parser) throws Exception;
public boolean readExtensions(GPXFile res, XmlPullParser parser) throws Exception;
}
public static class GPXExtensions {
@ -1803,11 +1804,23 @@ public class GPXUtilities {
}
public static GPXFile loadGPXFile(InputStream f) {
return loadGPXFile(f, null);
return loadGPXFile(f, null, null);
}
public static GPXFile loadGPXFile(InputStream f, GPXExtensionsReader extensionsReader) {
GPXFile res = new GPXFile(null);
public static GPXFile loadGPXFile(InputStream f, GPXFile gpxFile, GPXExtensionsReader extensionsReader) {
boolean readExtensionsOnly = false;
if (gpxFile == null) {
gpxFile = new GPXFile(null);
} else {
if (f == null) {
try {
f = new FileInputStream(new File(gpxFile.path));
} catch (FileNotFoundException e) {
return gpxFile;
}
}
readExtensionsOnly = extensionsReader != null;
}
SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT, Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat formatMillis = new SimpleDateFormat(GPX_TIME_FORMAT_MILLIS, Locale.US);
@ -1821,45 +1834,45 @@ public class GPXUtilities {
Stack<GPXExtensions> parserState = new Stack<>();
boolean extensionReadMode = false;
boolean routePointExtension = false;
parserState.push(res);
parserState.push(gpxFile);
int tok;
while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (tok == XmlPullParser.START_TAG) {
GPXExtensions parse = parserState.peek();
String tag = parser.getName();
if (extensionReadMode && parse != null && !routePointExtension) {
switch (tag.toLowerCase()) {
case "routepointextension":
routePointExtension = true;
if (parse instanceof WptPt) {
parse.getExtensionsToWrite().put("offset", routeTrackSegment.points.size() + "");
}
break;
String tagName = tag.toLowerCase();
boolean extensionsRead = false;
if (extensionsReader != null) {
extensionsRead = extensionsReader.readExtensions(gpxFile, parser);
}
if (!readExtensionsOnly && !extensionsRead) {
switch (tagName) {
case "routepointextension":
routePointExtension = true;
if (parse instanceof WptPt) {
parse.getExtensionsToWrite().put("offset", routeTrackSegment.points.size() + "");
}
break;
case "route":
case "types":
if (extensionsReader != null) {
extensionsReader.readExtensions(res, parser);
}
break;
default:
Map<String, String> values = readTextMap(parser, tag);
if (values.size() > 0) {
for (Entry<String, String> entry : values.entrySet()) {
String t = entry.getKey().toLowerCase();
String value = entry.getValue();
parse.getExtensionsToWrite().put(t, value);
if (tag.equals("speed") && parse instanceof WptPt) {
try {
((WptPt) parse).speed = Float.parseFloat(value);
} catch (NumberFormatException e) {
log.debug(e.getMessage(), e);
default:
Map<String, String> values = readTextMap(parser, tag);
if (values.size() > 0) {
for (Entry<String, String> entry : values.entrySet()) {
String t = entry.getKey().toLowerCase();
String value = entry.getValue();
parse.getExtensionsToWrite().put(t, value);
if (tag.equals("speed") && parse instanceof WptPt) {
try {
((WptPt) parse).speed = Float.parseFloat(value);
} catch (NumberFormatException e) {
log.debug(e.getMessage(), e);
}
}
}
}
}
break;
break;
}
}
} else if (parse != null && tag.equals("extensions")) {
extensionReadMode = true;
@ -1869,7 +1882,7 @@ public class GPXUtilities {
routeTrackSegment.points.add(wptPt);
parserState.push(wptPt);
}
} else {
} else if (!readExtensionsOnly) {
if (parse instanceof GPXFile) {
if (tag.equals("gpx")) {
((GPXFile) parse).author = parser.getAttributeValue("", "creator");
@ -2056,6 +2069,9 @@ public class GPXUtilities {
if (parse != null && tag.equals("extensions")) {
extensionReadMode = false;
}
if (readExtensionsOnly) {
continue;
}
if (tag.equals("metadata")) {
Object pop = parserState.pop();
@ -2097,13 +2113,13 @@ public class GPXUtilities {
}
}
if (!routeTrackSegment.points.isEmpty()) {
res.tracks.add(routeTrack);
gpxFile.tracks.add(routeTrack);
}
} catch (Exception e) {
res.error = e;
gpxFile.error = e;
log.error("Error reading gpx", e); //$NON-NLS-1$
}
return res;
return gpxFile;
}
private static Reader getUTF8Reader(InputStream f) throws IOException {

View file

@ -82,25 +82,25 @@ public class StringBundle {
super(name, ItemType.STRING, String.valueOf(value));
}
private StringItem(String name, float value, int digits) {
super(name, ItemType.STRING, getFormattedValue(value, digits));
private StringItem(String name, float value, int maxDigits) {
super(name, ItemType.STRING, getFormattedValue(value, maxDigits));
}
private StringItem(String name, boolean value) {
super(name, ItemType.STRING, String.valueOf(value));
}
private static String getFormattedValue(float value, int digits) {
private static String getFormattedValue(float value, int maxDigits) {
DecimalFormat formatter = null;
if (digits == 2) {
if (maxDigits == 2) {
formatter = TWO_DIGITS_FORMATTER;
} else if (digits == 3) {
} else if (maxDigits == 3) {
formatter = THREE_DIGITS_FORMATTER;
} else if (digits == 4) {
} else if (maxDigits == 4) {
formatter = FOUR_DIGITS_FORMATTER;
} else if (digits == 5) {
} else if (maxDigits == 5) {
formatter = FIVE_DIGITS_FORMATTER;
} else if (digits == 6) {
} else if (maxDigits == 6) {
formatter = SIX_DIGITS_FORMATTER;
}
return formatter != null ? formatter.format(value) : String.valueOf(value);
@ -206,8 +206,8 @@ public class StringBundle {
map.put(key, new StringItem(key, value));
}
public void putFloat(String key, float value, int digits) {
map.put(key, new StringItem(key, value, digits));
public void putFloat(String key, float value, int maxDigits) {
map.put(key, new StringItem(key, value, maxDigits));
}
public float getFloat(String key, float defaultValue) {

View file

@ -11,6 +11,7 @@ import java.util.Map;
public class RouteDataResources {
private Map<RouteTypeRule, Integer> rules = new LinkedHashMap<>();
private Map<RouteSegmentResult, Map<RouteTypeRule, RouteTypeRule>> segmentRules = new LinkedHashMap<>();
private List<Location> locations;
private int currentLocation;
@ -27,6 +28,15 @@ public class RouteDataResources {
return rules;
}
public Map<RouteTypeRule, RouteTypeRule> getSegmentRules(RouteSegmentResult segmentResult) {
Map<RouteTypeRule, RouteTypeRule> ruleMap = segmentRules.get(segmentResult);
if (ruleMap == null) {
ruleMap = new LinkedHashMap<>();
segmentRules.put(segmentResult, ruleMap);
}
return ruleMap;
}
public List<Location> getLocations() {
return locations;
}

View file

@ -1,6 +1,5 @@
package net.osmand.router;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXExtensionsWriter;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.Track;
@ -15,29 +14,27 @@ import net.osmand.binary.StringBundleXmlWriter;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class RouteExporter {
private static final String OSMAND_ROUTER = "OsmAndRouter";
public static final String OSMAND_ROUTER_V2 = "OsmAndRouterV2";
private File file;
private String name;
private List<RouteSegmentResult> route;
private List<Location> locations;
private List<WptPt> points;
public RouteExporter(File file, List<RouteSegmentResult> route, List<Location> locations) {
this.file = file;
public RouteExporter(String name, List<RouteSegmentResult> route, List<Location> locations, List<WptPt> points) {
this.name = name;
this.route = route;
this.locations = locations;
this.points = points;
}
public Exception exportRoute() {
public GPXFile exportRoute() {
RouteDataResources resources = new RouteDataResources(locations);
final RouteDataBundle bundle = new RouteDataBundle(resources);
@ -66,12 +63,17 @@ public class RouteExporter {
bundle.putBundleList("types", "type", typeList);
GPXFile gpx = new GPXFile("OsmAnd");
gpx.author = OSMAND_ROUTER;
gpx.author = OSMAND_ROUTER_V2;
Track track = new Track();
track.name = new SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(new Date());
track.name = name;
gpx.tracks.add(track);
TrkSegment trkSegment = new TrkSegment();
track.segments.add(trkSegment);
if (locations == null || locations.isEmpty()) {
return gpx;
}
for (int i = 0; i < locations.size(); i++) {
Location loc = locations.get(i);
WptPt pt = new WptPt();
@ -89,6 +91,12 @@ public class RouteExporter {
trkSegment.points.add(pt);
}
if (points != null) {
for (WptPt pt : points) {
gpx.addPoint(pt);
}
}
GPXExtensionsWriter extensionsWriter = new GPXExtensionsWriter() {
@Override
public void writeExtensions(XmlSerializer serializer) {
@ -98,6 +106,6 @@ public class RouteExporter {
};
gpx.setExtensionsWriter(extensionsWriter);
return GPXUtilities.writeGpxFile(file, gpx);
return gpx;
}
}

View file

@ -27,11 +27,16 @@ public class RouteImporter {
public final static Log log = PlatformUtil.getLog(RouteImporter.class);
private File file;
private GPXFile gpxFile;
public RouteImporter(File file) {
this.file = file;
}
public RouteImporter(GPXFile gpxFile) {
this.gpxFile = gpxFile;
}
public List<RouteSegmentResult> importRoute() {
final List<RouteSegmentResult> route = new ArrayList<>();
@ -40,7 +45,7 @@ public class RouteImporter {
GPXExtensionsReader extensionsReader = new GPXExtensionsReader() {
@Override
public void readExtensions(GPXFile res, XmlPullParser parser) throws Exception {
public boolean readExtensions(GPXFile res, XmlPullParser parser) throws Exception {
if (!resources.hasLocations()) {
List<Location> locations = resources.getLocations();
if (res.tracks.size() > 0 && res.tracks.get(0).segments.size() > 0 && res.tracks.get(0).segments.get(0).points.size() > 0) {
@ -66,7 +71,7 @@ public class RouteImporter {
} else if (tok == XmlPullParser.END_TAG) {
tag = parser.getName();
if ("route".equals(tag)) {
return;
return true;
}
}
}
@ -87,33 +92,41 @@ public class RouteImporter {
} else if (tok == XmlPullParser.END_TAG) {
tag = parser.getName();
if ("types".equals(tag)) {
return;
return true;
}
}
}
}
return false;
}
};
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
GPXFile gpxFile = GPXUtilities.loadGPXFile(fis, extensionsReader);
if (gpxFile != null) {
GPXUtilities.loadGPXFile(null, gpxFile, extensionsReader);
for (RouteSegmentResult segment : route) {
segment.fillData();
}
gpxFile.path = file.getAbsolutePath();
gpxFile.modifiedTime = file.lastModified();
} catch (IOException e) {
log.error("Error importing route " + file.getAbsolutePath(), e);
return null;
} finally {
} else if (file != null) {
FileInputStream fis = null;
try {
if (fis != null) {
fis.close();
fis = new FileInputStream(file);
GPXFile gpxFile = GPXUtilities.loadGPXFile(fis, null, extensionsReader);
for (RouteSegmentResult segment : route) {
segment.fillData();
}
gpxFile.path = file.getAbsolutePath();
gpxFile.modifiedTime = file.lastModified();
} catch (IOException e) {
log.error("Error importing route " + file.getAbsolutePath(), e);
return null;
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException ignore) {
// ignore
}
} catch (IOException ignore) {
// ignore
}
}

View file

@ -12,6 +12,7 @@ import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -46,13 +47,15 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
void collectTypes(RouteDataResources resources) {
Map<RouteTypeRule, Integer> rules = resources.getRules();
Map<RouteTypeRule, RouteTypeRule> segmentRules = resources.getSegmentRules(this);
if (object.types != null) {
collectRules(rules, object.types);
collectRules(rules, segmentRules, object.types);
}
if (object.pointTypes != null) {
for (int[] types : object.pointTypes) {
for (int i = startPointIndex; i <= endPointIndex; i++) {
int[] types = object.pointTypes[i];
if (types != null) {
collectRules(rules, types);
collectRules(rules, segmentRules, types);
}
}
}
@ -85,17 +88,32 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
}
}
private void collectRules(Map<RouteTypeRule, Integer> rules, int[] types) {
private void collectRules(Map<RouteTypeRule, Integer> rules, Map<RouteTypeRule, RouteTypeRule> segmentRules, int[] types) {
RouteRegion region = object.region;
for (int type : types) {
RouteTypeRule rule = region.quickGetEncodingRule(type);
if (!rules.containsKey(rule)) {
RouteTypeRule segmentRule = null;
String tag = rule.getTag();
if (tag.equals("osmand_ele_start")) {
if (object.heightDistanceArray != null && object.heightDistanceArray.length > startPointIndex * 2) {
float h = object.heightDistanceArray[startPointIndex * 2 + 1];
segmentRule = new RouteTypeRule(tag, String.valueOf(Math.round(h)));
}
} else if (tag.equals("osmand_ele_end")) {
if (object.heightDistanceArray != null && object.heightDistanceArray.length > endPointIndex * 2) {
float h = object.heightDistanceArray[endPointIndex * 2 + 1];
segmentRule = new RouteTypeRule(tag, String.valueOf(Math.round(h)));
}
}
if (segmentRule != null && !segmentRules.containsKey(rule)) {
segmentRules.put(rule, segmentRule);
} else if (!rules.containsKey(rule)) {
rules.put(rule, rules.size());
}
}
}
private int[] convertTypes(int[] types, Map<RouteTypeRule, Integer> rules) {
private int[] convertTypes(int[] types, Map<RouteTypeRule, Integer> rules, Map<RouteTypeRule, RouteTypeRule> segmentRules) {
if (types == null || types.length == 0) {
return null;
}
@ -103,16 +121,22 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
for (int i = 0; i < types.length; i++) {
int type = types[i];
RouteTypeRule rule = object.region.quickGetEncodingRule(type);
Integer ruleId = rules.get(rule);
if (ruleId == null) {
throw new IllegalArgumentException("Cannot find collected rule: " + rule.toString());
RouteTypeRule segmentRule = segmentRules.get(rule);
if (segmentRule != null) {
res[i] = rules.size();
rules.put(segmentRule, rules.size());
} else {
Integer ruleId = rules.get(rule);
if (ruleId == null) {
throw new IllegalArgumentException("Cannot find collected rule: " + rule.toString());
}
res[i] = ruleId;
}
res[i] = ruleId;
}
return res;
}
private int[][] convertTypes(int[][] types, Map<RouteTypeRule, Integer> rules) {
private int[][] convertTypes(int[][] types, Map<RouteTypeRule, Integer> rules, Map<RouteTypeRule, RouteTypeRule> segmentRules) {
if (types == null || types.length == 0) {
return null;
}
@ -120,7 +144,7 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
for (int i = 0; i < types.length; i++) {
int[] typesArr = types[i];
if (typesArr != null) {
res[i] = convertTypes(typesArr, rules);
res[i] = convertTypes(typesArr, rules, segmentRules);
}
}
return res;
@ -168,6 +192,7 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
@Override
public void writeToBundle(RouteDataBundle bundle) {
Map<RouteTypeRule, Integer> rules = bundle.getResources().getRules();
Map<RouteTypeRule, RouteTypeRule> segmentRules = bundle.getResources().getSegmentRules(this);
bundle.putInt("length", (Math.abs(endPointIndex - startPointIndex) + 1) * (endPointIndex >= startPointIndex ? 1 : -1));
bundle.putFloat("segmentTime", segmentTime, 2);
bundle.putFloat("speed", speed, 2);
@ -181,12 +206,12 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
}
int[] turnLanes = turnType.getLanes();
if (turnLanes != null && turnLanes.length > 0) {
//bundle.putArray("turnLanes", turnLanes);
bundle.putString("turnLanes", TurnType.lanesToString(turnLanes));
}
}
bundle.putArray("types", convertTypes(object.types, rules));
bundle.putArray("pointTypes", convertTypes(object.pointTypes, rules));
bundle.putLong("id", object.id);
bundle.putArray("types", convertTypes(object.types, rules, segmentRules));
bundle.putArray("pointTypes", convertTypes(Arrays.copyOfRange(object.pointTypes, startPointIndex, endPointIndex + 1), rules, segmentRules));
bundle.putArray("names", convertNameIds(object.nameIds, rules));
}
@ -204,10 +229,10 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
turnType = TurnType.fromString(turnTypeStr, false);
turnType.setSkipToSpeak(bundle.getBoolean("skipTurn", turnType.isSkipToSpeak()));
turnType.setTurnAngle(bundle.getFloat("turnAngle", turnType.getTurnAngle()));
//int[] turnLanes = bundle.getIntArray("turnLanes", null);
int[] turnLanes = TurnType.lanesFromString(bundle.getString("turnLanes", null));
turnType.setLanes(turnLanes);
}
object.id = bundle.getLong("id", object.id);
object.types = bundle.getIntArray("types", null);
object.pointTypes = bundle.getIntIntArray("pointTypes", null);
object.nameIds = bundle.getIntArray("names", null);

View file

@ -177,10 +177,6 @@ public class RouteCalculationResult {
this.routeRecalcDistance = ctx.getSettings().ROUTE_RECALCULATION_DISTANCE.getModeValue(mode);
this.routeVisibleAngle = routeService == RouteProvider.RouteService.STRAIGHT ?
ctx.getSettings().ROUTE_STRAIGHT_ANGLE.getModeValue(mode) : 0;
RouteExporter exporter = new RouteExporter(new File(ctx.getAppPath(IndexConstants.GPX_INDEX_DIR), "test.gpx"), list, locations);
//exporter.exportRoute();
}
public ApplicationMode getAppMode() {
@ -285,12 +281,16 @@ public class RouteCalculationResult {
}
public List<RouteSegmentResult> getOriginalRoute() {
return getOriginalRoute(0);
}
public List<RouteSegmentResult> getOriginalRoute(int startIndex) {
if (segments.size() == 0) {
return null;
}
List<RouteSegmentResult> list = new ArrayList<RouteSegmentResult>();
list.add(segments.get(0));
for (int i = 1; i < segments.size(); i++) {
list.add(segments.get(startIndex++));
for (int i = startIndex; i < segments.size(); i++) {
if (segments.get(i - 1) != segments.get(i)) {
list.add(segments.get(i));
}

View file

@ -32,6 +32,7 @@ import net.osmand.router.GeneralRouter;
import net.osmand.router.GeneralRouter.RoutingParameter;
import net.osmand.router.GeneralRouter.RoutingParameterType;
import net.osmand.router.PrecalculatedRouteDirection;
import net.osmand.router.RouteExporter;
import net.osmand.router.RouteImporter;
import net.osmand.router.RoutePlannerFrontEnd;
import net.osmand.router.RoutePlannerFrontEnd.RouteCalculationMode;
@ -50,7 +51,6 @@ import org.xml.sax.SAXException;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@ -72,6 +72,8 @@ import javax.xml.parsers.ParserConfigurationException;
import btools.routingapp.IBRouterService;
import static net.osmand.router.RouteExporter.OSMAND_ROUTER_V2;
public class RouteProvider {
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RouteProvider.class);
@ -174,7 +176,6 @@ public class RouteProvider {
public GPXRouteParams build(Location start, OsmandSettings settings) {
GPXRouteParams res = new GPXRouteParams();
res.prepareGPXFile(this);
res.file = file;
// if (passWholeRoute && start != null) {
// res.points.add(0, start);
// }
@ -199,12 +200,12 @@ public class RouteProvider {
public static class GPXRouteParams {
List<Location> points = new ArrayList<Location>();
List<RouteDirectionInfo> directions;
List<RouteSegmentResult> route;
boolean calculateOsmAndRoute;
boolean passWholeRoute;
boolean calculateOsmAndRouteParts;
boolean useIntermediatePointsRTE;
private List<LocationPoint> wpt;
private GPXFile file;
boolean addMissingTurns = true;
@ -248,8 +249,11 @@ public class RouteProvider {
wpt.add(new WptLocationPoint(w));
}
}
if (file.isCloudmadeRouteFile() || OSMAND_ROUTER.equals(file.author)) {
directions = parseOsmAndGPXRoute(points, file, OSMAND_ROUTER.equals(file.author), builder.leftSide, 10);
if (OSMAND_ROUTER_V2.equals(file.author)) {
route = parseOsmAndGPXRoute(points, file);
addMissingTurns = reverse;
} else if (file.isCloudmadeRouteFile() || OSMAND_ROUTER.equals(file.author)) {
directions = parseOsmAndGPXRoute(points, file, OSMAND_ROUTER.equals(file.author), builder.leftSide, 10);
if (OSMAND_ROUTER.equals(file.author)) {
// For files generated by OSMAND_ROUTER use directions contained unaltered
addMissingTurns = false;
@ -362,14 +366,12 @@ public class RouteProvider {
private RouteCalculationResult calculateGpxRoute(RouteCalculationParams routeParams) throws IOException {
RouteImporter routeImporter = new RouteImporter(new File(routeParams.gpxRoute.file.path));
List<RouteSegmentResult> route = routeImporter.importRoute();
List<RouteSegmentResult> route = routeParams.gpxRoute.route;
if (!Algorithms.isEmpty(route)) {
return new RouteCalculationResult(route, routeParams.start, routeParams.end,
routeParams.intermediates, routeParams.ctx, routeParams.leftSide, null, null, routeParams.mode);
}
RouteCalculationResult res = new RouteCalculationResult(route, routeParams.start, routeParams.end,
routeParams.intermediates, routeParams.ctx, routeParams.leftSide, null, null, routeParams.mode);
return res;
/*
// get the closest point to start and to end
GPXRouteParams gpxParams = routeParams.gpxRoute;
if(routeParams.gpxRoute.useIntermediatePointsRTE){
@ -417,10 +419,9 @@ public class RouteProvider {
info.distance = 0;
info.afterLeftTime = 0;
}
RouteCalculationResult res = new RouteCalculationResult(gpxRoute, gpxDirections, routeParams,
gpxParams == null? null: gpxParams.wpt, routeParams.gpxRoute.addMissingTurns);
return res;
*/
return new RouteCalculationResult(gpxRoute, gpxDirections, routeParams,
gpxParams.wpt, routeParams.gpxRoute.addMissingTurns);
}
private RouteCalculationResult calculateOsmAndRouteWithIntermediatePoints(RouteCalculationParams routeParams,
@ -841,25 +842,37 @@ public class RouteProvider {
return new RouteCalculationResult("Empty result");
}
private static List<RouteDirectionInfo> parseOsmAndGPXRoute(List<Location> res, GPXFile gpxFile, boolean osmandRouter,
private static List<RouteSegmentResult> parseOsmAndGPXRoute(List<Location> points, GPXFile gpxFile) {
for (Track tr : gpxFile.tracks) {
for (TrkSegment ts : tr.segments) {
for (WptPt p : ts.points) {
points.add(createLocation(p));
}
}
}
RouteImporter routeImporter = new RouteImporter(gpxFile);
return routeImporter.importRoute();
}
private static List<RouteDirectionInfo> parseOsmAndGPXRoute(List<Location> points, GPXFile gpxFile, boolean osmandRouter,
boolean leftSide, float defSpeed) {
List<RouteDirectionInfo> directions = null;
if (!osmandRouter) {
for (WptPt pt : gpxFile.getPoints()) {
res.add(createLocation(pt));
points.add(createLocation(pt));
}
} else {
for (Track tr : gpxFile.tracks) {
for (TrkSegment ts : tr.segments) {
for (WptPt p : ts.points) {
res.add(createLocation(p));
points.add(createLocation(p));
}
}
}
}
float[] distanceToEnd = new float[res.size()];
for (int i = res.size() - 2; i >= 0; i--) {
distanceToEnd[i] = distanceToEnd[i + 1] + res.get(i).distanceTo(res.get(i + 1));
float[] distanceToEnd = new float[points.size()];
for (int i = points.size() - 2; i >= 0; i--) {
distanceToEnd[i] = distanceToEnd[i + 1] + points.get(i).distanceTo(points.get(i + 1));
}
Route route = null;
@ -946,12 +959,12 @@ public class RouteProvider {
!osmandRouter) {
// calculate angle
if (previous.routePointOffset > 0) {
float paz = res.get(previous.routePointOffset - 1).bearingTo(res.get(previous.routePointOffset));
float paz = points.get(previous.routePointOffset - 1).bearingTo(points.get(previous.routePointOffset));
float caz;
if (previous.getTurnType().isRoundAbout() && dirInfo.routePointOffset < res.size() - 1) {
caz = res.get(dirInfo.routePointOffset).bearingTo(res.get(dirInfo.routePointOffset + 1));
if (previous.getTurnType().isRoundAbout() && dirInfo.routePointOffset < points.size() - 1) {
caz = points.get(dirInfo.routePointOffset).bearingTo(points.get(dirInfo.routePointOffset + 1));
} else {
caz = res.get(dirInfo.routePointOffset - 1).bearingTo(res.get(dirInfo.routePointOffset));
caz = points.get(dirInfo.routePointOffset - 1).bearingTo(points.get(dirInfo.routePointOffset));
}
float angle = caz - paz;
if (angle < 0) {
@ -980,9 +993,9 @@ public class RouteProvider {
}
if (previous != null && TurnType.C != previous.getTurnType().getValue()) {
// calculate angle
if (previous.routePointOffset > 0 && previous.routePointOffset < res.size() - 1) {
float paz = res.get(previous.routePointOffset - 1).bearingTo(res.get(previous.routePointOffset));
float caz = res.get(previous.routePointOffset).bearingTo(res.get(res.size() - 1));
if (previous.routePointOffset > 0 && previous.routePointOffset < points.size() - 1) {
float paz = points.get(previous.routePointOffset - 1).bearingTo(points.get(previous.routePointOffset));
float caz = points.get(previous.routePointOffset).bearingTo(points.get(points.size() - 1));
float angle = caz - paz;
if (angle < 0) {
angle += 360;
@ -995,120 +1008,16 @@ public class RouteProvider {
return directions;
}
public GPXFile createOsmandRouterGPX(RouteCalculationResult srcRoute, OsmandApplication ctx, String name) {
public GPXFile createOsmandRouterGPX(RouteCalculationResult route, OsmandApplication ctx, String name) {
TargetPointsHelper helper = ctx.getTargetPointsHelper();
int currentRoute = srcRoute.currentRoute;
List<Location> routeNodes = srcRoute.getImmutableAllLocations();
List<RouteDirectionInfo> directionInfo = srcRoute.getImmutableAllDirections();
int currentDirectionInfo = srcRoute.currentDirectionInfo;
GPXFile gpx = new GPXFile(Version.getFullVersion(ctx));
gpx.author = OSMAND_ROUTER;
Track track = new Track();
track.name = name;
gpx.tracks.add(track);
TrkSegment trkSegment = new TrkSegment();
track.segments.add(trkSegment);
if (routeNodes == null || routeNodes.isEmpty()) {
return gpx;
}
// Save the start point to gpx file's trkpt section unless already contained
WptPt startpoint = new WptPt();
TargetPoint sc = helper.getPointToStart();
int routePointOffsetAdjusted = 0;
if (sc != null && ((float) sc.getLatitude() != (float) routeNodes.get(currentRoute).getLatitude() || (float) sc.getLongitude() != (float) routeNodes.get(currentRoute).getLongitude())){
startpoint.lat = sc.getLatitude();
startpoint.lon = sc.getLongitude();
trkSegment.points.add(startpoint);
if (directionInfo != null && !directionInfo.isEmpty()) {
for (RouteDirectionInfo i : directionInfo) {
i.routePointOffset++;
}
}
routePointOffsetAdjusted = 1;
}
for (int i = currentRoute; i< routeNodes.size(); i++) {
Location loc = routeNodes.get(i);
WptPt pt = new WptPt();
pt.lat = loc.getLatitude();
pt.lon = loc.getLongitude();
if (loc.hasSpeed()) {
pt.speed = loc.getSpeed();
}
if (loc.hasAltitude()) {
pt.ele = loc.getAltitude();
}
if (loc.hasAccuracy()) {
pt.hdop = loc.getAccuracy();
}
trkSegment.points.add(pt);
}
if (directionInfo != null && !directionInfo.isEmpty()) {
Route route = new Route();
route.name = name;
gpx.routes.add(route);
for (int i = currentDirectionInfo; i < directionInfo.size(); i++) {
RouteDirectionInfo dirInfo = directionInfo.get(i);
if (dirInfo.routePointOffset - routePointOffsetAdjusted >= currentRoute) {
if (dirInfo.getTurnType() != null && !dirInfo.getTurnType().isSkipToSpeak() &&
dirInfo.routePointOffset - routePointOffsetAdjusted < routeNodes.size()) {
Location loc = routeNodes.get(dirInfo.routePointOffset - routePointOffsetAdjusted);
WptPt pt = new WptPt();
pt.lat = loc.getLatitude();
pt.lon = loc.getLongitude();
// Collect distances and times for subsequent suppressed turns
int collectedDistance = 0;
int collectedTime = 0;
for (int j = i + 1; j < directionInfo.size(); j++) {
if (directionInfo.get(j).getTurnType() != null && directionInfo.get(j).getTurnType().isSkipToSpeak()) {
collectedDistance += directionInfo.get(j).getDistance();
collectedTime += directionInfo.get(j).getExpectedTime();
} else {
break;
}
}
pt.desc = dirInfo.getDescriptionRoute(ctx, collectedDistance + dirInfo.getDistance());
Map<String, String> extensions = pt.getExtensionsToWrite();
extensions.put("time", (collectedTime + dirInfo.getExpectedTime()) + "");
int turnType = dirInfo.getTurnType().getValue();
if (TurnType.C != turnType) {
extensions.put("turn", dirInfo.getTurnType().toXmlString());
extensions.put("turn-angle", dirInfo.getTurnType().getTurnAngle() + "");
}
int[] lanes = dirInfo.getTurnType().getLanes();
if (lanes != null && lanes.length > 0) {
extensions.put("lanes", Algorithms.arrayToString(lanes));
}
extensions.put("offset", (dirInfo.routePointOffset - currentRoute) + "");
// Issue #2894
if (dirInfo.getRef() != null && !"null".equals(dirInfo.getRef())) {
extensions.put("ref", dirInfo.getRef() + "");
}
if (dirInfo.getStreetName() != null && !"null".equals(dirInfo.getStreetName())) {
extensions.put("street-name", dirInfo.getStreetName() + "");
}
if (dirInfo.getDestinationName() != null && !"null".equals(dirInfo.getDestinationName())) {
extensions.put("dest", dirInfo.getDestinationName() + "");
}
route.points.add(pt);
}
}
}
}
List<WptPt> points = new ArrayList<>();
List<TargetPoint> ps = helper.getIntermediatePointsWithTarget();
for (int k = 0; k < ps.size(); k++) {
WptPt pt = new WptPt();
pt.lat = ps.get(k).getLatitude();
pt.lon = ps.get(k).getLongitude();
if (k < ps.size()) {
pt.name = ps.get(k).getOnlyName() +"";
pt.name = ps.get(k).getOnlyName() + "";
if (k == ps.size() - 1) {
String target = ctx.getString(R.string.destination_point, "");
if (pt.name.startsWith(target)) {
@ -1125,14 +1034,19 @@ public class RouteProvider {
}
pt.desc = pt.name;
}
gpx.addPoint(pt);
points.add(pt);
}
return gpx;
int currentRoute = route.currentRoute;
List<Location> locations = route.getRouteLocations();
List<RouteSegmentResult> originalRoute = route.getOriginalRoute(currentRoute);
RouteExporter exporter = new RouteExporter(name, originalRoute, locations, points);
return exporter.exportRoute();
}
private void appendOSRMLoc(StringBuilder uri, LatLon il) {
uri.append(";").append(String.valueOf(il.getLongitude()));
uri.append(",").append(String.valueOf(il.getLatitude()));
uri.append(";").append(il.getLongitude());
uri.append(",").append(il.getLatitude());
}
protected RouteCalculationResult findOSRMRoute(RouteCalculationParams params)