Implement new GPX reader. Fix issue with cloudmade GPX files navigation

This commit is contained in:
Victor Shcherb 2011-09-04 14:26:45 +03:00
commit 5059ae6238
12 changed files with 628 additions and 367 deletions

View file

@ -2,7 +2,7 @@
<resources>
<string name="local_index_gpx_info_show">\n\nДлинное нажатие для просмотра на карте</string>
<string name="local_index_gpx_info_speed">\nСредняя скорость : %1$s \nМаксимальная скорость : %2$s</string>
<string name="local_index_gpx_info_elevation">\nСредняя высота : %1$.0f метров\nМинимальная высота : %2$.0f метров\Максимальная высота : %3$.0f метров\nПодъем вверх : %4$.0f метров\nПодъем вниз : %5$.0f метров</string>
<string name="local_index_gpx_info_elevation">\nСредняя высота : %1$.0f метров\nМинимальная высота : %2$.0f метров\nМаксимальная высота : %3$.0f метров\nПодъем вверх : %4$.0f метров\nПодъем вниз : %5$.0f метров</string>
<string name="local_index_gpx_info">Путей : %1$d\nВсего точек : %2$d\nОтмечено точек : %3$d\nВсего расстояние : %4$s
\nНачало : %5$tD %5$tR\nОкончание : %6$tD %6$tR\n</string>
<string name="local_index_installed">Установлено</string>

View file

@ -2,17 +2,23 @@ package net.osmand;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;
import java.util.TimeZone;
import net.osmand.plus.R;
@ -28,16 +34,35 @@ import android.util.Xml;
public class GPXUtilities {
public final static Log log = LogUtil.getLog(GPXUtilities.class);
private final static String GPX_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$
private final static NumberFormat latLonFormat = new DecimalFormat("0.00#####", new DecimalFormatSymbols(Locale.US));
public static class WptPt {
public static class GPXExtensions {
Map<String, String> extensions = null;
public Map<String, String> getExtensionsToRead() {
if(extensions == null){
return Collections.emptyMap();
}
return extensions;
}
public Map<String, String> getExtensionsToWrite() {
if(extensions == null){
extensions = new LinkedHashMap<String, String>();
}
return extensions;
}
}
public static class WptPt extends GPXExtensions {
public double lat;
public double lon;
public String name = null;
public String desc = null;
// by default
public long time = 0;
public double ele = Double.NaN;
@ -45,17 +70,55 @@ public class GPXUtilities {
public double hdop = Double.NaN;
}
public static class TrkSegment {
public static class TrkSegment extends GPXExtensions {
public List<WptPt> points = new ArrayList<WptPt>();
}
public static class Track {
public static class Track extends GPXExtensions {
public String name = null;
public String desc = null;
public List<TrkSegment> segments = new ArrayList<TrkSegment>();
}
public static class GPXFile {
public static class Route extends GPXExtensions {
public String name = null;
public String desc = null;
public List<WptPt> points = new ArrayList<WptPt>();
}
public static class GPXFile extends GPXExtensions {
public String author;
public List<Track> tracks = new ArrayList<Track>();
public List<WptPt> points = new ArrayList<WptPt>();
public List<Route> routes = new ArrayList<Route>();
public String warning = null;
public boolean isCloudmadeRouteFile(){
return "cloudmade".equalsIgnoreCase(author);
}
public WptPt findPointToShow(){
for(Track t : tracks){
for(TrkSegment s : t.segments){
if(s.points.size() > 0){
return s.points.get(0);
}
}
}
for (Route s : routes) {
if (s.points.size() > 0) {
return s.points.get(0);
}
}
if (points.size() > 0) {
return points.get(0);
}
return null;
}
}
@ -70,7 +133,11 @@ public class GPXUtilities {
serializer.startDocument("UTF-8", true); //$NON-NLS-1$
serializer.startTag(null, "gpx"); //$NON-NLS-1$
serializer.attribute(null, "version", "1.1"); //$NON-NLS-1$ //$NON-NLS-2$
serializer.attribute(null, "creator", Version.APP_NAME_VERSION); //$NON-NLS-1$
if(file.author == null ){
serializer.attribute(null, "creator", Version.APP_NAME_VERSION); //$NON-NLS-1$
} else {
serializer.attribute(null, "creator", file.author); //$NON-NLS-1$
}
serializer.attribute(null, "xmlns", "http://www.topografix.com/GPX/1/1"); //$NON-NLS-1$ //$NON-NLS-2$
serializer.attribute(null, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
serializer.attribute(null, "xsi:schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd");
@ -78,31 +145,38 @@ public class GPXUtilities {
for (Track track : file.tracks) {
serializer.startTag(null, "trk"); //$NON-NLS-1$
writeNotNullText(serializer, "name", track.name);
writeNotNullText(serializer, "desc", track.desc);
for (TrkSegment segment : track.segments) {
serializer.startTag(null, "trkseg"); //$NON-NLS-1$
for (WptPt p : segment.points) {
serializer.startTag(null, "trkpt"); //$NON-NLS-1$
writeWpt(format, serializer, p);
serializer.endTag(null, "trkpt"); //$NON-NLS-1$
}
serializer.endTag(null, "trkseg"); //$NON-NLS-1$
}
writeExtensions(serializer, track);
serializer.endTag(null, "trk"); //$NON-NLS-1$
}
for (Route track : file.routes) {
serializer.startTag(null, "rte"); //$NON-NLS-1$
writeNotNullText(serializer, "name", track.name);
writeNotNullText(serializer, "desc", track.desc);
for (WptPt p : track.points) {
serializer.startTag(null, "rtept"); //$NON-NLS-1$
writeWpt(format, serializer, p);
serializer.endTag(null, "rtept"); //$NON-NLS-1$
}
writeExtensions(serializer, track);
serializer.endTag(null, "rte"); //$NON-NLS-1$
}
for (WptPt l : file.points) {
serializer.startTag(null, "wpt"); //$NON-NLS-1$
serializer.attribute(null, "lat", latLonFormat.format(l.lat)); //$NON-NLS-1$
serializer.attribute(null, "lon", latLonFormat.format(l.lon)); //$NON-NLS-1$ //$NON-NLS-2$
if (l.time != 0) {
serializer.startTag(null, "time"); //$NON-NLS-1$
serializer.text(format.format(new Date(l.time)));
serializer.endTag(null, "time"); //$NON-NLS-1$
}
serializer.startTag(null, "name"); //$NON-NLS-1$
serializer.text(l.name);
serializer.endTag(null, "name"); //$NON-NLS-1$
writeWpt(format, serializer, l);
serializer.endTag(null, "wpt"); //$NON-NLS-1$
}
@ -118,38 +192,42 @@ public class GPXUtilities {
}
return null;
}
private static void writeNotNullText(XmlSerializer serializer, String tag, String value) throws IOException {
if(value != null){
serializer.startTag(null, tag);
serializer.text(value);
serializer.endTag(null, tag);
}
}
private static void writeExtensions(XmlSerializer serializer, GPXExtensions p) throws IOException {
serializer.startTag(null, "extensions");
for(Map.Entry<String, String> s : p.getExtensionsToRead().entrySet()){
writeNotNullText(serializer, s.getKey(), s.getValue());
}
serializer.endTag(null, "extensions");
}
private static void writeWpt(SimpleDateFormat format, XmlSerializer serializer, WptPt p) throws IOException {
serializer.attribute(null, "lat", latLonFormat.format(p.lat)); //$NON-NLS-1$ //$NON-NLS-2$
serializer.attribute(null, "lon", latLonFormat.format(p.lon)); //$NON-NLS-1$ //$NON-NLS-2$
if(!Double.isNaN(p.ele)){
serializer.startTag(null, "ele"); //$NON-NLS-1$
serializer.text(p.ele + ""); //$NON-NLS-1$
serializer.endTag(null, "ele"); //$NON-NLS-1$
}
if(p.name != null){
serializer.startTag(null, "name"); //$NON-NLS-1$
serializer.text(p.name);
serializer.endTag(null, "name"); //$NON-NLS-1$
writeNotNullText(serializer, "ele", p.ele+"");
}
writeNotNullText(serializer, "name", p.name);
writeNotNullText(serializer, "desc", p.desc);
if(!Double.isNaN(p.hdop)){
serializer.startTag(null, "hdop"); //$NON-NLS-1$
serializer.text(p.hdop +"");
serializer.endTag(null, "hdop"); //$NON-NLS-1$
writeNotNullText(serializer, "hdop", p.hdop+"");
}
if(p.time != 0){
serializer.startTag(null, "time"); //$NON-NLS-1$
serializer.text(format.format(new Date(p.time)));
serializer.endTag(null, "time"); //$NON-NLS-1$
writeNotNullText(serializer, "time", format.format(new Date(p.time)));
}
if (p.speed > 0) {
serializer.startTag(null, "extensions");
serializer.startTag(null, "speed"); //$NON-NLS-1$
serializer.text(p.speed + ""); //$NON-NLS-1$
serializer.endTag(null, "speed"); //$NON-NLS-1$
serializer.endTag(null, "extensions");
p.getExtensionsToWrite().put("speed", p.speed+"");
}
writeExtensions(serializer, p);
}
@ -174,114 +252,209 @@ public class GPXUtilities {
}
}
public static GPXFileResult loadGPXFile(Context ctx, File f){
GPXFileResult res = new GPXFileResult();
private static String readText(XmlPullParser parser, String key) throws XmlPullParserException, IOException {
int tok;
String text = null;
while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) {
if(tok == XmlPullParser.END_TAG && parser.getName().equals(key)){
break;
} else if(tok == XmlPullParser.TEXT){
if(text == null){
text = parser.getText();
} else {
text += parser.getText();
}
}
}
return text;
}
public static GPXFile loadGPXFile(Context ctx, File f, boolean convertCloudmadeSource) {
try {
return loadGPXFile(ctx, new FileInputStream(f), convertCloudmadeSource);
} catch (FileNotFoundException e) {
GPXFile res = new GPXFile();
log.error("Error reading gpx", e); //$NON-NLS-1$
res.warning = ctx.getString(R.string.error_reading_gpx);
return res;
}
}
public static GPXFile loadGPXFile(Context ctx, InputStream f, boolean convertCloudmadeSource) {
GPXFile res = new GPXFile();
SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
res.cloudMadeFile = false;
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$
parser.setInput(f, "UTF-8"); //$NON-NLS-1$
Stack<Object> parserState = new Stack<Object>();
boolean extensionReadMode = false;
parserState.push(res);
int tok;
Location current = null;
String currentName = ""; //$NON-NLS-1$
while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (tok == XmlPullParser.START_TAG) {
if (parser.getName().equals("copyright")) { //$NON-NLS-1$
res.cloudMadeFile |= "cloudmade".equalsIgnoreCase(parser.getAttributeValue("", "author")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else if (parser.getName().equals("trkseg")) { //$NON-NLS-1$
res.locations.add(new ArrayList<Location>());
} else if (parser.getName().equals("wpt") || parser.getName().equals("trkpt") || //$NON-NLS-1$//$NON-NLS-2$
(!res.cloudMadeFile && parser.getName().equals("rtept"))) { //$NON-NLS-1$
// currently not distinguish different point represents all as a line
try {
currentName = ""; //$NON-NLS-1$
current = new Location("gpx_file"); //$NON-NLS-1$
current.setLatitude(Double.parseDouble(parser.getAttributeValue("", "lat"))); //$NON-NLS-1$ //$NON-NLS-2$
current.setLongitude(Double.parseDouble(parser.getAttributeValue("", "lon"))); //$NON-NLS-1$ //$NON-NLS-2$
} catch (NumberFormatException e) {
current = null;
}
} else if (current != null && parser.getName().equals("name")) { //$NON-NLS-1$
if (parser.next() == XmlPullParser.TEXT) {
currentName = parser.getText();
}
} else if (current != null && parser.getName().equals("time")) { //$NON-NLS-1$
if (parser.next() == XmlPullParser.TEXT) {
try {
current.setTime(format.parse(parser.getText()).getTime());
} catch (ParseException e) {
}
}
} else if (current != null && parser.getName().equals("hdop")) { //$NON-NLS-1$
if (parser.next() == XmlPullParser.TEXT) {
try {
current.setAccuracy(Float.parseFloat(parser.getText()));
} catch (NumberFormatException e) {
}
}
} else if (current != null && parser.getName().equals("ele")) { //$NON-NLS-1$
if (parser.next() == XmlPullParser.TEXT) {
try {
current.setAltitude(Double.parseDouble(parser.getText()));
} catch (NumberFormatException e) {
}
}
} else if (current != null && parser.getName().equals("speed")) { //$NON-NLS-1$
if (parser.next() == XmlPullParser.TEXT) {
try {
current.setSpeed(Float.parseFloat(parser.getText()));
} catch (NumberFormatException e) {
}
}
}
} else if (tok == XmlPullParser.END_TAG) {
if (parser.getName().equals("wpt") || //$NON-NLS-1$
parser.getName().equals("trkpt") || (!res.cloudMadeFile && parser.getName().equals("rtept"))) { //$NON-NLS-1$ //$NON-NLS-2$
if (current != null) {
if (parser.getName().equals("wpt") && !res.cloudMadeFile) { //$NON-NLS-1$
res.wayPoints.add(convertLocationToWayPoint(current, currentName));
} else {
if (res.locations.isEmpty()) {
res.locations.add(new ArrayList<Location>());
Object parse = parserState.peek();
String tag = parser.getName();
if (extensionReadMode && parse instanceof GPXExtensions) {
String value = readText(parser, tag);
if (value != null) {
((GPXExtensions) parse).getExtensionsToWrite().put(tag, value);
if (tag.equals("speed") && parse instanceof WptPt) {
try {
((WptPt) parse).speed = Float.parseFloat(value);
} catch (NumberFormatException e) {
}
}
}
} else if (parse instanceof GPXExtensions && tag.equals("extensions")) {
extensionReadMode = true;
} else {
if (parse instanceof GPXFile) {
if (parser.getName().equals("gpx")) {
((GPXFile) parse).author = parser.getAttributeValue("", "creator");
}
if (parser.getName().equals("trk")) {
Track track = new Track();
((GPXFile) parse).tracks.add(track);
parserState.push(track);
}
if (parser.getName().equals("rte")) {
Route route = new Route();
((GPXFile) parse).routes.add(route);
parserState.push(route);
}
if (parser.getName().equals("wpt")) {
WptPt wptPt = parseWptAttributes(parser);
((GPXFile) parse).points.add(wptPt);
parserState.push(wptPt);
}
} else if (parse instanceof Route) {
if (parser.getName().equals("name")) {
((Route) parse).name = readText(parser, "name");
}
if (parser.getName().equals("desc")) {
((Route) parse).desc = readText(parser, "desc");
}
if (parser.getName().equals("rtept")) {
WptPt wptPt = parseWptAttributes(parser);
((Route) parse).points.add(wptPt);
parserState.push(wptPt);
}
} else if (parse instanceof Track) {
if (parser.getName().equals("name")) {
((Track) parse).name = readText(parser, "name");
}
if (parser.getName().equals("desc")) {
((Track) parse).desc = readText(parser, "desc");
}
if (parser.getName().equals("trkseg")) {
TrkSegment trkSeg = new TrkSegment();
((Track) parse).segments.add(trkSeg);
parserState.push(trkSeg);
}
} else if (parse instanceof TrkSegment) {
if (parser.getName().equals("trkpt")) {
WptPt wptPt = parseWptAttributes(parser);
((TrkSegment) parse).points.add(wptPt);
parserState.push(wptPt);
}
// main object to parse
} else if (parse instanceof WptPt) {
if (parser.getName().equals("name")) {
((WptPt) parse).name = readText(parser, "name");
} else if (parser.getName().equals("desc")) {
((WptPt) parse).desc = readText(parser, "desc");
} else if (parser.getName().equals("ele")) {
String text = readText(parser, "ele");
if (text != null) {
try {
((WptPt) parse).ele = Float.parseFloat(text);
} catch (NumberFormatException e) {
}
}
} else if (parser.getName().equals("hdop")) {
String text = readText(parser, "hdop");
if (text != null) {
try {
((WptPt) parse).hdop = Float.parseFloat(text);
} catch (NumberFormatException e) {
}
}
} else if (parser.getName().equals("time")) {
String text = readText(parser, "time");
if (text != null) {
try {
((WptPt) parse).time = format.parse(text).getTime();
} catch (ParseException e) {
}
}
res.locations.get(res.locations.size() - 1).add(current);
}
}
}
} else if (tok == XmlPullParser.END_TAG) {
Object parse = parserState.peek();
String tag = parser.getName();
if (parse instanceof GPXExtensions && tag.equals("extensions")) {
extensionReadMode = false;
}
if(tag.equals("trkpt")){
Object pop = parserState.pop();
assert pop instanceof WptPt;
} else if(tag.equals("wpt")){
Object pop = parserState.pop();
assert pop instanceof WptPt;
} else if(tag.equals("rtept")){
Object pop = parserState.pop();
assert pop instanceof WptPt;
} else if(tag.equals("trk")){
Object pop = parserState.pop();
assert pop instanceof Track;
} else if(tag.equals("rte")){
Object pop = parserState.pop();
assert pop instanceof Route;
} else if(tag.equals("trkseg")){
Object pop = parserState.pop();
assert pop instanceof TrkSegment;
}
}
}
if(convertCloudmadeSource && res.isCloudmadeRouteFile()){
Track tk = new Track();
res.tracks.add(tk);
TrkSegment segment = new TrkSegment();
tk.segments.add(segment);
for(WptPt wp : res.points){
segment.points.add(wp);
}
res.points.clear();
}
} catch (XmlPullParserException e) {
log.error("Error reading gpx", e); //$NON-NLS-1$
res.error = ctx.getString(R.string.error_reading_gpx);
res.warning = ctx.getString(R.string.error_reading_gpx);
} catch (IOException e) {
log.error("Error reading gpx", e); //$NON-NLS-1$
res.error = ctx.getString(R.string.error_reading_gpx);
res.warning = ctx.getString(R.string.error_reading_gpx);
}
return res;
}
private static WptPt convertLocationToWayPoint(Location current, String name){
WptPt pt = new WptPt();
pt.lat = current.getLatitude();
pt.lon = current.getLongitude();
if(current.hasAltitude()) {
pt.ele = current.getAltitude();
private static WptPt parseWptAttributes(XmlPullParser parser) {
WptPt wpt = new WptPt();
try {
wpt.lat = Double.parseDouble(parser.getAttributeValue("", "lat")); //$NON-NLS-1$ //$NON-NLS-2$
wpt.lon = Double.parseDouble(parser.getAttributeValue("", "lon")); //$NON-NLS-1$ //$NON-NLS-2$
} catch (NumberFormatException e) {
}
if(current.hasSpeed()) {
pt.speed = current.getSpeed();
}
if(current.hasAccuracy()) {
pt.hdop = current.getAccuracy();
}
pt.time = current.getTime();
pt.name = name;
return pt;
return wpt;
}
}

View file

@ -16,7 +16,6 @@ import net.osmand.FavouritePoint;
import net.osmand.GPXUtilities;
import net.osmand.OsmAndFormatter;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXFileResult;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
@ -377,15 +376,18 @@ public class FavouritesActivity extends ExpandableListActivity {
existedPoints.add(fp.getName() + "_" + fp.getCategory());
}
}
GPXFileResult res = GPXUtilities.loadGPXFile(FavouritesActivity.this, f);
if(res.error != null){
return res.error;
GPXFile res = GPXUtilities.loadGPXFile(FavouritesActivity.this, f, false);
if(res.warning != null){
return res.warning;
}
for(WptPt p : res.wayPoints){
for(WptPt p : res.points){
if(!existedPoints.contains(p.name)){
String categoryName = FavouritesActivity.this.getString(R.string.favorite_default_category);
int c;
String name = p.name;
if(name == null){
name = "";
}
if((c = p.name.lastIndexOf('_')) != -1){
categoryName = p.name.substring(c + 1);
name = p.name.substring(0, c);

View file

@ -15,7 +15,10 @@ import java.util.TreeSet;
import net.osmand.GPXUtilities;
import net.osmand.OsmAndFormatter;
import net.osmand.GPXUtilities.GPXFileResult;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.Track;
import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.binary.BinaryIndexPart;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion;
@ -35,7 +38,6 @@ import net.osmand.plus.voice.MediaCommandPlayerImpl;
import net.osmand.plus.voice.TTSCommandPlayerImpl;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.location.Location;
import android.os.Build;
public class LocalIndexHelper {
@ -103,21 +105,21 @@ public class LocalIndexHelper {
private void updateGpxInfo(LocalIndexInfo info, File f) {
if(info.getGpxFile() == null){
info.setGpxFile(GPXUtilities.loadGPXFile(app, f));
info.setGpxFile(GPXUtilities.loadGPXFile(app, f, true));
}
GPXFileResult result = info.getGpxFile();
if(result.error != null){
GPXFile result = info.getGpxFile();
if(result.warning != null){
info.setCorrupted(true);
info.setDescription(result.error);
info.setDescription(result.warning);
} else {
int totalDistance = 0;
int totalTracks = 0;
long startTime = Long.MAX_VALUE;
long endTime = Long.MIN_VALUE;
double diffElevationUp = 0;
double diffElevationDown = 0;
double totalElevation = 0;
double Elevation = 0;
double minElevation = 99999;
double maxElevation = 0;
@ -126,39 +128,48 @@ public class LocalIndexHelper {
double totalSpeedSum = 0;
int points = 0;
for(int i = 0; i< result.locations.size() ; i++){
List<Location> subtrack = result.locations.get(i);
points += subtrack.size();
int distance = 0;
for (int j = 0; j < subtrack.size(); j++) {
long time = subtrack.get(j).getTime();
if(time != 0){
startTime = Math.min(startTime, time);
endTime = Math.max(startTime, time);
}
float speed = subtrack.get(j).getSpeed();
if(speed > 0){
totalSpeedSum += speed;
maxSpeed = Math.max(speed, maxSpeed);
speedCount ++;
for(int i = 0; i< result.tracks.size() ; i++){
Track subtrack = result.tracks.get(i);
for(TrkSegment segment : subtrack.segments){
totalTracks++;
points += segment.points.size();
for (int j = 0; j < segment.points.size(); j++) {
WptPt point = segment.points.get(j);
long time = point.time;
if(time != 0){
startTime = Math.min(startTime, time);
endTime = Math.max(startTime, time);
}
float speed = (float) point.speed;
if(speed > 0){
totalSpeedSum += speed;
maxSpeed = Math.max(speed, maxSpeed);
speedCount ++;
}
double elevation = point.ele;
if (!Double.isNaN(elevation)) {
totalElevation += elevation;
minElevation = Math.min(elevation, minElevation);
maxElevation = Math.max(elevation, maxElevation);
}
if (j > 0) {
WptPt prev = segment.points.get(j - 1);
if (!Double.isNaN(point.ele) && !Double.isNaN(prev.ele)) {
double diff = point.ele - prev.ele;
if (diff > 0) {
diffElevationUp += diff;
} else {
diffElevationDown -= diff;
}
}
totalDistance += MapUtils.getDistance(prev.lat, prev.lon, point.lat, point.lon);
}
}
Elevation = subtrack.get(j).getAltitude();
totalElevation += Elevation;
minElevation = Math.min(Elevation, minElevation);
maxElevation = Math.max(Elevation, maxElevation);
if (j > 0) {
double diff = subtrack.get(j).getAltitude() - subtrack.get(j - 1).getAltitude();
if(diff > 0){
diffElevationUp += diff;
} else {
diffElevationDown -= diff;
}
distance += MapUtils.getDistance(subtrack.get(j - 1).getLatitude(), subtrack.get(j - 1).getLongitude(), subtrack
.get(j).getLatitude(), subtrack.get(j).getLongitude());
}
}
totalDistance += distance;
}
if(startTime == Long.MAX_VALUE){
startTime = f.lastModified();
@ -167,8 +178,8 @@ public class LocalIndexHelper {
endTime = f.lastModified();
}
info.setDescription(app.getString(R.string.local_index_gpx_info, result.locations.size(), points,
result.wayPoints.size(), OsmAndFormatter.getFormattedDistance(totalDistance, app),
info.setDescription(app.getString(R.string.local_index_gpx_info, totalTracks, points,
result.points.size(), OsmAndFormatter.getFormattedDistance(totalDistance, app),
startTime, endTime));
if(totalElevation != 0 || diffElevationUp != 0 || diffElevationDown != 0){
info.setDescription(info.getDescription() +
@ -403,7 +414,7 @@ public class LocalIndexHelper {
// UI state expanded
private boolean expanded;
private GPXFileResult gpxFile;
private GPXFile gpxFile;
public LocalIndexInfo(LocalIndexType type, File f, boolean backuped){
pathToData = f.getAbsolutePath();
@ -446,11 +457,11 @@ public class LocalIndexHelper {
this.kbSize = size;
}
public void setGpxFile(GPXFileResult gpxFile) {
public void setGpxFile(GPXFile gpxFile) {
this.gpxFile = gpxFile;
}
public GPXFileResult getGpxFile() {
public GPXFile getGpxFile() {
return gpxFile;
}

View file

@ -14,6 +14,7 @@ import java.util.Set;
import net.osmand.Algoritms;
import net.osmand.IProgress;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.ResourceManager;
@ -27,7 +28,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.AsyncTask.Status;
@ -97,10 +97,10 @@ public class LocalIndexesActivity extends ExpandableListActivity {
if (child >= 0 && group >= 0) {
final LocalIndexInfo point = (LocalIndexInfo) listAdapter.getChild(group, child);
if (point != null && point.getGpxFile() != null) {
Location loc = point.getGpxFile().findFistLocation();
WptPt loc = point.getGpxFile().findPointToShow();
if (loc != null) {
OsmandSettings.getOsmandSettings(LocalIndexesActivity.this).setMapLocationToShow(loc.getLatitude(),
loc.getLongitude());
OsmandSettings.getOsmandSettings(LocalIndexesActivity.this).setMapLocationToShow(loc.lat,
loc.lon);
}
((OsmandApplication) getApplication()).setGpxFileToDisplay(point.getGpxFile());
MapActivity.launchMapActivityMoveToTop(LocalIndexesActivity.this);

View file

@ -1,14 +1,13 @@
package net.osmand.plus.activities;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.osmand.Algoritms;
import net.osmand.CallbackWithObject;
import net.osmand.LogUtil;
import net.osmand.Version;
import net.osmand.GPXUtilities.GPXFileResult;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.data.MapTileDownloader;
import net.osmand.data.MapTileDownloader.DownloadRequest;
import net.osmand.data.MapTileDownloader.IMapDownloaderCallback;
@ -19,6 +18,7 @@ import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.ResourceManager;
import net.osmand.plus.activities.RouteProvider.GPXRouteParams;
import net.osmand.plus.activities.search.SearchActivity;
import net.osmand.plus.activities.search.SearchPoiFilterActivity;
import net.osmand.plus.activities.search.SearchTransportActivity;
@ -1190,10 +1190,10 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
private void useGPXRouting() {
final LatLon endForRouting = getPointToNavigate();
mapLayers.selectGPXFileLayer(new CallbackWithObject<GPXFileResult>() {
mapLayers.selectGPXFileLayer(new CallbackWithObject<GPXFile>() {
@Override
public boolean processResult(final GPXFileResult result) {
public boolean processResult(final GPXFile result) {
Builder builder = new AlertDialog.Builder(MapActivity.this);
final boolean[] props = new boolean[]{false, false, false};
builder.setMultiChoiceItems(new String[] { getString(R.string.gpx_option_reverse_route),
@ -1209,35 +1209,35 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
public void onClick(DialogInterface dialog, int which) {
boolean reverse = props[0];
boolean passWholeWay = props[2];
ArrayList<List<Location>> locations = result.locations;
List<Location> l = new ArrayList<Location>();
for(List<Location> s : locations){
l.addAll(s);
}
if(reverse){
Collections.reverse(l);
}
boolean useDestination = props[1];
GPXRouteParams gpxRoute = new GPXRouteParams(result, reverse);
Location loc = getLastKnownLocation();
if(passWholeWay && loc != null){
l.add(0, loc);
gpxRoute.setStartPoint(loc);
}
Location startForRouting = getLastKnownLocation();
if(startForRouting == null && !l.isEmpty()){
startForRouting = l.get(0);
if(startForRouting == null){
startForRouting = gpxRoute.getStartPointForRoute();
}
LatLon endPoint = endForRouting;
if((endPoint == null || !props[1]) && !l.isEmpty()){
LatLon point = new LatLon(l.get(l.size() - 1).getLatitude(), l.get(l.size() - 1).getLongitude());
settings.setPointToNavigate(point.getLatitude(), point.getLongitude(), null);
endPoint = point;
mapLayers.getNavigationLayer().setPointToNavigate(point);
if(endPoint == null || !useDestination){
LatLon point = gpxRoute.getLastPoint();
if(point != null){
endPoint = point;
}
if(endPoint != null) {
settings.setPointToNavigate(point.getLatitude(), point.getLongitude(), null);
mapLayers.getNavigationLayer().setPointToNavigate(point);
}
}
mapView.refreshMap();
if(endPoint != null){
settings.FOLLOW_TO_THE_ROUTE.set(true);
routingHelper.setFollowingMode(true);
routingHelper.setFinalAndCurrentLocation(endPoint, startForRouting, l);
routingHelper.setFinalAndCurrentLocation(endPoint, startForRouting, gpxRoute);
getMyApplication().showDialogInitializingCommandPlayer(MapActivity.this);
}
}
@ -1246,7 +1246,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
builder.show();
return true;
}
});
}, false);
}
public void contextMenuPoint(final double latitude, final double longitude){

View file

@ -12,7 +12,7 @@ import java.util.Map.Entry;
import net.osmand.Algoritms;
import net.osmand.CallbackWithObject;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFileResult;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.OsmAndFormatter;
import net.osmand.data.AmenityType;
import net.osmand.map.ITileSource;
@ -327,9 +327,9 @@ public class MapActivityLayers {
public void showGPXFileLayer(final OsmandMapTileView mapView){
final OsmandSettings settings = getApplication().getSettings();
selectGPXFileLayer(new CallbackWithObject<GPXFileResult>() {
selectGPXFileLayer(new CallbackWithObject<GPXFile>() {
@Override
public boolean processResult(GPXFileResult result) {
public boolean processResult(GPXFile result) {
settings.SHOW_FAVORITES.set(true);
if (result != null) {
getApplication().setGpxFileToDisplay(result);
@ -338,19 +338,19 @@ public class MapActivityLayers {
}
return true;
}
});
}, true);
}
private void updateGPXLayer(){
GPXFileResult gpxFileToDisplay = getApplication().getGpxFileToDisplay();
GPXFile gpxFileToDisplay = getApplication().getGpxFileToDisplay();
if(gpxFileToDisplay == null){
gpxLayer.setTracks(null);
} else {
gpxLayer.setTracks(gpxFileToDisplay.locations);
gpxLayer.setTracks(gpxFileToDisplay.tracks);
}
}
public void selectGPXFileLayer(final CallbackWithObject<GPXFileResult> callbackWithObject) {
public void selectGPXFileLayer(final CallbackWithObject<GPXFile> callbackWithObject, final boolean convertCloudmade) {
final List<String> list = new ArrayList<String>();
final OsmandSettings settings = getApplication().getSettings();
final File dir = settings.extendOsmandPath(ResourceManager.GPX_PATH);
@ -393,22 +393,16 @@ public class MapActivityLayers {
new Thread(new Runnable() {
@Override
public void run() {
final GPXFileResult res = GPXUtilities.loadGPXFile(activity, f);
if (res.error != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity, res.error, Toast.LENGTH_LONG).show();
}
});
}
final GPXFile res = GPXUtilities.loadGPXFile(activity, f, convertCloudmade);
dlg.dismiss();
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
callbackWithObject.processResult(res);
if(res.warning != null){
Toast.makeText(activity, res.warning, Toast.LENGTH_LONG).show();
} else {
callbackWithObject.processResult(res);
}
}
});
}

View file

@ -13,7 +13,7 @@ import java.util.Locale;
import net.osmand.Algoritms;
import net.osmand.FavouritePoint;
import net.osmand.LogUtil;
import net.osmand.GPXUtilities.GPXFileResult;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.NavigationService;
@ -35,7 +35,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.AsyncTask;
import android.os.Handler;
import android.text.format.DateFormat;
import android.util.Log;
@ -60,7 +59,7 @@ public class OsmandApplication extends Application {
private ProgressDialogImplementation startDialog;
private List<String> startingWarnings;
private Handler uiHandler;
private GPXFileResult gpxFileToDisplay;
private GPXFile gpxFileToDisplay;
private boolean applicationInitializing = false;
private Locale prefferedLocale = null;
@ -106,16 +105,19 @@ public class OsmandApplication extends Application {
return poiFilters;
}
public void setGpxFileToDisplay(GPXFileResult gpxFileToDisplay) {
public void setGpxFileToDisplay(GPXFile gpxFileToDisplay) {
this.gpxFileToDisplay = gpxFileToDisplay;
if(gpxFileToDisplay == null){
getFavorites().setFavoritePointsFromGPXFile(null);
} else {
List<FavouritePoint> pts = new ArrayList<FavouritePoint>();
for (WptPt p : gpxFileToDisplay.wayPoints) {
for (WptPt p : gpxFileToDisplay.points) {
FavouritePoint pt = new FavouritePoint();
pt.setLatitude(p.lat);
pt.setLongitude(p.lon);
if(p.name == null){
p.name = "";
}
pt.setName(p.name);
pts.add(pt);
}
@ -123,7 +125,7 @@ public class OsmandApplication extends Application {
}
}
public GPXFileResult getGpxFileToDisplay() {
public GPXFile getGpxFileToDisplay() {
return gpxFileToDisplay;
}

View file

@ -6,6 +6,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
@ -14,8 +15,14 @@ import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import net.osmand.GPXUtilities;
import net.osmand.LogUtil;
import net.osmand.OsmAndFormatter;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.Route;
import net.osmand.GPXUtilities.Track;
import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
@ -31,7 +38,6 @@ import net.osmand.router.RoutingContext;
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
@ -57,6 +63,76 @@ public class RouteProvider {
public RouteProvider(){
}
public static class GPXRouteParams {
List<Location> points = new ArrayList<Location>();
List<RouteDirectionInfo> directions;
public GPXRouteParams(GPXFile file, boolean reverse){
prepareEverything(file, reverse);
}
public void setStartPoint(Location startPoint) {
points.add(0, startPoint);
}
public Location getStartPointForRoute(){
if(!points.isEmpty()){
return points.get(0);
}
return null;
}
public LatLon getLastPoint() {
if(!points.isEmpty()){
Location l = points.get(points.size() - 1);
LatLon point = new LatLon(l.getLatitude(), l.getLongitude());
return point;
}
return null;
}
private void prepareEverything(GPXFile file, boolean reverse){
if(file.isCloudmadeRouteFile()){
directions = parseCloudmadeRoute(points, file);
if(reverse){
// clear directions all turns should be recalculated
directions = null;
Collections.reverse(points);
}
} else {
// first of all check tracks
for (Track tr : file.tracks) {
for (TrkSegment tkSeg : tr.segments) {
for (WptPt pt : tkSeg.points) {
points.add(createLocation(pt));
}
}
}
if (points.isEmpty()) {
for (Route rte : file.routes) {
for (WptPt pt : rte.points) {
points.add(createLocation(pt));
}
}
}
if (reverse) {
Collections.reverse(points);
}
}
}
}
private static Location createLocation(WptPt pt){
Location loc = new Location("OsmandRouteProvider");
loc.setLatitude(pt.lat);
loc.setLongitude(pt.lon);
loc.setSpeed((float) pt.speed);
loc.setAltitude(pt.ele);
loc.setAccuracy((float) pt.hdop);
return loc;
}
public static class RouteCalculationResult {
private final List<Location> locations;
@ -169,7 +245,7 @@ public class RouteProvider {
}
public RouteCalculationResult calculateRouteImpl(Location start, LatLon end, ApplicationMode mode, RouteService type, Context ctx,
List<Location> gpxRoute, boolean fast){
GPXRouteParams gpxRoute, boolean fast){
long time = System.currentTimeMillis();
if (start != null && end != null) {
if(log.isInfoEnabled()){
@ -177,7 +253,7 @@ public class RouteProvider {
}
try {
RouteCalculationResult res;
if(gpxRoute != null && !gpxRoute.isEmpty()){
if(gpxRoute != null && !gpxRoute.points.isEmpty()){
res = calculateGpxRoute(start, end, gpxRoute);
addMissingTurnsToRoute(res, start, end, mode, ctx);
} else if (type == RouteService.YOURS) {
@ -206,11 +282,12 @@ public class RouteProvider {
return new RouteCalculationResult(null);
}
private RouteCalculationResult calculateGpxRoute(Location start, LatLon end, List<Location> gpxRoute) {
private RouteCalculationResult calculateGpxRoute(Location start, LatLon end, GPXRouteParams params) {
RouteCalculationResult res;
// get the closest point to start and to end
float minDist = Integer.MAX_VALUE;
int startI = 0;
List<Location> gpxRoute = params.points;
int endI = gpxRoute.size();
if (start != null) {
for (int i = 0; i < gpxRoute.size(); i++) {
@ -227,7 +304,7 @@ public class RouteProvider {
l.setLatitude(end.getLatitude());
l.setLongitude(end.getLongitude());
minDist = Integer.MAX_VALUE;
// get in reverse order taking into account cycle ways
// get in reverse order taking into account ways with cycle
for (int i = gpxRoute.size() - 1; i >= startI; i--) {
float d = gpxRoute.get(i).distanceTo(l);
if (d < minDist) {
@ -236,7 +313,27 @@ public class RouteProvider {
minDist = d - 40;
}
}
res = new RouteCalculationResult(new ArrayList<Location>(gpxRoute.subList(startI, endI)), null, start, end, null);
ArrayList<Location> sublist = new ArrayList<Location>(gpxRoute.subList(startI, endI));
if(params.directions == null){
res = new RouteCalculationResult(sublist, params.directions, start, end, null);
} else {
List<RouteDirectionInfo> subdirections = new ArrayList<RouteDirectionInfo>();
for (RouteDirectionInfo info : params.directions) {
if(info.routePointOffset >= startI && info.routePointOffset < endI){
RouteDirectionInfo ch = new RouteDirectionInfo();
ch.routePointOffset = info.routePointOffset - startI;
ch.descriptionRoute = info.descriptionRoute;
ch.expectedTime = info.expectedTime;
ch.turnType = info.turnType;
// recalculate
ch.distance = 0;
ch.afterLeftTime = 0;
subdirections.add(ch);
}
}
res = new RouteCalculationResult(sublist, subdirections, start, end, null);
}
return res;
}
@ -554,137 +651,124 @@ public class RouteProvider {
}
protected RouteCalculationResult findCloudMadeRoute(Location start, LatLon end, ApplicationMode mode, Context ctx, boolean fast) throws MalformedURLException, IOException,
ParserConfigurationException, FactoryConfigurationError, SAXException {
protected RouteCalculationResult findCloudMadeRoute(Location start, LatLon end, ApplicationMode mode, Context ctx, boolean fast)
throws MalformedURLException, IOException, ParserConfigurationException, FactoryConfigurationError, SAXException {
List<Location> res = new ArrayList<Location>();
List<RouteDirectionInfo> directions = null;
StringBuilder uri = new StringBuilder();
// possibly hide that API key because it is privacy of osmand
uri.append("http://routes.cloudmade.com/A6421860EBB04234AB5EF2D049F2CD8F/api/0.3/"); //$NON-NLS-1$
uri.append(start.getLatitude()+"").append(","); //$NON-NLS-1$ //$NON-NLS-2$
uri.append(start.getLongitude()+"").append(","); //$NON-NLS-1$ //$NON-NLS-2$
uri.append(end.getLatitude()+"").append(","); //$NON-NLS-1$//$NON-NLS-2$
uri.append(end.getLongitude()+"").append("/"); //$NON-NLS-1$ //$NON-NLS-2$
uri.append(start.getLatitude() + "").append(","); //$NON-NLS-1$ //$NON-NLS-2$
uri.append(start.getLongitude() + "").append(","); //$NON-NLS-1$ //$NON-NLS-2$
uri.append(end.getLatitude() + "").append(","); //$NON-NLS-1$//$NON-NLS-2$
uri.append(end.getLongitude() + "").append("/"); //$NON-NLS-1$ //$NON-NLS-2$
if (ApplicationMode.PEDESTRIAN == mode) {
uri.append("foot.gpx"); //$NON-NLS-1$
} else if (ApplicationMode.BICYCLE == mode) {
uri.append("bicycle.gpx"); //$NON-NLS-1$
} else {
if(fast){
if (fast) {
uri.append("car.gpx"); //$NON-NLS-1$
} else {
uri.append("car/shortest.gpx"); //$NON-NLS-1$
}
}
uri.append("?lang=").append(Locale.getDefault().getLanguage()); //$NON-NLS-1$
URL url = new URL(uri.toString());
URLConnection connection = url.openConnection();
DocumentBuilder dom = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dom.parse(new InputSource(new InputStreamReader(connection.getInputStream())));
// TODO how to find that error occurred ? Gpx API doesn't say anything
NodeList list = doc.getElementsByTagName("wpt"); //$NON-NLS-1$
for (int i = 0; i < list.getLength(); i++) {
Element item = (Element) list.item(i);
try {
Location l = new Location("router"); //$NON-NLS-1$
l.setLatitude(Double.parseDouble(item.getAttribute("lat"))); //$NON-NLS-1$
l.setLongitude(Double.parseDouble(item.getAttribute("lon"))); //$NON-NLS-1$
res.add(l);
} catch (NumberFormatException e) {
}
GPXFile gpxFile = GPXUtilities.loadGPXFile(ctx, connection.getInputStream(), false);
directions = parseCloudmadeRoute(res, gpxFile);
return new RouteCalculationResult(res, directions, start, end, null);
}
private static List<RouteDirectionInfo> parseCloudmadeRoute(List<Location> res, GPXFile gpxFile) {
List<RouteDirectionInfo> directions = null;
for (WptPt pt : gpxFile.points) {
res.add(createLocation(pt));
}
list = doc.getElementsByTagName("rtept"); //$NON-NLS-1$
if(list.getLength() > 0){
directions = new ArrayList<RouteDirectionInfo>();
Route route = null;
if (gpxFile.routes.size() > 0) {
route = gpxFile.routes.get(0);
}
RouteDirectionInfo previous = null;
for (int i = 0; i < list.getLength(); i++) {
Element item = (Element) list.item(i);
try {
RouteDirectionInfo dirInfo = new RouteDirectionInfo();
dirInfo.descriptionRoute = getContentFromNode(item, "desc"); //$NON-NLS-1$
String stime = getContentFromNode(item, "time"); //$NON-NLS-1$
if(stime != null){
dirInfo.expectedTime = Integer.parseInt(stime);
}
String stype = getContentFromNode(item, "turn"); //$NON-NLS-1$
if(stype != null){
dirInfo.turnType = TurnType.valueOf(stype.toUpperCase());
} else {
dirInfo.turnType = TurnType.valueOf(TurnType.C);
}
String sturn = getContentFromNode(item, "turn-angle"); //$NON-NLS-1$
if(sturn != null){
dirInfo.turnType.setTurnAngle((float) Double.parseDouble(sturn));
}
int offset = Integer.parseInt(getContentFromNode(item, "offset")); //$NON-NLS-1$
dirInfo.routePointOffset = offset;
if(previous != null && previous.turnType != null && !TurnType.C.equals(previous.turnType.getValue())){
// calculate angle
if(previous.routePointOffset > 0){
float paz = res.get(previous.routePointOffset - 1).bearingTo(res.get(previous.routePointOffset));
float caz;
if(previous.turnType.isRoundAbout() && dirInfo.routePointOffset < res.size() - 1){
caz = res.get(dirInfo.routePointOffset).bearingTo(res.get(dirInfo.routePointOffset + 1));
} else {
caz = res.get(dirInfo.routePointOffset - 1).bearingTo(res.get(dirInfo.routePointOffset));
}
float angle = caz - paz;
if(angle < 0){
angle += 360;
} else if(angle > 360){
angle -= 360;
}
// that magic number helps to fix some errors for turn
angle += 75;
if (route != null && route.points.size() > 0) {
directions = new ArrayList<RouteDirectionInfo>();
for (WptPt item : route.points) {
try {
RouteDirectionInfo dirInfo = new RouteDirectionInfo();
dirInfo.descriptionRoute = item.desc; //$NON-NLS-1$
String stime = item.getExtensionsToRead().get("time");
if (stime != null) {
dirInfo.expectedTime = Integer.parseInt(stime);
}
String stype = item.getExtensionsToRead().get("turn"); //$NON-NLS-1$
if (stype != null) {
dirInfo.turnType = TurnType.valueOf(stype.toUpperCase());
} else {
dirInfo.turnType = TurnType.valueOf(TurnType.C);
}
String sturn = item.getExtensionsToRead().get("turn-angle"); //$NON-NLS-1$
if (sturn != null) {
dirInfo.turnType.setTurnAngle((float) Double.parseDouble(sturn));
}
if(previous.turnType.getTurnAngle() < 0.5f){
previous.turnType.setTurnAngle(angle);
int offset = Integer.parseInt(item.getExtensionsToRead().get("offset")); //$NON-NLS-1$
dirInfo.routePointOffset = offset;
if (previous != null && previous.turnType != null && !TurnType.C.equals(previous.turnType.getValue())) {
// calculate angle
if (previous.routePointOffset > 0) {
float paz = res.get(previous.routePointOffset - 1).bearingTo(res.get(previous.routePointOffset));
float caz;
if (previous.turnType.isRoundAbout() && dirInfo.routePointOffset < res.size() - 1) {
caz = res.get(dirInfo.routePointOffset).bearingTo(res.get(dirInfo.routePointOffset + 1));
} else {
caz = res.get(dirInfo.routePointOffset - 1).bearingTo(res.get(dirInfo.routePointOffset));
}
float angle = caz - paz;
if (angle < 0) {
angle += 360;
} else if (angle > 360) {
angle -= 360;
}
// that magic number helps to fix some errors for turn
angle += 75;
if (previous.turnType.getTurnAngle() < 0.5f) {
previous.turnType.setTurnAngle(angle);
}
}
}
}
directions.add(dirInfo);
previous = dirInfo;
} catch (NumberFormatException e) {
log.info("Exception", e); //$NON-NLS-1$
} catch (IllegalArgumentException e) {
log.info("Exception", e); //$NON-NLS-1$
directions.add(dirInfo);
previous = dirInfo;
} catch (NumberFormatException e) {
log.info("Exception", e); //$NON-NLS-1$
} catch (IllegalArgumentException e) {
log.info("Exception", e); //$NON-NLS-1$
}
}
}
if(previous != null && previous.turnType != null && !TurnType.C.equals(previous.turnType.getValue())){
if (previous != null && previous.turnType != null && !TurnType.C.equals(previous.turnType.getValue())) {
// calculate angle
if(previous.routePointOffset > 0 && previous.routePointOffset < res.size() - 1){
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));
float angle = caz - paz;
if(angle < 0){
float caz = res.get(previous.routePointOffset).bearingTo(res.get(res.size() - 1));
float angle = caz - paz;
if (angle < 0) {
angle += 360;
}
if(previous.turnType.getTurnAngle() < 0.5f){
if (previous.turnType.getTurnAngle() < 0.5f) {
previous.turnType.setTurnAngle(angle);
}
}
}
return new RouteCalculationResult(res, directions, start, end, null);
return directions;
}
private String getContentFromNode(Element item, String tagName){
NodeList list = item.getElementsByTagName(tagName);
if(list.getLength() > 0){
return list.item(0).getFirstChild().getNodeValue();
}
return null;
}
}

View file

@ -10,6 +10,7 @@ import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.RouteProvider.GPXRouteParams;
import net.osmand.plus.activities.RouteProvider.RouteCalculationResult;
import net.osmand.plus.activities.RouteProvider.RouteService;
import net.osmand.plus.voice.CommandPlayer;
@ -30,6 +31,7 @@ public class RoutingHelper {
public void routeWasCancelled();
}
private final double DISTANCE_TO_USE_OSMAND_ROUTER = 20000;
private List<IRouteInformationListener> listeners = new ArrayList<IRouteInformationListener>();
@ -41,7 +43,7 @@ public class RoutingHelper {
private boolean isFollowingMode = false;
private List<Location> currentGPXRoute = null;
private GPXRouteParams currentGPXRoute = null;
// instead of this properties RouteCalculationResult could be used
private List<Location> routeNodes = new ArrayList<Location>();
private List<RouteDirectionInfo> directionInfo = null;
@ -87,7 +89,7 @@ public class RoutingHelper {
setFinalAndCurrentLocation(finalLocation, currentLocation, null);
}
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, Location currentLocation, List<Location> gpxRoute){
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, Location currentLocation, GPXRouteParams gpxRoute){
clearCurrentRoute(finalLocation);
currentGPXRoute = gpxRoute;
// to update route
@ -120,7 +122,7 @@ public class RoutingHelper {
}
public List<Location> getCurrentGPXRoute() {
public GPXRouteParams getCurrentGPXRoute() {
return currentGPXRoute;
}
@ -433,7 +435,7 @@ public class RoutingHelper {
return 0;
}
private void recalculateRouteInBackground(final Location start, final LatLon end, final List<Location> currentGPXRoute){
private void recalculateRouteInBackground(final Location start, final LatLon end, final GPXRouteParams gpxRoute){
if (start == null || end == null) {
return;
}
@ -460,7 +462,7 @@ public class RoutingHelper {
if(service != RouteService.OSMAND && !settings.isInternetConnectionAvailable()){
showMessage(context.getString(R.string.internet_connection_required_for_online_route), Toast.LENGTH_LONG);
}
RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode, service, context, currentGPXRoute, fastRouteMode);
RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode, service, context, gpxRoute, fastRouteMode);
synchronized (RoutingHelper.this) {
if (res.isCalculated()) {
setNewRoute(res);
@ -640,6 +642,12 @@ public class RoutingHelper {
// location when you should action (turn or go ahead)
public int routePointOffset;
// TODO add from parser
public String ref;
public String streetName;
// speed limit in m/s (should be array of speed limits?)
public float speedLimit;
// calculated vars
// after action (excluding expectedTime)

View file

@ -3,6 +3,10 @@ package net.osmand.plus.views;
import java.util.ArrayList;
import java.util.List;
import net.osmand.GPXUtilities.Track;
import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.GPXUtilities.WptPt;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@ -12,14 +16,13 @@ import android.graphics.RectF;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.location.Location;
public class GPXLayer implements OsmandMapLayer {
private OsmandMapTileView view;
private List<List<Location>> points = new ArrayList<List<Location>>();
private List<List<WptPt>> points = new ArrayList<List<WptPt>>();
private Paint paint;
@ -51,23 +54,24 @@ public class GPXLayer implements OsmandMapLayer {
@Override
public void onDraw(Canvas canvas, RectF latLonBounds, RectF tilesRect, boolean nightMode) {
List<List<WptPt>> points = this.points;
if(points.isEmpty()){
return;
}
for (List<Location> l : points) {
for (List<WptPt> l : points) {
path.rewind();
int startIndex = -1;
for (int i = 0; i < l.size(); i++) {
Location ls = l.get(i);
WptPt ls = l.get(i);
if (startIndex == -1) {
if (ls.getLatitude() >= latLonBounds.bottom && ls.getLatitude() <= latLonBounds.top && ls.getLongitude() >= latLonBounds.left
&& ls.getLongitude() <= latLonBounds.right ) {
if (ls.lat >= latLonBounds.bottom && ls.lat <= latLonBounds.top && ls.lon >= latLonBounds.left
&& ls.lon <= latLonBounds.right ) {
startIndex = i > 0 ? i - 1 : i;
}
} else if (!(latLonBounds.left <= ls.getLongitude() + 0.03 && ls.getLongitude() - 0.03 <= latLonBounds.right
&& latLonBounds.bottom <= ls.getLatitude() + 0.03 && ls.getLatitude() - 0.03 <= latLonBounds.top)) {
} else if (!(latLonBounds.left <= ls.lon + 0.03 && ls.lon - 0.03 <= latLonBounds.right
&& latLonBounds.bottom <= ls.lat + 0.03 && ls.lat - 0.03 <= latLonBounds.top)) {
drawSegment(canvas, l, startIndex, i);
// do not continue make method more efficient (because it calls in UI thread)
// this break also has logical sense !
@ -84,14 +88,14 @@ public class GPXLayer implements OsmandMapLayer {
}
private void drawSegment(Canvas canvas, List<Location> l, int startIndex, int endIndex) {
int px = view.getMapXForPoint(l.get(startIndex).getLongitude());
int py = view.getMapYForPoint(l.get(startIndex).getLatitude());
private void drawSegment(Canvas canvas, List<WptPt> l, int startIndex, int endIndex) {
int px = view.getMapXForPoint(l.get(startIndex).lon);
int py = view.getMapYForPoint(l.get(startIndex).lat);
path.moveTo(px, py);
for (int i = startIndex + 1; i <= endIndex; i++) {
Location p = l.get(i);
int x = view.getMapXForPoint(p.getLongitude());
int y = view.getMapYForPoint(p.getLatitude());
WptPt p = l.get(i);
int x = view.getMapXForPoint(p.lon);
int y = view.getMapYForPoint(p.lat);
path.lineTo(x, y);
}
canvas.drawPath(path, paint);
@ -107,11 +111,18 @@ public class GPXLayer implements OsmandMapLayer {
points.clear();
}
public void setTracks(List<List<Location>> tracks){
public void setTracks(List<Track> tracks){
if(tracks == null){
clearCurrentGPX();
} else {
points = tracks;
List<List<WptPt>> tpoints = new ArrayList<List<WptPt>>();
for (Track t : tracks) {
for (TrkSegment ts : t.segments) {
tpoints.add(ts.points);
}
}
points = tpoints;
}
}

View file

@ -1,24 +0,0 @@
cd ~/gen_indexes
rm osmand.log
rm console
# update map creator
cd OsmAndMapCreator
yes | unzip /var/www-download/latest-night-build/OsmAndMapCreator-development.zip
cd ..
# remove backup and create new backup
rm -r backup
mkdir backup
mv indexes/uploaded/*.* backup
# remove all previous files
rm -r indexes
mkdir indexes
mkdir indexes/osm
mkdir indexes/uploaded
#run batch creator
./batch_indexing.sh > /dev/null 2&>console &