Fix gpx to route fixes
This commit is contained in:
parent
0e9148ce5b
commit
95087d3b88
8 changed files with 225 additions and 239 deletions
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue