Implement different GPX read/write

This commit is contained in:
Victor Shcherb 2011-08-31 15:14:13 +02:00
parent 0cb0263259
commit 99dbc17f89
11 changed files with 810 additions and 262 deletions

View file

@ -0,0 +1,316 @@
<?xml version="1.0" encoding="UTF-8"?>
<gpx creator="CloudMade" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<metadata>
<author>
<name>CloudMade</name>
<email id="support" domain="cloudmade.com" />
<link href="http://maps.cloudmade.com"></link>
</author>
<copyright author="CloudMade">
<license>http://cloudmade.com/faq#license</license>
</copyright>
<time>2011-08-28T22:39:40</time>
</metadata>
<extensions>
<distance>10164</distance>
<time>556</time>
<start>Неизвестная дорога возле Минск</start>
<end>Неизвестная дорога возле Боровляны</end>
</extensions>
<wpt lat="53.911297" lon="27.579508" />
<wpt lat="53.91172" lon="27.579926" />
<wpt lat="53.911747" lon="27.579847" />
<wpt lat="53.911819" lon="27.579664" />
<wpt lat="53.911938" lon="27.579315" />
<wpt lat="53.912552" lon="27.579935" />
<wpt lat="53.913841" lon="27.581224" />
<wpt lat="53.913975" lon="27.581381" />
<wpt lat="53.91407" lon="27.581509" />
<wpt lat="53.914108" lon="27.581562" />
<wpt lat="53.914986" lon="27.58288" />
<wpt lat="53.91555" lon="27.583744" />
<wpt lat="53.916466" lon="27.585115" />
<wpt lat="53.916599" lon="27.58534" />
<wpt lat="53.916756" lon="27.585676" />
<wpt lat="53.916908" lon="27.586044" />
<wpt lat="53.918388" lon="27.589788" />
<wpt lat="53.919773" lon="27.593138" />
<wpt lat="53.919983" lon="27.593712" />
<wpt lat="53.921032" lon="27.596378" />
<wpt lat="53.921398" lon="27.597338" />
<wpt lat="53.921646" lon="27.598314" />
<wpt lat="53.921936" lon="27.599611" />
<wpt lat="53.922291" lon="27.601025" />
<wpt lat="53.922447" lon="27.602894" />
<wpt lat="53.922512" lon="27.603594" />
<wpt lat="53.922695" lon="27.605644" />
<wpt lat="53.92284" lon="27.60741" />
<wpt lat="53.922871" lon="27.607737" />
<wpt lat="53.922993" lon="27.608934" />
<wpt lat="53.923038" lon="27.6092" />
<wpt lat="53.923077" lon="27.609394" />
<wpt lat="53.923714" lon="27.61199" />
<wpt lat="53.924309" lon="27.614241" />
<wpt lat="53.924568" lon="27.615273" />
<wpt lat="53.924698" lon="27.615744" />
<wpt lat="53.924911" lon="27.616541" />
<wpt lat="53.925529" lon="27.618874" />
<wpt lat="53.925598" lon="27.619146" />
<wpt lat="53.925873" lon="27.620188" />
<wpt lat="53.926109" lon="27.62109" />
<wpt lat="53.927292" lon="27.625641" />
<wpt lat="53.927528" lon="27.62648" />
<wpt lat="53.928188" lon="27.62883" />
<wpt lat="53.92849" lon="27.62993" />
<wpt lat="53.928558" lon="27.63019" />
<wpt lat="53.929111" lon="27.6322" />
<wpt lat="53.929832" lon="27.634825" />
<wpt lat="53.929871" lon="27.63497" />
<wpt lat="53.930943" lon="27.638798" />
<wpt lat="53.931" lon="27.639025" />
<wpt lat="53.931091" lon="27.639357" />
<wpt lat="53.932308" lon="27.643827" />
<wpt lat="53.93256" lon="27.644732" />
<wpt lat="53.933575" lon="27.648359" />
<wpt lat="53.934841" lon="27.652927" />
<wpt lat="53.934895" lon="27.653145" />
<wpt lat="53.935661" lon="27.65589" />
<wpt lat="53.935753" lon="27.656187" />
<wpt lat="53.936111" lon="27.65748" />
<wpt lat="53.937061" lon="27.660999" />
<wpt lat="53.937351" lon="27.662027" />
<wpt lat="53.938129" lon="27.664841" />
<wpt lat="53.938789" lon="27.66703" />
<wpt lat="53.939651" lon="27.669727" />
<wpt lat="53.94006" lon="27.67111" />
<wpt lat="53.940483" lon="27.672497" />
<wpt lat="53.940868" lon="27.673742" />
<wpt lat="53.941471" lon="27.67568" />
<wpt lat="53.941601" lon="27.67606" />
<wpt lat="53.941601" lon="27.676374" />
<wpt lat="53.941601" lon="27.676493" />
<wpt lat="53.94154" lon="27.67675" />
<wpt lat="53.941429" lon="27.67683" />
<wpt lat="53.941299" lon="27.676802" />
<wpt lat="53.941208" lon="27.676691" />
<wpt lat="53.940552" lon="27.675571" />
<wpt lat="53.93985" lon="27.674423" />
<wpt lat="53.93977" lon="27.674229" />
<wpt lat="53.939758" lon="27.674" />
<wpt lat="53.939781" lon="27.67387" />
<wpt lat="53.939823" lon="27.673714" />
<wpt lat="53.940037" lon="27.673569" />
<wpt lat="53.940628" lon="27.673307" />
<wpt lat="53.940788" lon="27.673244" />
<wpt lat="53.941002" lon="27.673157" />
<wpt lat="53.941441" lon="27.672966" />
<wpt lat="53.942101" lon="27.672688" />
<wpt lat="53.942501" lon="27.67248" />
<wpt lat="53.942871" lon="27.672199" />
<wpt lat="53.943474" lon="27.671619" />
<wpt lat="53.943821" lon="27.671207" />
<wpt lat="53.94418" lon="27.67057" />
<wpt lat="53.94474" lon="27.669333" />
<wpt lat="53.944969" lon="27.66872" />
<wpt lat="53.94519" lon="27.668297" />
<wpt lat="53.945419" lon="27.668032" />
<wpt lat="53.945709" lon="27.667965" />
<wpt lat="53.945877" lon="27.668032" />
<wpt lat="53.946007" lon="27.668152" />
<wpt lat="53.946095" lon="27.66824" />
<wpt lat="53.946163" lon="27.668297" />
<wpt lat="53.94651" lon="27.667318" />
<wpt lat="53.946758" lon="27.666662" />
<wpt lat="53.946861" lon="27.666388" />
<wpt lat="53.946987" lon="27.666504" />
<wpt lat="53.94738" lon="27.666912" />
<wpt lat="53.947731" lon="27.66732" />
<wpt lat="53.9482" lon="27.667938" />
<wpt lat="53.948303" lon="27.66818" />
<wpt lat="53.94836" lon="27.668312" />
<wpt lat="53.948509" lon="27.668699" />
<wpt lat="53.948666" lon="27.669155" />
<wpt lat="53.949013" lon="27.670317" />
<wpt lat="53.949516" lon="27.671894" />
<wpt lat="53.949539" lon="27.67197" />
<wpt lat="53.9496" lon="27.672165" />
<wpt lat="53.949776" lon="27.67272" />
<wpt lat="53.949799" lon="27.6728" />
<wpt lat="53.950008" lon="27.673492" />
<wpt lat="53.950375" lon="27.67465" />
<wpt lat="53.950459" lon="27.674915" />
<wpt lat="53.950569" lon="27.67531" />
<wpt lat="53.950745" lon="27.675859" />
<wpt lat="53.95126" lon="27.6775" />
<wpt lat="53.951527" lon="27.678341" />
<wpt lat="53.951672" lon="27.678787" />
<wpt lat="53.95203" lon="27.679934" />
<wpt lat="53.952141" lon="27.680267" />
<wpt lat="53.952465" lon="27.681379" />
<wpt lat="53.95253" lon="27.681583" />
<wpt lat="53.952629" lon="27.681919" />
<wpt lat="53.952686" lon="27.681795" />
<wpt lat="53.952709" lon="27.68173" />
<wpt lat="53.953102" lon="27.680672" />
<wpt lat="53.953133" lon="27.680742" />
<wpt lat="53.953442" lon="27.681711" />
<wpt lat="53.953861" lon="27.681322" />
<wpt lat="53.953857" lon="27.681313" />
<rte>
<rtept lat="53.911297" lon="27.579508">
<desc>Направляйтесь на северо-восток, 55 м</desc>
<extensions>
<distance>55</distance>
<time>20</time>
<offset>0</offset>
<distance-text>55 м</distance-text>
<direction>NE</direction>
<azimuth>30.2</azimuth>
</extensions>
</rtept>
<rtept lat="53.91172" lon="27.579926">
<desc>Поверните налево, 61 м</desc>
<extensions>
<distance>61</distance>
<time>22</time>
<offset>1</offset>
<distance-text>61 м</distance-text>
<direction>NW</direction>
<azimuth>300.7</azimuth>
<turn>TL</turn>
<turn-angle>270.4</turn-angle>
</extensions>
</rtept>
<rtept lat="53.911938" lon="27.579315">
<desc>Поверните направо на просп. Независимости, 3.1 км</desc>
<extensions>
<distance>3050</distance>
<time>146</time>
<offset>4</offset>
<distance-text>3.1 км</distance-text>
<direction>NE</direction>
<azimuth>30.9</azimuth>
<turn>TR</turn>
<turn-angle>91.0</turn-angle>
</extensions>
</rtept>
<rtept lat="53.924698" lon="27.615744">
<desc>Продолжайте движение по просп. Независимости, 3.7 км</desc>
<extensions>
<distance>3736</distance>
<time>179</time>
<offset>35</offset>
<distance-text>3.7 км</distance-text>
<direction>NE</direction>
<azimuth>65.6</azimuth>
<turn>C</turn>
<turn-angle>0.5</turn-angle>
</extensions>
</rtept>
<rtept lat="53.938789" lon="27.66703">
<desc>Продолжайте движение по просп. Независимости, 0.8 км</desc>
<extensions>
<distance>772</distance>
<time>37</time>
<offset>63</offset>
<distance-text>0.8 км</distance-text>
<direction>NE</direction>
<azimuth>61.6</azimuth>
<turn>C</turn>
<turn-angle>358.6</turn-angle>
</extensions>
</rtept>
<rtept lat="53.941601" lon="27.67606">
<desc>Примите вправо, 0.7 км</desc>
<extensions>
<distance>707</distance>
<time>32</time>
<offset>69</offset>
<distance-text>0.7 км</distance-text>
<direction>E</direction>
<azimuth>90.0</azimuth>
<turn>TSLR</turn>
<turn-angle>30.1</turn-angle>
</extensions>
</rtept>
<rtept lat="53.941441" lon="27.672966">
<desc>Продолжайте движение по M9/МКАД, 0.9 км</desc>
<extensions>
<distance>877</distance>
<time>35</time>
<offset>86</offset>
<distance-text>0.9 км</distance-text>
<direction>N</direction>
<azimuth>346.1</azimuth>
<turn>C</turn>
<turn-angle>0.2</turn-angle>
</extensions>
</rtept>
<rtept lat="53.944969" lon="27.66872">
<desc>Примите вправо, 0.2 км</desc>
<extensions>
<distance>164</distance>
<time>7</time>
<offset>94</offset>
<distance-text>0.2 км</distance-text>
<direction>NW</direction>
<azimuth>311.5</azimuth>
<turn>TSLR</turn>
<turn-angle>9.1</turn-angle>
</extensions>
</rtept>
<rtept lat="53.946163" lon="27.668297">
<desc>Поверните налево на Городецкая ул., 0.2 км</desc>
<extensions>
<distance>198</distance>
<time>10</time>
<offset>101</offset>
<distance-text>0.2 км</distance-text>
<direction>NW</direction>
<azimuth>301.3</azimuth>
<turn>TL</turn>
<turn-angle>272.6</turn-angle>
</extensions>
</rtept>
<rtept lat="53.946861" lon="27.666388">
<desc>Поверните направо на ул. Гинтовта, 1.4 км</desc>
<extensions>
<distance>1389</distance>
<time>71</time>
<offset>104</offset>
<distance-text>1.4 км</distance-text>
<direction>NE</direction>
<azimuth>28.2</azimuth>
<turn>TR</turn>
<turn-angle>85.6</turn-angle>
</extensions>
</rtept>
<rtept lat="53.952629" lon="27.681919">
<desc>Поверните налево на Лопатина ул., 0.2 км</desc>
<extensions>
<distance>180</distance>
<time>9</time>
<offset>131</offset>
<distance-text>0.2 км</distance-text>
<direction>NW</direction>
<azimuth>308.0</azimuth>
<turn>TL</turn>
<turn-angle>242.8</turn-angle>
</extensions>
</rtept>
<rtept lat="53.953102" lon="27.680672">
<desc>Поверните направо, 0.3 км</desc>
<extensions>
<distance>258</distance>
<time>93</time>
<offset>134</offset>
<distance-text>0.3 км</distance-text>
<direction>NE</direction>
<azimuth>53.8</azimuth>
<turn>TR</turn>
<turn-angle>111.6</turn-angle>
</extensions>
</rtept>
</rte>
</gpx>

View file

@ -10,9 +10,13 @@ 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 +32,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 +68,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 +131,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 +143,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 +190,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 +250,168 @@ 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) {
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$
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$
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(parser.getText());
} catch (NumberFormatException e) {
}
}
}
} 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 (parse instanceof GPXExtensions && tag.equals("extensions")) {
extensionReadMode = true;
} else {
if (parse instanceof GPXFile) {
if (parser.getName().equals("gpx")) {
((GPXFile) parse).author = parser.getAttributeValue("", "creator");
}
}
} 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) {
if (parser.getName().equals("trk")) {
Track track = new Track();
((GPXFile) parse).tracks.add(track);
parserState.push(new Track());
}
}
} 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) {
if (parser.getName().equals("rte")) {
Route route = new Route();
((GPXFile) parse).routes.add(route);
parserState.push(route);
}
}
} 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) {
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).name = 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).name = 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).name = 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(parser.getText()).getTime();
} catch (ParseException e) {
}
}
((WptPt) parse).name = readText(parser, "hdop");
}
}
}
} 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>());
}
res.locations.get(res.locations.size() - 1).add(current);
}
}
Object parse = parserState.peek();
String tag = parser.getName();
if (parse instanceof GPXExtensions && tag.equals("extensions")) {
extensionReadMode = false;
}
}
}
} 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,50 @@ 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++;
int distance = 0;
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;
}
}
distance += MapUtils.getDistance(prev.lat, prev.lon, point.lat, point.lon);
}
totalDistance += distance;
}
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 +180,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 +416,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 +459,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

