implement navigation using gpx file
git-svn-id: https://osmand.googlecode.com/svn/trunk@508 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
5618985c9e
commit
0afdfa96dc
13 changed files with 475 additions and 315 deletions
|
@ -10,7 +10,7 @@ public class ToDoConstants {
|
|||
// TODO swing
|
||||
// !!! 12. Reinvent UI of swing app (remove Region object and clear other MapObject) use indexes to show results
|
||||
|
||||
// TODO max 87
|
||||
// TODO max 94
|
||||
// ! 81. Add some objects to POI category (1) to add them into OSM 2) to help navigation)
|
||||
// highway (?), traffic_calming (?), barrier(?), military(?-), landuse (?), office(?), man_made(?), power(?),
|
||||
// railway( station, subway?) - issue 17
|
||||
|
@ -19,7 +19,7 @@ public class ToDoConstants {
|
|||
|
||||
// 89. Transport redesign UI (enable run from context menu, switch go to goal/not) !
|
||||
// 90. Use Junidecode library on the client for fast english translation
|
||||
// 94. Implement navigate using selected gpx track
|
||||
|
||||
|
||||
// 91. Invent binary format (minimize disk space, maximize speed)
|
||||
// 92. Replace poi index with standard map index and unify POI categories
|
||||
|
@ -49,16 +49,9 @@ public class ToDoConstants {
|
|||
// 19. colors for road trunk and motorway
|
||||
// 12. Fix : find proper location for streets ! centralize them (when create index)?
|
||||
|
||||
// TODO Check
|
||||
// 1. check postal_code if the building was registered by relation!
|
||||
// 2. TEST after refactoring : poi custom filters
|
||||
|
||||
// 8. Download with wget
|
||||
// 9. progress while map is loading
|
||||
|
||||
// Unscheduled (complex)
|
||||
// 65. Intermediate points - for better control routing, to avoid traffic jams ...(?)
|
||||
// 40. Support simple vector road rendering (require new index file) (?)
|
||||
// 63. Support simple offline routing(require new index file) (?)
|
||||
|
||||
// Not clear if it is really needed
|
||||
|
@ -68,18 +61,8 @@ public class ToDoConstants {
|
|||
// 83. Add monitoring service to send locations to internet (?)
|
||||
|
||||
// DONE ANDROID :
|
||||
// 70. Show building numbers over map (require changing address index - index 2 more columns lat/lon for fast search).
|
||||
// (Not needed, because of vector rendering)
|
||||
// 82. Rotate map according compass
|
||||
// 85. Remove context menu on long press map ! Accumulate actions and show label (+)
|
||||
// 88. Implement show gpx track from folder
|
||||
|
||||
// DONE SWING
|
||||
// 10. Improve address indexing (use relations). (+)
|
||||
// use relation "a6" (to accumulate streets!), "a3" to read all cities & define boundaries for city (& define that street in city).
|
||||
// ! 9. Fix issues with big files (such as netherlands) - save memory (!)
|
||||
// Current result : for big file (1 - task 60-80% time, 90% memory) (?) (+)
|
||||
// 11. Index buildings using interpolations (from nodes) (+)
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<item android:id="@+id/map_layers" android:title="@string/menu_layers" android:icon="@android:drawable/ic_menu_mapmode"></item>
|
||||
<item android:id="@+id/map_show_settings" android:title="@string/settings_Button" android:icon="@android:drawable/ic_menu_preferences"></item>
|
||||
|
||||
<!-- not visible currently -->
|
||||
<!-- not visible by default -->
|
||||
<item android:id="@+id/map_navigate_to_point" android:title="@string/stop_navigation" android:visible="false" android:icon="@android:drawable/ic_menu_close_clear_cancel"></item>
|
||||
<item android:id="@+id/map_mute" android:title="@string/menu_mute_off" android:visible="false"></item>
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
|||
|
||||
<item android:id="@+id/map_transport" android:title="@string/transport"></item>
|
||||
<item android:title="@string/show_gps_status" android:id="@+id/map_show_gps_status" android:icon="@android:drawable/ic_menu_compass"></item>
|
||||
<item android:title="@string/map_route_by_gpx" android:id="@+id/map_gpx_routing"></item>
|
||||
</group>
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="gpx_reverse_route">Обратный путь</string>
|
||||
<string name="gpx_direct_route">Прямой путь</string>
|
||||
<string name="map_route_by_gpx">Навигация по GPX</string>
|
||||
<string name="gpx_files_not_found">GPX файлы были не найдены в /osmand/tracks директории</string>
|
||||
<string name="layer_gpx_layer">GPX треки</string>
|
||||
<string name="error_reading_gpx">Ошибка при чтении gpx файла</string>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="gpx_reverse_route">Reverse route</string>
|
||||
<string name="gpx_direct_route">Direct route</string>
|
||||
<string name="map_route_by_gpx">Route using GPX</string>
|
||||
<string name="gpx_files_not_found">GPX files were not found in /osmand/tracks directory</string>
|
||||
<string name="layer_gpx_layer">GPX tracks</string>
|
||||
<string name="error_reading_gpx">Error reading gpx data</string>
|
||||
|
|
222
OsmAnd/src/net/osmand/GPXUtilities.java
Normal file
222
OsmAnd/src/net/osmand/GPXUtilities.java
Normal file
|
@ -0,0 +1,222 @@
|
|||
package net.osmand;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.util.Xml;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class GPXUtilities {
|
||||
public final static Log log = LogUtil.getLog(GPXUtilities.class);
|
||||
|
||||
|
||||
|
||||
public final static String GPX_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$
|
||||
|
||||
public static class TrkPt {
|
||||
public double lat;
|
||||
public double lon;
|
||||
public double ele;
|
||||
public double speed;
|
||||
public long time;
|
||||
}
|
||||
|
||||
public static class WptPt {
|
||||
public double lat;
|
||||
public double lon;
|
||||
public String name;
|
||||
}
|
||||
|
||||
|
||||
public static boolean saveToXMLFiles(File fout, List<WptPt> data, Context ctx ){
|
||||
try {
|
||||
FileOutputStream output = new FileOutputStream(fout);
|
||||
XmlSerializer serializer = Xml.newSerializer();
|
||||
serializer.setOutput(output, "UTF-8"); //$NON-NLS-1$
|
||||
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); //$NON-NLS-1$
|
||||
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$
|
||||
serializer.attribute("xmlns", "xsi", "http://www.w3.org/2001/XMLSchema-instance"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
serializer.attribute("xsi", "schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
serializer.attribute(null, "xmlns", "http://www.topografix.com/GPX/1/1"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
for (WptPt l : data) {
|
||||
serializer.startTag(null, "wpt"); //$NON-NLS-1$
|
||||
serializer.attribute(null, "lat", l.lat + ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
serializer.attribute(null, "lon", l.lon + ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
serializer.startTag(null, "name"); //$NON-NLS-1$
|
||||
serializer.text(l.name);
|
||||
serializer.endTag(null, "name"); //$NON-NLS-1$
|
||||
serializer.endTag(null, "wpt"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
serializer.endTag(null, "gpx"); //$NON-NLS-1$
|
||||
serializer.flush();
|
||||
serializer.endDocument();
|
||||
|
||||
return true;
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Error saving gpx", e); //$NON-NLS-1$
|
||||
Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
log.error("Error saving gpx", e); //$NON-NLS-1$
|
||||
Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String saveToXMLFiles(File dir, Map<String, List<List<TrkPt>>> data, Context ctx){
|
||||
SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT);
|
||||
try {
|
||||
for (String f : data.keySet()) {
|
||||
File fout = new File(dir, f + ".gpx"); //$NON-NLS-1$
|
||||
int ind = 1;
|
||||
while(fout.exists()){
|
||||
fout = new File(dir, f + "_"+(++ind)+".gpx"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
FileOutputStream output = new FileOutputStream(fout);
|
||||
XmlSerializer serializer = Xml.newSerializer();
|
||||
serializer.setOutput(output, "UTF-8"); //$NON-NLS-1$
|
||||
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); //$NON-NLS-1$
|
||||
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$
|
||||
serializer.attribute("xmlns", "xsi", "http://www.w3.org/2001/XMLSchema-instance"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
serializer.attribute("xsi", "schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
serializer.attribute(null, "xmlns", "http://www.topografix.com/GPX/1/1"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
serializer.startTag(null, "trk"); //$NON-NLS-1$
|
||||
for(List<TrkPt> l : data.get(f)){
|
||||
serializer.startTag(null, "trkseg"); //$NON-NLS-1$
|
||||
for(TrkPt p : l){
|
||||
serializer.startTag(null, "trkpt"); //$NON-NLS-1$
|
||||
serializer.attribute(null, "lat", p.lat+""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
serializer.attribute(null, "lon", p.lon+""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
serializer.startTag(null, "time"); //$NON-NLS-1$
|
||||
serializer.text(format.format(new Date(p.time)));
|
||||
serializer.endTag(null, "time"); //$NON-NLS-1$
|
||||
serializer.startTag(null, "ele"); //$NON-NLS-1$
|
||||
serializer.text(p.ele+""); //$NON-NLS-1$
|
||||
serializer.endTag(null, "ele"); //$NON-NLS-1$
|
||||
if (p.speed > 0) {
|
||||
serializer.startTag(null, "speed"); //$NON-NLS-1$
|
||||
serializer.text(p.speed + ""); //$NON-NLS-1$
|
||||
serializer.endTag(null, "speed"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
serializer.endTag(null, "trkpt"); //$NON-NLS-1$
|
||||
}
|
||||
serializer.endTag(null, "trkseg"); //$NON-NLS-1$
|
||||
}
|
||||
serializer.endTag(null, "trk"); //$NON-NLS-1$
|
||||
|
||||
serializer.endTag(null, "gpx"); //$NON-NLS-1$
|
||||
serializer.flush();
|
||||
serializer.endDocument();
|
||||
}
|
||||
return null;
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Error saving gpx", e); //$NON-NLS-1$
|
||||
return ctx.getString(R.string.error_occurred_saving_gpx);
|
||||
} catch (IOException e) {
|
||||
log.error("Error saving gpx", e); //$NON-NLS-1$
|
||||
return ctx.getString(R.string.error_occurred_saving_gpx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class GPXFileResult {
|
||||
public ArrayList<List<Location>> locations = new ArrayList<List<Location>>();
|
||||
public ArrayList<WptPt> wayPoints = new ArrayList<WptPt>();
|
||||
// special case for cloudmate gpx : they discourage common schema
|
||||
// by using waypoint as track points and rtept are not very close to real way
|
||||
// such as wpt. However they provide additional information into gpx.
|
||||
public boolean cloudMadeFile;
|
||||
public String error;
|
||||
}
|
||||
|
||||
public static GPXFileResult loadGPXFile(Context ctx, File f){
|
||||
GPXFileResult res = new GPXFileResult();
|
||||
try {
|
||||
boolean cloudMade = false;
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$
|
||||
|
||||
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$
|
||||
cloudMade |= "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$
|
||||
(!cloudMade && 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 (tok == XmlPullParser.END_TAG) {
|
||||
if (parser.getName().equals("wpt") || //$NON-NLS-1$
|
||||
parser.getName().equals("trkpt") || (!cloudMade && parser.getName().equals("rtept"))) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (current != null) {
|
||||
if (parser.getName().equals("wpt") && !cloudMade) { //$NON-NLS-1$
|
||||
WptPt pt = new WptPt();
|
||||
pt.lat = current.getLatitude();
|
||||
pt.lon = current.getLongitude();
|
||||
pt.name = currentName;
|
||||
res.wayPoints.add(pt);
|
||||
} else {
|
||||
if (res.locations.isEmpty()) {
|
||||
res.locations.add(new ArrayList<Location>());
|
||||
}
|
||||
res.locations.get(res.locations.size() - 1).add(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (XmlPullParserException e) {
|
||||
log.error("Error reading gpx", e); //$NON-NLS-1$
|
||||
res.error = 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);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
|
@ -10,10 +10,12 @@ import java.util.LinkedHashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.OsmandSettings;
|
||||
import net.osmand.R;
|
||||
import net.osmand.ResourceManager;
|
||||
import net.osmand.activities.SavingTrackHelper.WptPt;
|
||||
import net.osmand.GPXUtilities.GPXFileResult;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.osm.MapUtils;
|
||||
import android.app.AlertDialog;
|
||||
|
@ -179,7 +181,7 @@ public class FavouritesActivity extends ListActivity {
|
|||
pt.name = p.name;
|
||||
wpt.add(pt);
|
||||
}
|
||||
if(SavingTrackHelper.saveToXMLFiles(f, wpt, this)){
|
||||
if(GPXUtilities.saveToXMLFiles(f, wpt, this)){
|
||||
Toast.makeText(this, MessageFormat.format(getString(R.string.fav_saved_sucessfully), f.getAbsolutePath()),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -196,9 +198,9 @@ public class FavouritesActivity extends ListActivity {
|
|||
existedPoints.add(fp.name);
|
||||
}
|
||||
}
|
||||
List<WptPt> points = new ArrayList<WptPt>();
|
||||
if(SavingTrackHelper.readWptPtFromFile(f, points, this)){
|
||||
for(WptPt p : points){
|
||||
GPXFileResult res = GPXUtilities.loadGPXFile(this, f);
|
||||
if (res.error == null) {
|
||||
for(WptPt p : res.wayPoints){
|
||||
if(!existedPoints.contains(p.name)){
|
||||
FavouritePoint fp = new FavouritePoint();
|
||||
fp.name = p.name;
|
||||
|
|
|
@ -4,12 +4,14 @@ import java.io.File;
|
|||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.AmenityIndexRepository;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.OsmandSettings;
|
||||
import net.osmand.PoiFilter;
|
||||
|
@ -18,6 +20,8 @@ import net.osmand.R;
|
|||
import net.osmand.ResourceManager;
|
||||
import net.osmand.SQLiteTileSource;
|
||||
import net.osmand.Version;
|
||||
import net.osmand.GPXUtilities.GPXFileResult;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.OsmandSettings.ApplicationMode;
|
||||
import net.osmand.activities.FavouritesActivity.FavouritePoint;
|
||||
import net.osmand.activities.FavouritesActivity.FavouritesDbHelper;
|
||||
|
@ -80,6 +84,7 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
|
@ -258,7 +263,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
|
||||
LatLon pointToNavigate = OsmandSettings.getPointToNavigate(this);
|
||||
|
||||
|
||||
// TODO how this situation could be ?
|
||||
if(!Algoritms.objectEquals(routingHelper.getFinalLocation(), pointToNavigate)){
|
||||
// there is no way how to clear mode. Only user can do : clear point to navigate, exit from app & set up new point.
|
||||
// that case help to not calculate route at all.
|
||||
|
@ -527,7 +532,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
} else {
|
||||
OsmandSettings.clearPointToNavigate(this);
|
||||
}
|
||||
routingHelper.setFinalAndCurrentLocation(point, null);
|
||||
routingHelper.setFinalAndCurrentLocation(point, null, routingHelper.getCurrentGPXRoute());
|
||||
if(point == null){
|
||||
routingHelper.setFollowingMode(false);
|
||||
OsmandSettings.setFollowingByRoute(MapActivity.this, false);
|
||||
|
@ -966,6 +971,9 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
navigateToPoint(new LatLon(mapView.getLatitude(), mapView.getLongitude()));
|
||||
}
|
||||
mapView.refreshMap();
|
||||
} else if (item.getItemId() == R.id.map_gpx_routing) {
|
||||
useGPXFileLayer(true, navigationLayer.getPointToNavigate());
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
@ -979,6 +987,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
return OsmandSettings.getApplicationMode(this);
|
||||
}
|
||||
|
||||
|
||||
protected void getDirections(final double lat, final double lon, boolean followEnabled){
|
||||
if(navigationLayer.getPointToNavigate() == null){
|
||||
Toast.makeText(this, R.string.mark_final_location_first, Toast.LENGTH_LONG).show();
|
||||
|
@ -1037,6 +1046,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
map.setLatitude(lat);
|
||||
map.setLongitude(lon);
|
||||
routingHelper.setAppMode(mode);
|
||||
OsmandSettings.setFollowingByRoute(MapActivity.this, false);
|
||||
routingHelper.setFollowingMode(false);
|
||||
routingHelper.setFinalAndCurrentLocation(navigationLayer.getPointToNavigate(), map);
|
||||
}
|
||||
|
@ -1063,9 +1073,10 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
location.setLongitude(lon);
|
||||
}
|
||||
routingHelper.setAppMode(mode);
|
||||
OsmandSettings.setFollowingByRoute(MapActivity.this, true);
|
||||
routingHelper.setFollowingMode(true);
|
||||
routingHelper.setFinalAndCurrentLocation(navigationLayer.getPointToNavigate(), location);
|
||||
OsmandSettings.setFollowingByRoute(MapActivity.this, true);
|
||||
|
||||
}
|
||||
};
|
||||
DialogInterface.OnClickListener showRoute = new DialogInterface.OnClickListener(){
|
||||
|
@ -1248,7 +1259,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
gpxLayer.clearCurrentGPX();
|
||||
} else {
|
||||
dialog.dismiss();
|
||||
selectGPXFileLayer();
|
||||
useGPXFileLayer(false, null);
|
||||
}
|
||||
} else if(item == routeInfoInd){
|
||||
routeInfoLayer.setVisible(isChecked);
|
||||
|
@ -1264,7 +1275,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
builder.show();
|
||||
}
|
||||
|
||||
private void selectGPXFileLayer() {
|
||||
private void useGPXFileLayer(final boolean useRouting, final LatLon endForRouting) {
|
||||
final List<String> list = new ArrayList<String>();
|
||||
final File dir = new File(Environment.getExternalStorageDirectory(), ResourceManager.APP_DIR + SavingTrackHelper.TRACKS_PATH);
|
||||
if (dir != null && dir.canRead()) {
|
||||
|
@ -1306,21 +1317,43 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
final String error = gpxLayer.showGPXFile(f);
|
||||
if (error != null) {
|
||||
Looper.prepare();
|
||||
final GPXFileResult res = GPXUtilities.loadGPXFile(MapActivity.this, f);
|
||||
if (res.error != null) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(MapActivity.this, error, Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(MapActivity.this, res.error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
dlg.dismiss();
|
||||
if(useRouting){
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
useGPXRouting(endForRouting, res);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
OsmandSettings.setShowingFavorites(MapActivity.this, true);
|
||||
List<FavouritePoint> pts = new ArrayList<FavouritePoint>();
|
||||
for(WptPt p : res.wayPoints){
|
||||
FavouritePoint pt = new FavouritePoint();
|
||||
pt.setLatitude(p.lat);
|
||||
pt.setLongitude(p.lon);
|
||||
pt.setName(p.name);
|
||||
pts.add(pt);
|
||||
}
|
||||
favoritesLayer.setAdditionalPoints(pts);
|
||||
gpxLayer.setTracks(res.locations);
|
||||
}
|
||||
mapView.refreshMap();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}, "Loading gpx").start(); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
|
@ -1329,6 +1362,45 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private void useGPXRouting(final LatLon endForRouting, final GPXFileResult res) {
|
||||
Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setItems(new String[]{getString(R.string.gpx_direct_route), getString(R.string.gpx_reverse_route)},
|
||||
new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
boolean reverse = which == 1;
|
||||
ArrayList<List<Location>> locations = res.locations;
|
||||
List<Location> l = new ArrayList<Location>();
|
||||
for(List<Location> s : locations){
|
||||
l.addAll(s);
|
||||
}
|
||||
if(reverse){
|
||||
Collections.reverse(l);
|
||||
}
|
||||
Location startForRouting = locationLayer.getLastKnownLocation();
|
||||
if(startForRouting == null && !l.isEmpty()){
|
||||
startForRouting = l.get(0);
|
||||
}
|
||||
LatLon endPoint = endForRouting;
|
||||
if(/*endForRouting == null && */!l.isEmpty()){
|
||||
LatLon point = new LatLon(l.get(l.size() - 1).getLatitude(), l.get(l.size() - 1).getLongitude());
|
||||
OsmandSettings.setPointToNavigate(MapActivity.this, point.getLatitude(), point.getLongitude());
|
||||
endPoint = point;
|
||||
navigationLayer.setPointToNavigate(point);
|
||||
}
|
||||
if(endForRouting != null){
|
||||
OsmandSettings.setFollowingByRoute(MapActivity.this, true);
|
||||
routingHelper.setFollowingMode(true);
|
||||
routingHelper.setFinalAndCurrentLocation(endPoint, startForRouting, l);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private void selectPOIFilterLayer(){
|
||||
final List<PoiFilter> userDefined = new ArrayList<PoiFilter>();
|
||||
|
|
|
@ -160,7 +160,8 @@ public class RouteProvider {
|
|||
|
||||
}
|
||||
|
||||
public RouteCalculationResult calculateRouteImpl(Location start, LatLon end, ApplicationMode mode, RouteService type, Context ctx){
|
||||
public RouteCalculationResult calculateRouteImpl(Location start, LatLon end, ApplicationMode mode, RouteService type, Context ctx,
|
||||
List<Location> gpxRoute){
|
||||
long time = System.currentTimeMillis();
|
||||
if (start != null && end != null) {
|
||||
if(log.isInfoEnabled()){
|
||||
|
@ -168,7 +169,36 @@ public class RouteProvider {
|
|||
}
|
||||
try {
|
||||
RouteCalculationResult res;
|
||||
if (type == RouteService.YOURS) {
|
||||
if(gpxRoute != null && !gpxRoute.isEmpty()){
|
||||
// get the closest point to start and to end
|
||||
float minDist = Integer.MAX_VALUE;
|
||||
int startI = 0;
|
||||
int endI = gpxRoute.size();
|
||||
if (start != null) {
|
||||
for (int i = 0; i < gpxRoute.size(); i++) {
|
||||
float d = gpxRoute.get(i).distanceTo(start);
|
||||
if (d < minDist) {
|
||||
startI = i;
|
||||
minDist = d;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
start = gpxRoute.get(0);
|
||||
}
|
||||
Location l = new Location("temp"); //$NON-NLS-1$
|
||||
l.setLatitude(end.getLatitude());
|
||||
l.setLongitude(end.getLongitude());
|
||||
minDist = Integer.MAX_VALUE;
|
||||
for (int i = 0; i < gpxRoute.size(); i++) {
|
||||
float d = gpxRoute.get(i).distanceTo(l);
|
||||
if (d < minDist) {
|
||||
endI = i + 1;
|
||||
minDist = d;
|
||||
}
|
||||
}
|
||||
res = new RouteCalculationResult(gpxRoute.subList(startI, endI), null, start, end, null);
|
||||
addMissingTurnsToRoute(res, start, end, mode, ctx);
|
||||
} else if (type == RouteService.YOURS) {
|
||||
res = findYOURSRoute(start, end, mode);
|
||||
addMissingTurnsToRoute(res, start, end, mode, ctx);
|
||||
} else {
|
||||
|
|
|
@ -40,6 +40,7 @@ public class RoutingHelper {
|
|||
|
||||
private boolean isFollowingMode = false;
|
||||
|
||||
private List<Location> currentGPXRoute = null;
|
||||
// instead of this properties RouteCalculationResult could be used
|
||||
private List<Location> routeNodes = new ArrayList<Location>();
|
||||
private List<RouteDirectionInfo> directionInfo = null;
|
||||
|
@ -93,12 +94,18 @@ public class RoutingHelper {
|
|||
this.isFollowingMode = isFollowingMode;
|
||||
}
|
||||
|
||||
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, Location currentLocation){
|
||||
|
||||
public void setFinalAndCurrentLocation(LatLon finalLocation, Location currentLocation){
|
||||
setFinalAndCurrentLocation(finalLocation, currentLocation, null);
|
||||
}
|
||||
|
||||
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, Location currentLocation, List<Location> gpxRoute){
|
||||
this.finalLocation = finalLocation;
|
||||
this.routeNodes.clear();
|
||||
listDistance = null;
|
||||
directionInfo = null;
|
||||
evalWaitInterval = 3000;
|
||||
currentGPXRoute = gpxRoute;
|
||||
for(IRouteInformationListener l : listeners){
|
||||
l.routeWasCancelled();
|
||||
}
|
||||
|
@ -107,6 +114,10 @@ public class RoutingHelper {
|
|||
|
||||
}
|
||||
|
||||
public List<Location> getCurrentGPXRoute() {
|
||||
return currentGPXRoute;
|
||||
}
|
||||
|
||||
public void setFinalLocation(LatLon finalLocation){
|
||||
setFinalAndCurrentLocation(finalLocation, getCurrentLocation());
|
||||
}
|
||||
|
@ -326,7 +337,7 @@ public class RoutingHelper {
|
|||
|
||||
lastFixedLocation = currentLocation;
|
||||
if(calculateRoute){
|
||||
calculateRoute(lastFixedLocation, finalLocation);
|
||||
calculateRoute(lastFixedLocation, finalLocation, currentGPXRoute);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,7 +433,7 @@ public class RoutingHelper {
|
|||
return 0;
|
||||
}
|
||||
|
||||
public void calculateRoute(final Location start, final LatLon end){
|
||||
public void calculateRoute(final Location start, final LatLon end, final List<Location> currentGPXRoute){
|
||||
final RouteService service = OsmandSettings.getRouterService(context);
|
||||
if(currentRunningJob == null){
|
||||
// do not evaluate very often
|
||||
|
@ -431,7 +442,7 @@ public class RoutingHelper {
|
|||
currentRunningJob = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode, service, context);
|
||||
RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode, service, context, currentGPXRoute);
|
||||
synchronized (RoutingHelper.this) {
|
||||
if (res.isCalculated()) {
|
||||
setNewRoute(res);
|
||||
|
@ -439,30 +450,31 @@ public class RoutingHelper {
|
|||
evalWaitInterval = 3000;
|
||||
} else {
|
||||
evalWaitInterval = evalWaitInterval * 4 / 3;
|
||||
if(evalWaitInterval > 120000){
|
||||
evalWaitInterval = 120000;
|
||||
if (evalWaitInterval > 120000) {
|
||||
evalWaitInterval = 120000;
|
||||
}
|
||||
}
|
||||
currentRunningJob = null;
|
||||
}
|
||||
|
||||
if (res.isCalculated()) {
|
||||
int[] dist = res.getListDistance();
|
||||
int l = dist != null && dist.length > 0 ? dist[0] : 0;
|
||||
showMessage(context.getString(R.string.new_route_calculated_dist) +" : "+ MapUtils.getFormattedDistance(l)); //$NON-NLS-1$
|
||||
if (uiActivity instanceof MapActivity) {
|
||||
// be aware that is non ui thread
|
||||
((MapActivity) uiActivity).getMapView().refreshMap();
|
||||
}
|
||||
} else {
|
||||
if (res.getErrorMessage() != null) {
|
||||
showMessage(context.getString(R.string.error_calculating_route)+" : " + res.getErrorMessage()); //$NON-NLS-1$
|
||||
} else if (res.getLocations() == null) {
|
||||
showMessage(context.getString(R.string.error_calculating_route_occured));
|
||||
} else {
|
||||
showMessage(context.getString(R.string.empty_route_calculated));
|
||||
}
|
||||
|
||||
if (res.isCalculated()) {
|
||||
int[] dist = res.getListDistance();
|
||||
int l = dist != null && dist.length > 0 ? dist[0] : 0;
|
||||
showMessage(context.getString(R.string.new_route_calculated_dist)
|
||||
+ " : " + MapUtils.getFormattedDistance(l)); //$NON-NLS-1$
|
||||
if (uiActivity instanceof MapActivity) {
|
||||
// be aware that is non ui thread
|
||||
((MapActivity) uiActivity).getMapView().refreshMap();
|
||||
}
|
||||
} else {
|
||||
if (res.getErrorMessage() != null) {
|
||||
showMessage(context.getString(R.string.error_calculating_route) + " : " + res.getErrorMessage()); //$NON-NLS-1$
|
||||
} else if (res.getLocations() == null) {
|
||||
showMessage(context.getString(R.string.error_calculating_route_occured));
|
||||
} else {
|
||||
showMessage(context.getString(R.string.empty_route_calculated));
|
||||
}
|
||||
}
|
||||
lastTimeEvaluatedRoute = System.currentTimeMillis();
|
||||
}
|
||||
}, "Calculating route"); //$NON-NLS-1$
|
||||
|
|
|
@ -1,25 +1,17 @@
|
|||
package net.osmand.activities;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.OsmandSettings;
|
||||
import net.osmand.R;
|
||||
import net.osmand.Version;
|
||||
import net.osmand.GPXUtilities.TrkPt;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
|
@ -27,8 +19,6 @@ import android.database.sqlite.SQLiteDatabase;
|
|||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.os.Environment;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.Xml;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class SavingTrackHelper extends SQLiteOpenHelper {
|
||||
public final static String TRACKS_PATH = "tracks"; //$NON-NLS-1$
|
||||
|
@ -45,7 +35,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
|
|||
|
||||
public final static Log log = LogUtil.getLog(SavingTrackHelper.class);
|
||||
|
||||
public final static String GPX_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$
|
||||
|
||||
|
||||
|
||||
private String updateScript;
|
||||
|
@ -69,166 +59,9 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
|
|||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
}
|
||||
|
||||
public static class TrkPt {
|
||||
public double lat;
|
||||
public double lon;
|
||||
public double ele;
|
||||
public double speed;
|
||||
public long time;
|
||||
}
|
||||
|
||||
public static class WptPt {
|
||||
public double lat;
|
||||
public double lon;
|
||||
public String name;
|
||||
}
|
||||
|
||||
public static boolean readWptPtFromFile(File fout, List<WptPt> readTo, Context ctx){
|
||||
try {
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
parser.setInput(new FileInputStream(fout), "UTF-8"); //$NON-NLS-1$
|
||||
int tok;
|
||||
WptPt current = null;
|
||||
while((tok=parser.next()) != XmlPullParser.END_DOCUMENT){
|
||||
if(tok == XmlPullParser.START_TAG){
|
||||
if(parser.getName().equals("wpt")){ //$NON-NLS-1$
|
||||
try {
|
||||
current = new WptPt();
|
||||
current.lat = Double.parseDouble(parser.getAttributeValue("", "lat")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
current.lon = 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){
|
||||
current.name = parser.getText();
|
||||
}
|
||||
}
|
||||
} else if(tok == XmlPullParser.END_TAG){
|
||||
if(parser.getName().equals("wpt")){ //$NON-NLS-1$
|
||||
if(current != null && current.name != null){
|
||||
readTo.add(current);
|
||||
}
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
log.error("Error loading gpx", e); //$NON-NLS-1$
|
||||
Toast.makeText(ctx, ctx.getString(R.string.error_occurred_loading_gpx), Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
} catch (XmlPullParserException e) {
|
||||
log.error("Error loading gpx", e); //$NON-NLS-1$
|
||||
Toast.makeText(ctx, ctx.getString(R.string.error_occurred_loading_gpx), Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static boolean saveToXMLFiles(File fout, List<WptPt> data, Context ctx ){
|
||||
try {
|
||||
FileOutputStream output = new FileOutputStream(fout);
|
||||
XmlSerializer serializer = Xml.newSerializer();
|
||||
serializer.setOutput(output, "UTF-8"); //$NON-NLS-1$
|
||||
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); //$NON-NLS-1$
|
||||
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$
|
||||
serializer.attribute("xmlns", "xsi", "http://www.w3.org/2001/XMLSchema-instance"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
serializer.attribute("xsi", "schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
serializer.attribute(null, "xmlns", "http://www.topografix.com/GPX/1/1"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
for (WptPt l : data) {
|
||||
serializer.startTag(null, "wpt"); //$NON-NLS-1$
|
||||
serializer.attribute(null, "lat", l.lat + ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
serializer.attribute(null, "lon", l.lon + ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
serializer.startTag(null, "name"); //$NON-NLS-1$
|
||||
serializer.text(l.name);
|
||||
serializer.endTag(null, "name"); //$NON-NLS-1$
|
||||
serializer.endTag(null, "wpt"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
serializer.endTag(null, "gpx"); //$NON-NLS-1$
|
||||
serializer.flush();
|
||||
serializer.endDocument();
|
||||
|
||||
return true;
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Error saving gpx", e); //$NON-NLS-1$
|
||||
Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
log.error("Error saving gpx", e); //$NON-NLS-1$
|
||||
Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String saveToXMLFiles(File dir, Map<String, List<List<TrkPt>>> data, Context ctx){
|
||||
SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT);
|
||||
try {
|
||||
for (String f : data.keySet()) {
|
||||
File fout = new File(dir, f + ".gpx"); //$NON-NLS-1$
|
||||
int ind = 1;
|
||||
while(fout.exists()){
|
||||
fout = new File(dir, f + "_"+(++ind)+".gpx"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
FileOutputStream output = new FileOutputStream(fout);
|
||||
XmlSerializer serializer = Xml.newSerializer();
|
||||
serializer.setOutput(output, "UTF-8"); //$NON-NLS-1$
|
||||
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); //$NON-NLS-1$
|
||||
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$
|
||||
serializer.attribute("xmlns", "xsi", "http://www.w3.org/2001/XMLSchema-instance"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
serializer.attribute("xsi", "schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
serializer.attribute(null, "xmlns", "http://www.topografix.com/GPX/1/1"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
serializer.startTag(null, "trk"); //$NON-NLS-1$
|
||||
for(List<TrkPt> l : data.get(f)){
|
||||
serializer.startTag(null, "trkseg"); //$NON-NLS-1$
|
||||
for(TrkPt p : l){
|
||||
serializer.startTag(null, "trkpt"); //$NON-NLS-1$
|
||||
serializer.attribute(null, "lat", p.lat+""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
serializer.attribute(null, "lon", p.lon+""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
serializer.startTag(null, "time"); //$NON-NLS-1$
|
||||
serializer.text(format.format(new Date(p.time)));
|
||||
serializer.endTag(null, "time"); //$NON-NLS-1$
|
||||
serializer.startTag(null, "ele"); //$NON-NLS-1$
|
||||
serializer.text(p.ele+""); //$NON-NLS-1$
|
||||
serializer.endTag(null, "ele"); //$NON-NLS-1$
|
||||
if (p.speed > 0) {
|
||||
serializer.startTag(null, "speed"); //$NON-NLS-1$
|
||||
serializer.text(p.speed + ""); //$NON-NLS-1$
|
||||
serializer.endTag(null, "speed"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
serializer.endTag(null, "trkpt"); //$NON-NLS-1$
|
||||
}
|
||||
serializer.endTag(null, "trkseg"); //$NON-NLS-1$
|
||||
}
|
||||
serializer.endTag(null, "trk"); //$NON-NLS-1$
|
||||
|
||||
serializer.endTag(null, "gpx"); //$NON-NLS-1$
|
||||
serializer.flush();
|
||||
serializer.endDocument();
|
||||
}
|
||||
return null;
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Error saving gpx", e); //$NON-NLS-1$
|
||||
return ctx.getString(R.string.error_occurred_saving_gpx);
|
||||
} catch (IOException e) {
|
||||
log.error("Error saving gpx", e); //$NON-NLS-1$
|
||||
return ctx.getString(R.string.error_occurred_saving_gpx);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasDataToSave(){
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
if(db != null){
|
||||
|
@ -295,7 +128,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
|
|||
} while (query.moveToNext());
|
||||
}
|
||||
query.close();
|
||||
String w = saveToXMLFiles(file, data, ctx);
|
||||
String w = GPXUtilities.saveToXMLFiles(file, data, ctx);
|
||||
if(w != null){
|
||||
warnings.add(w);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ public class FavoritesLayer implements OsmandMapLayer, ContextMenuLayer.IContext
|
|||
|
||||
private OsmandMapTileView view;
|
||||
private List<FavouritePoint> favouritePoints;
|
||||
private List<FavouritePoint> additionalPoints;
|
||||
private Rect pixRect = new Rect();
|
||||
private RectF tileRect = new RectF();
|
||||
private Path path;
|
||||
|
@ -84,6 +85,10 @@ public class FavoritesLayer implements OsmandMapLayer, ContextMenuLayer.IContext
|
|||
|
||||
}
|
||||
|
||||
public void setAdditionalPoints(List<FavouritePoint> additionalPoints) {
|
||||
this.additionalPoints = additionalPoints;
|
||||
}
|
||||
|
||||
public void reloadFavorites(Context ctx){
|
||||
FavouritesDbHelper helper = new FavouritesActivity.FavouritesDbHelper(ctx);
|
||||
favouritePoints = helper.getFavouritePoints();
|
||||
|
@ -118,6 +123,19 @@ public class FavoritesLayer implements OsmandMapLayer, ContextMenuLayer.IContext
|
|||
canvas.drawPath(pathDst, paintBlack);
|
||||
}
|
||||
}
|
||||
if(additionalPoints != null){
|
||||
for (FavouritePoint o : additionalPoints) {
|
||||
if (o.getLatitude() <= topLatitude && o.getLatitude() >= bottomLatitude && o.getLongitude() >= leftLongitude
|
||||
&& o.getLongitude() <= rightLongitude) {
|
||||
int x = view.getMapXForPoint(o.getLongitude());
|
||||
int y = view.getMapYForPoint(o.getLatitude());
|
||||
matrix.setTranslate(x, y);
|
||||
path.transform(matrix, pathDst);
|
||||
canvas.drawPath(pathDst, paint);
|
||||
canvas.drawPath(pathDst, paintBlack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,6 +161,19 @@ public class FavoritesLayer implements OsmandMapLayer, ContextMenuLayer.IContext
|
|||
}
|
||||
}
|
||||
}
|
||||
if (additionalPoints != null) {
|
||||
int ex = (int) point.x;
|
||||
int ey = (int) point.y;
|
||||
for (int i = 0; i < additionalPoints.size(); i++) {
|
||||
FavouritePoint n = additionalPoints.get(i);
|
||||
int x = view.getRotatedMapXForPoint(n.getLatitude(), n.getLongitude());
|
||||
int y = view.getRotatedMapYForPoint(n.getLatitude(), n.getLongitude());
|
||||
if (Math.abs(x - ex) <= r && Math.abs(y - ey) <= r) {
|
||||
r = Math.max(Math.abs(x - ex), Math.abs(y - ey));
|
||||
result = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,9 @@
|
|||
package net.osmand.views;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.R;
|
||||
import net.osmand.osm.MapUtils;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
|
@ -25,18 +15,17 @@ import android.graphics.Paint.Cap;
|
|||
import android.graphics.Paint.Join;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.location.Location;
|
||||
import android.util.Xml;
|
||||
|
||||
public class GPXLayer implements OsmandMapLayer {
|
||||
|
||||
private final static Log log = LogUtil.getLog(GPXLayer.class);
|
||||
|
||||
private OsmandMapTileView view;
|
||||
|
||||
private Rect boundsRect;
|
||||
private RectF tileRect;
|
||||
private List<Location> points = new ArrayList<Location>();
|
||||
private List<List<Location>> points = new ArrayList<List<Location>>();
|
||||
private Paint paint;
|
||||
private Paint paintPoint;
|
||||
|
||||
|
||||
private Path path;
|
||||
|
@ -55,6 +44,11 @@ public class GPXLayer implements OsmandMapLayer {
|
|||
paint.setAntiAlias(true);
|
||||
paint.setStrokeCap(Cap.ROUND);
|
||||
paint.setStrokeJoin(Join.ROUND);
|
||||
|
||||
|
||||
paintPoint = new Paint();
|
||||
paintPoint.setColor(Color.argb(190, 160, 10, 215));
|
||||
paintPoint.setStyle(Style.FILL_AND_STROKE);
|
||||
path = new Path();
|
||||
}
|
||||
|
||||
|
@ -67,51 +61,59 @@ public class GPXLayer implements OsmandMapLayer {
|
|||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
path.reset();
|
||||
|
||||
if(points.isEmpty()){
|
||||
return;
|
||||
}
|
||||
int w = view.getWidth();
|
||||
int h = view.getHeight();
|
||||
boundsRect = new Rect(-w / 2, -h / 2, 3 * w / 2, 3 * h / 2);
|
||||
boundsRect = new Rect(0, 0, w, h);
|
||||
view.calculateTileRectangle(boundsRect, view.getCenterPointX(), view.getCenterPointY(), view.getXTile(), view.getYTile(),
|
||||
tileRect);
|
||||
double topLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.top);
|
||||
double leftLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.left);
|
||||
double bottomLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.bottom);
|
||||
double rightLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.right);
|
||||
int startIndex = -1;
|
||||
int endIndex = -1;
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
Location ls = points.get(i);
|
||||
if(leftLongitude <= ls.getLongitude() && ls.getLongitude() <= rightLongitude &&
|
||||
bottomLatitude <= ls.getLatitude() && ls.getLatitude() <= topLatitude){
|
||||
if(startIndex == -1){
|
||||
startIndex = i > 0 ? i - 1 : i;
|
||||
|
||||
for (List<Location> l : points) {
|
||||
path.rewind();
|
||||
int startIndex = -1;
|
||||
int endIndex = -1;
|
||||
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
Location ls = l.get(i);
|
||||
if (startIndex == -1) {
|
||||
if (leftLongitude <= ls.getLongitude() && ls.getLongitude() <= rightLongitude && bottomLatitude <= ls.getLatitude()
|
||||
&& ls.getLatitude() <= topLatitude) {
|
||||
startIndex = i > 0 ? i - 1 : i;
|
||||
}
|
||||
} else if (!(leftLongitude <= ls.getLongitude() + 0.01 && ls.getLongitude() - 0.01 <= rightLongitude
|
||||
&& bottomLatitude <= ls.getLatitude() + 0.01 && ls.getLatitude() - 0.01 <= topLatitude)) {
|
||||
endIndex = i;
|
||||
// do not continue make method more efficient (because it calls in UI thread)
|
||||
// this break also has logical sense !
|
||||
break;
|
||||
}
|
||||
} else if(startIndex > 0){
|
||||
endIndex = i;
|
||||
// do not continue make method more efficient (because it calls in UI thread)
|
||||
// this break also has logical sense !
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(startIndex == -1){
|
||||
return;
|
||||
} else if(endIndex == -1){
|
||||
endIndex = points.size() - 1;
|
||||
if (startIndex == -1) {
|
||||
return;
|
||||
}
|
||||
if (endIndex == -1) {
|
||||
endIndex = l.size() - 1;
|
||||
}
|
||||
|
||||
int px = view.getMapXForPoint(l.get(startIndex).getLongitude());
|
||||
int py = view.getMapYForPoint(l.get(startIndex).getLatitude());
|
||||
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());
|
||||
path.lineTo(x, y);
|
||||
}
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
int px = view.getMapXForPoint(points.get(startIndex).getLongitude());
|
||||
int py = view.getMapYForPoint(points.get(startIndex).getLatitude());
|
||||
path.moveTo(px, py);
|
||||
for (int i = startIndex + 1; i <= endIndex; i++) {
|
||||
Location o = points.get(i);
|
||||
int x = view.getMapXForPoint(o.getLongitude());
|
||||
int y = view.getMapYForPoint(o.getLatitude());
|
||||
path.lineTo(x, y);
|
||||
}
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
|
||||
|
@ -119,51 +121,18 @@ public class GPXLayer implements OsmandMapLayer {
|
|||
return !points.isEmpty();
|
||||
}
|
||||
|
||||
public String showGPXFile(File f){
|
||||
try {
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
int tok;
|
||||
Location current = null;
|
||||
while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) {
|
||||
if(tok == XmlPullParser.START_TAG){
|
||||
// currently not distinguish different point represents all as a line
|
||||
if(parser.getName().equals("wpt") || parser.getName().equals("trkpt") /*|| parser.getName().equals("rtept")*/){ //$NON-NLS-1$ //$NON-NLS-2$
|
||||
try {
|
||||
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(tok == XmlPullParser.END_TAG){
|
||||
if(parser.getName().equals("wpt") || //$NON-NLS-1$
|
||||
parser.getName().equals("trkpt") /*|| parser.getName().equals("rtept")*/){ //$NON-NLS-1$
|
||||
if(current != null){
|
||||
locations.add(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.points = locations;
|
||||
} catch (XmlPullParserException e) {
|
||||
log.error("Error reading gpx", e); //$NON-NLS-1$
|
||||
return view.getContext().getString(R.string.error_reading_gpx);
|
||||
} catch (IOException e) {
|
||||
log.error("Error reading gpx", e); //$NON-NLS-1$
|
||||
return view.getContext().getString(R.string.error_reading_gpx);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clearCurrentGPX(){
|
||||
points.clear();
|
||||
}
|
||||
|
||||
public void setTracks(List<List<Location>> tracks){
|
||||
if(tracks == null){
|
||||
clearCurrentGPX();
|
||||
} else {
|
||||
points = tracks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,7 +31,6 @@ import alice.tuprolog.Var;
|
|||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Environment;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class CommandPlayer {
|
||||
|
||||
|
|
Loading…
Reference in a new issue