@ -8,6 +8,7 @@ import net.osmand.Algoritms;
import net.osmand.CallbackWithObject;
import net.osmand.LogUtil;
import net.osmand.Version;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXFileResult;
import net.osmand.data.MapTileDownloader;
import net.osmand.data.MapTileDownloader.DownloadRequest;
@ -19,6 +20,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;
@ -1203,10 +1205,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),
@ -1222,35 +1224,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);
}
}
@ -1259,7 +1261,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
builder.show();
return true;
}
});
}, true);
}
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;
}
});
}, false);
}
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, boolean forRouting) {
final List<String> list = new ArrayList<String>();
final OsmandSettings settings = getApplication().getSettings();
final File dir = settings.extendOsmandPath(ResourceManager.GPX_PATH);
@ -393,12 +393,12 @@ public class MapActivityLayers {
new Thread(new Runnable() {
@Override
public void run() {
final GPXFileResult res = GPXUtilities.loadGPXFile(activity, f);
if (res.error != null) {
final GPXFile res = GPXUtilities.loadGPXFile(activity, f, true);
if (res.warning != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity, res.error, Toast.LENGTH_LONG).show();
Toast.makeText(activity, res.warning, Toast.LENGTH_LONG).show();
}
});

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;
@ -16,6 +17,11 @@ import javax.xml.parsers.ParserConfigurationException;
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;
@ -57,6 +63,72 @@ public class RouteProvider {
public RouteProvider(){
}
public static class GPXRouteParams {
List<Location> points = new ArrayList<Location>();
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 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;
}
private void prepareEverything(GPXFile file, boolean reverse){
if(file.isCloudmadeRouteFile()){
for(WptPt wp : file.points){
points.add(createLocation(wp));
}
} 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);
}
}
}
public static class RouteCalculationResult {
private final List<Location> locations;
@ -169,7 +241,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 +249,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 +278,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 +300,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) {
@ -554,24 +627,24 @@ 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$
@ -596,10 +669,8 @@ public class RouteProvider {
}
}
list = doc.getElementsByTagName("rtept"); //$NON-NLS-1$
if(list.getLength() > 0){
if (list.getLength() > 0) {
directions = new ArrayList<RouteDirectionInfo>();
}
RouteDirectionInfo previous = null;
@ -609,50 +680,50 @@ public class RouteProvider {
RouteDirectionInfo dirInfo = new RouteDirectionInfo();
dirInfo.descriptionRoute = getContentFromNode(item, "desc"); //$NON-NLS-1$
String stime = getContentFromNode(item, "time"); //$NON-NLS-1$
if(stime != null){
if (stime != null) {
dirInfo.expectedTime = Integer.parseInt(stime);
}
String stype = getContentFromNode(item, "turn"); //$NON-NLS-1$
if(stype != null){
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){
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())){
if (previous != null && previous.turnType != null && !TurnType.C.equals(previous.turnType.getValue())) {
// calculate angle
if(previous.routePointOffset > 0){
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){
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){
float angle = caz - paz;
if (angle < 0) {
angle += 360;
} else if(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){
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$
@ -660,22 +731,21 @@ public class RouteProvider {
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);
}

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);

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, boolean moreDetail) {
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;
}
}