Merge branch 'master' into plan_route_exit_wo_saving
This commit is contained in:
commit
0b4fb55b44
20 changed files with 296 additions and 185 deletions
|
@ -2,6 +2,6 @@
|
||||||
Major contributors / developers listed here https://github.com/osmandapp/osmandapp.github.io/blob/master/website/help/about.html#L8
|
Major contributors / developers listed here https://github.com/osmandapp/osmandapp.github.io/blob/master/website/help/about.html#L8
|
||||||
|
|
||||||
### Other Pull requests
|
### Other Pull requests
|
||||||
Copyright © All authors of translations and pull requests could be found in commits history:
|
Copyright © All authors of translations and pull requests can be found in the commit history:
|
||||||
- Translations are under special “contributor” name ‘weblate’
|
- Translations are under special “contributor” name ‘weblate’
|
||||||
- Pull requests have two committers, first is original contributor and second is project maintainer
|
- Pull requests have two committers: first is original contributor, and second is project maintainer
|
||||||
|
|
|
@ -1,26 +1,32 @@
|
||||||
Before entering an issue, please read the information below.
|
Before entering an issue, please read the information below.
|
||||||
|
|
||||||
```GitHub is a main development tool for developers. There are hundreds requests a month and there are only few developers. So by opening an issue, please know that your issue will be sent out to all developers and acknowledge that it could be closed without explanation or with a brief message. Comments on the closed issues are also sent to all developers, so you will definitely will be heard. However, there is no guarantee that a developer will pick up the issue to work on it.```
|
```GitHub is our main development tool for our developers. There are hundreds of requests a month and there are relatively few developers.
|
||||||
|
So by opening an issue, please know that your issue will be sent out to all developers and acknowledge that it could be closed without explanation or with just a brief message.
|
||||||
|
Comments on the closed issues are also sent to all developers, so you will definitely will be heard.
|
||||||
|
However, there is no guarantee that a developer will pick up the issue to work on it.```
|
||||||
|
|
||||||
In case you are not sure to open issue or not, please send your request to support support@osmand.net. For **general questions** about OsmAnd, please use the [Google group](https://groups.google.com/forum/#!forum/osmand).
|
In case you aren't sure whether to open an issue or not, please send your request to support@osmand.net.
|
||||||
|
For **general questions** about OsmAnd, please use the [Google group](https://groups.google.com/forum/#!forum/osmand).
|
||||||
|
|
||||||
Please be sure to have read our [FAQ](http://osmand.net/help-online) before creating an issue here. (Also, tell us in Google Groups when the FAQ is wrong or outdated.)
|
Please be sure to read our [FAQ](https://osmand.net/help-online) before creating an issue here.
|
||||||
|
(Also, tell us in Google Groups when the FAQ is wrong or outdated.)
|
||||||
|
|
||||||
The best way to get help about an OsmAnd issue is to create a valid and detailed issue content.
|
The best way to get help about an OsmAnd issue is to create a valid and detailed issue.
|
||||||
Please give us the following information so that we can try to **reproduce** your issue:
|
Please give us the following information so that we can try to **reproduce** your issue:
|
||||||
|
|
||||||
What version of OsmAnd are you using, on what device and Android/iOS version?
|
What version of OsmAnd are you using, and on what device and Android/iOS version?
|
||||||
|
|
||||||
Do you use the offline maps offered within the OsmAnd app for download, or online (tile / raster) maps?
|
Do you use the offline maps offered within the OsmAnd app for download, or the online (tile / raster) maps?
|
||||||
|
|
||||||
If you have an issue related to offline maps, tell us the exact name of the map file where the issue occurs, and its edition date.
|
If you have an issue related to offline maps, tell us the exact name of the map file where the issue occurs and its edition date.
|
||||||
|
|
||||||
__*In case of wrong routing:*__
|
__*In case of wrong routing:*__
|
||||||
|
|
||||||
Tell us whether you have used OsmAnd's in-app offline routing, or any online routing provider like YOURS, OpenRouteService or OSRM.
|
Tell us whether you have used OsmAnd's in-app offline routing or any online routing provider like YOURS, OpenRouteService, OSRM, etc.
|
||||||
|
|
||||||
What routing profile is chosen in OsmAnd app? (car, bike, pedestrian, fastest or shortest)
|
What routing profile is chosen in the OsmAnd app? (car, bike, pedestrian, fastest or shortest, etc.)
|
||||||
|
|
||||||
Please specify as exactly as possible the start and end point of your route by telling us city name and street name so that we can find it via in-app address search easily. Also, a permalink from openstreetmap.org can be helpful.
|
Please specify (as exact as possible) the start and end point of your route by telling us the city and street name so that we can find it via the in-app address search easily.
|
||||||
|
Also, a permalink from [openstreetmap.org](https://www.openstreetmap.org/) can be helpful.
|
||||||
|
|
||||||
Tell us your expected routing, and how OsmAnd routes, or add screenshots here.
|
Tell us your expected routing and how OsmAnd routes, or add screenshots here.
|
||||||
|
|
70
LICENSE
70
LICENSE
|
@ -1,11 +1,11 @@
|
||||||
|
|
||||||
OsmAnd – OSM Automated Navigation Directions – navigation software based on OpenStreetMap.
|
OsmAnd – OSM Automated Navigation Directions – navigation software based on OpenStreetMap.
|
||||||
Copyright © 2010–2018 OsmAnd BV (Amstelveen, Netherlands - KvK 62066714, BTW 854627704B01).
|
Copyright © 2010–2020 OsmAnd BV (Amstelveen, Netherlands - KvK 62066714, BTW 854627704B01).
|
||||||
|
|
||||||
The code in this repository is covered by *GPLv3* (for code) and the artwork is covered by [ CC-BY-NC-ND 4.0 ](https://creativecommons.org/licenses/by-nc-nd/4.0/) (for artwork), except some 3rd party libs and resources.
|
The code in this repository is covered by *GPLv3* (for code) and the artwork is covered by [CC-BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/) (for artwork), except for some third-party libraries and resources.
|
||||||
ATTENTION: please be aware that some artwork has proprietary license.
|
ATTENTION: Please be aware that some artwork uses a proprietary license.
|
||||||
|
|
||||||
Main AUTHORS (more detailed list in AUTHORS):
|
Main AUTHORS (more detailed list in AUTHORS.md):
|
||||||
Victor Shcherb – all parts of the project, originator
|
Victor Shcherb – all parts of the project, originator
|
||||||
Alexey Pelykh – rendering and core parts
|
Alexey Pelykh – rendering and core parts
|
||||||
Hardy Mueller – main parts of the project, mostly rendering, UI interaction design
|
Hardy Mueller – main parts of the project, mostly rendering, UI interaction design
|
||||||
|
@ -30,33 +30,33 @@
|
||||||
* Source code in main repositories is covered by GPLv3 (license exceptions below):
|
* Source code in main repositories is covered by GPLv3 (license exceptions below):
|
||||||
- https://github.com/osmandapp/Osmand/tree/master/OsmAnd
|
- https://github.com/osmandapp/Osmand/tree/master/OsmAnd
|
||||||
- https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java
|
- https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java
|
||||||
- https://github.com/osmandapp/Osmand-core/tree/legacy_core
|
- https://github.com/osmandapp/OsmAnd-core/tree/legacy_core
|
||||||
- https://github.com/osmandapp/Osmand-core/
|
- https://github.com/osmandapp/OsmAnd-core
|
||||||
- https://github.com/osmandapp/OsmAnd-misc
|
- https://github.com/osmandapp/OsmAnd-misc
|
||||||
- https://github.com/osmandapp/OsmAnd-tools
|
- https://github.com/osmandapp/OsmAnd-tools
|
||||||
- https://github.com/osmandapp/OsmAnd-resources
|
- https://github.com/osmandapp/OsmAnd-resources
|
||||||
|
|
||||||
* UI Design and UX work, such as layout, icons is covered by CC-BY-NC-ND
|
* UI Design and UX work, such as layout and icons, are covered by [CC-BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/)
|
||||||
- https://github.com/osmandapp/Osmand/tree/master/OsmAnd/res and others
|
- https://github.com/osmandapp/Osmand/tree/master/OsmAnd/res and others
|
||||||
Restriction to UI/UX CC-BY-NC-ND:
|
Restriction to UI/UX CC-BY-NC-ND:
|
||||||
* Publishing applications using the OsmAnd UI/UX code to Google Play, Amazon Market or Apple Store must be done with written permission*
|
* Publishing applications using the OsmAnd UI/UX code to Google Play, Amazon Market, or Apple Store must be done with written permission.*
|
||||||
|
|
||||||
|
|
||||||
* Map icons are taken from sjjb and some are drawn and distributed under Public Domain (except icons8)
|
* Map icons are taken from sjjb and some are drawn and distributed under Public Domain (except icons8)
|
||||||
- https://github.com/osmandapp/OsmAnd-resources/tree/master/icons/svg
|
- https://github.com/osmandapp/OsmAnd-resources/tree/master/icons/svg
|
||||||
- some icons are from http://osm-icons.org/wiki/Icons (CC-0 by Markus59, CC BY-SA 2.0)
|
- some icons are from http://osm-icons.org/wiki/Icons (CC-0 by Markus59, CC BY-SA 2.0)
|
||||||
|
|
||||||
* Integration with Qt library in (https://github.com/osmandapp/Osmand-core/) - dynamic linking
|
* Integration with Qt library in (https://github.com/osmandapp/OsmAnd-core) - dynamic linking
|
||||||
- LGPL (http://www.qt.io/qt-licensing-terms/)
|
- LGPL (https://www.qt.io/terms-conditions/)
|
||||||
|
|
||||||
* Map icons and their derived primitives are covered by proprietary license:
|
* Map icons and their derived primitives are covered by a proprietary license:
|
||||||
- © icons8.com (https://github.com/osmandapp/OsmAnd-resources/tree/master/icons/svg/icons8)
|
- © icons8.com (https://github.com/osmandapp/OsmAnd-resources/tree/master/icons/svg/icons8)
|
||||||
|
|
||||||
* Generated voice files from TTS files are covered by proprietary license:
|
* Generated voice files from TTS files are covered by a proprietary license:
|
||||||
- Voice files (https://github.com/osmandapp/OsmAnd-resources/tree/master/voice)
|
- Voice files (https://github.com/osmandapp/OsmAnd-resources/tree/master/voice)
|
||||||
|
|
||||||
* Fonts (https://github.com/osmandapp/OsmAnd-resources/tree/master/rendering_styles/fonts)
|
* Fonts (https://github.com/osmandapp/OsmAnd-resources/tree/master/rendering_styles/fonts)
|
||||||
- Google Fonts (Apache License 2)
|
- Google Fonts (Apache License 2.0)
|
||||||
|
|
||||||
* Map icons (Mapnik):
|
* Map icons (Mapnik):
|
||||||
- Open-SVG-Map-Icons - Public Domain
|
- Open-SVG-Map-Icons - Public Domain
|
||||||
|
@ -65,49 +65,27 @@
|
||||||
- SherlockBar - Apache License - https://github.com/osmandapp/Osmand/tree/master/SherlockBar (https://github.com/JakeWharton/ActionBarSherlock/blob/master/LICENSE.txt)
|
- SherlockBar - Apache License - https://github.com/osmandapp/Osmand/tree/master/SherlockBar (https://github.com/JakeWharton/ActionBarSherlock/blob/master/LICENSE.txt)
|
||||||
|
|
||||||
* Patched libraries:
|
* Patched libraries:
|
||||||
- Protobuf - New BSD License (patches - https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/protobuf-src, https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/protobuf)
|
- Protobuf - New BSD License (patches - https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/src/main/java/com/google/protobuf, https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/protobuf)
|
||||||
- Expat - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/expat)
|
|
||||||
- Freetype - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/freetype)
|
|
||||||
- Giflib - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/giflib)
|
|
||||||
- Jpeg - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/jpeg)
|
- Jpeg - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/jpeg)
|
||||||
- Libpng - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/libpng)
|
|
||||||
- Skia - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/skia)
|
- Skia - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/skia)
|
||||||
- ZLib - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/zlib)
|
- android-openmap-framework - (https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/src/main/java/com/jwetherell/openmap/common)
|
||||||
|
- mapbox-vector-tile - (https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/src/main/java/com/wdtinc/mapbox_vector_tile)
|
||||||
|
|
||||||
* 3rd party libraries present in the libs folder (https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/libs):
|
* 3rd party libraries present in the libs folder (https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/libs):
|
||||||
- bzip2-20090327.jar Bzip2 - Apache License
|
|
||||||
- commons-logging-1.1.1.jar - Apache License
|
|
||||||
- gnu-trove-osmand.jar GNU trove - LGPL
|
- gnu-trove-osmand.jar GNU trove - LGPL
|
||||||
- icu4j-49_1.jar - ICU license (http://source.icu-project.org/repos/icu/icu/trunk/license.html)
|
- icu4j-49_1_patched.jar - ICU license (https://home.unicode.org/basic-info/projects/#/icu/icu/trunk/license.html)
|
||||||
- json-20090211.jar - BSD alike (http://www.json.org/license.html)
|
|
||||||
- junidecode-0.1.jar - BSD-4-Clause-UC (http://sourceforge.net/projects/junidecode/)
|
|
||||||
- kxml2-2.3.0.jar - BSD license (http://www.kxml.org/)
|
|
||||||
- tuprolog.jar - LGPL (http://apice.unibo.it/xwiki/bin/view/Tuprolog/)
|
|
||||||
- OpenMap framework - Apache License (https://code.google.com/p/android-openmap-framework/)
|
|
||||||
|
|
||||||
* Pull-requests and translations:
|
* Pull-requests and translations:
|
||||||
- All pull requests are accepted under MIT License (most honorable contributors are mentioned in AUTHORS list)
|
- All pull requests are accepted under MIT License (most honorable contributors are mentioned in AUTHORS list).
|
||||||
|
|
||||||
* Libraries not used in final product (https://github.com/osmandapp/OsmAnd-tools/tree/master/OsmAndMapCreator/libi)
|
|
||||||
- Ant libraries - (tools) https://github.com/osmandapp/Osmand/tree/master/OsmAnd/ant-lib
|
|
||||||
- jleveldb-v01.jar
|
|
||||||
- jsch-20120101.jar
|
|
||||||
- junit-4.10.jar
|
|
||||||
- mysql-connector-java-5.1.18-bin.jar
|
|
||||||
- sqlite-jdbc-3.7.6.3-20110609.081603-3.jar
|
|
||||||
- h2-latest.jar
|
|
||||||
|
|
||||||
* Special tools for new rendering (GPLv3)
|
* Special tools for new rendering (GPLv3)
|
||||||
- https://github.com/osmandapp/OsmAnd-tools/tree/master/obf-inspector
|
- https://github.com/osmandapp/OsmAnd-tools
|
||||||
- https://github.com/osmandapp/OsmAnd-tools/tree/master/obf-verifier
|
|
||||||
- https://github.com/osmandapp/OsmAnd-tools/tree/master/route-tester
|
|
||||||
|
|
||||||
* OSM data 2014
|
* OSM data
|
||||||
- Extracts - https://github.com/osmandapp/OsmAnd-misc/blob/master/osm-planet/osm-data/
|
- Extracts - https://github.com/osmandapp/OsmAnd-misc/tree/master/osm-planet/osm-data
|
||||||
|
|
||||||
* Data files
|
* Data files
|
||||||
- Country boundaries - https://github.com/osmandapp/OsmAnd-misc/tree/master/osm-planet/geo-polygons © by Geofabrik - data free to use
|
- Country boundaries - https://github.com/osmandapp/OsmAnd-misc/tree/master/osm-planet/polygons © by Geofabrik - data free to use
|
||||||
- Country boundaries - https://github.com/osmandapp/OsmAnd-misc/tree/master/osm-planet/gislab-polygons © by http://be.gis-lab.info - data free to use
|
|
||||||
|
|
||||||
* Subway icons
|
* Subway icons
|
||||||
- Moscow: Art Lebedev Studio (http://www.artlebedev.ru/everything/metro/logo/) [Public domain], undefined
|
- Moscow: Art Lebedev Studio (http://www.artlebedev.ru/everything/metro/logo/) [Public domain], undefined
|
||||||
|
@ -119,7 +97,7 @@
|
||||||
- Kazan: «Kazan-metro-Logo» (Россиянин) - own work. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:Kazan-metro-Logo.svg#/media/File:Kazan-metro-Logo.svg
|
- Kazan: «Kazan-metro-Logo» (Россиянин) - own work. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:Kazan-metro-Logo.svg#/media/File:Kazan-metro-Logo.svg
|
||||||
- Tbilisi: «Metro Tbilisi logo» (Carnby) - own work. Under CC BY-SA 3.0 license from site - https://commons.wikimedia.org/wiki/File:Metro_Tbilisi_logo.svg#/media/File:Metro_Tbilisi_logo.svg
|
- Tbilisi: «Metro Tbilisi logo» (Carnby) - own work. Under CC BY-SA 3.0 license from site - https://commons.wikimedia.org/wiki/File:Metro_Tbilisi_logo.svg#/media/File:Metro_Tbilisi_logo.svg
|
||||||
- Minsk: «Minsk metro logo» (Skip405) - own work. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:Minsk_metro_logo.svg#/media/File:Minsk_metro_logo.svg
|
- Minsk: «Minsk metro logo» (Skip405) - own work. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:Minsk_metro_logo.svg#/media/File:Minsk_metro_logo.svg
|
||||||
- Nizhny Novgorod: «NNMetro» (AlexTref871) - own work. This vector image includes elements borrowed from another image: Coat of arms of Nizhny Novgorod Region.svg.. Under Public domain Commons licensefrom the site - https://commons.wikimedia.org/wiki/File:NNMetro.svg#/media/File:NNMetro.svg
|
- Nizhny Novgorod: «NNMetro» (AlexTref871) - own work. This vector image includes elements borrowed from another image: Coat of arms of Nizhny Novgorod Region.svg.. Under Public domain Commons licensefrom the site - https://commons.wikimedia.org/wiki/File:NNMetro.svg#/media/File:NNMetro.svg
|
||||||
- Novosibirsk: «Logo-Nsk-Metro» (AlexTref871) - own work. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:Logo-Nsk-Metro.svg#/media/File:Logo-Nsk-Metro.svg
|
- Novosibirsk: «Logo-Nsk-Metro» (AlexTref871) - own work. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:Logo-Nsk-Metro.svg#/media/File:Logo-Nsk-Metro.svg
|
||||||
- Yekaterinburg: «Ekt-metro-logo-01» (AlexTref871) - own work. Under CC BY-SA 4.0 license from site - https://commons.wikimedia.org/wiki/File:Ekt-metro-logo-01.svg#/media/File:Ekt-metro-logo-01.svg
|
- Yekaterinburg: «Ekt-metro-logo-01» (AlexTref871) - own work. Under CC BY-SA 4.0 license from site - https://commons.wikimedia.org/wiki/File:Ekt-metro-logo-01.svg#/media/File:Ekt-metro-logo-01.svg
|
||||||
- New York: «MTA New York City Subway logo» (Metropolitan Transportation Authority) - http://mta.info/. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:MTA_New_York_City_Subway_logo.svg#/media/File:MTA_New_York_City_Subway_logo.svg
|
- New York: «MTA New York City Subway logo» (Metropolitan Transportation Authority) - http://mta.info/. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:MTA_New_York_City_Subway_logo.svg#/media/File:MTA_New_York_City_Subway_logo.svg
|
||||||
|
@ -152,7 +130,7 @@
|
||||||
- Los Angeles: "Lametro" by Los Angeles County Metropolitan Transportation Authority. Original uploader was Cheeselouise at en.wikipedia - Metro materials at http://www.metro.net/riding_metro/pocket_guide_cambodian_printers.pdf. Licensed under Public Domain via Commons - https://commons.wikimedia.org/wiki/File:Lametro.svg#/media/File:Lametro.svg
|
- Los Angeles: "Lametro" by Los Angeles County Metropolitan Transportation Authority. Original uploader was Cheeselouise at en.wikipedia - Metro materials at http://www.metro.net/riding_metro/pocket_guide_cambodian_printers.pdf. Licensed under Public Domain via Commons - https://commons.wikimedia.org/wiki/File:Lametro.svg#/media/File:Lametro.svg
|
||||||
|
|
||||||
* Depth maps
|
* Depth maps
|
||||||
- The GEBCO_2014 Grid, version 20150318, www.gebco.net
|
- The GEBCO_2020 Grid, www.gebco.net
|
||||||
- U.S. Bureau of Ocean Energy Management (24 may 2017,12m per pixel)
|
- U.S. Bureau of Ocean Energy Management (24 may 2017,12m per pixel)
|
||||||
- South_Padre_Island_DEM_4133: Grothe, P.G., L.A. Taylor, B.W. Eakins, K.S. Carignan, D.Z. Friday, and M. Love, 2012. Digital Elevation Models of South Padre Island, Texas: Procedures, Data Sources and Analysis, NOAA National Geophysical Data Center technical report, Boulder, CO, 15 pp.
|
- South_Padre_Island_DEM_4133: Grothe, P.G., L.A. Taylor, B.W. Eakins, K.S. Carignan, D.Z. Friday, and M. Love, 2012. Digital Elevation Models of South Padre Island, Texas: Procedures, Data Sources and Analysis, NOAA National Geophysical Data Center technical report, Boulder, CO, 15 pp.
|
||||||
- Corpus_Christi_DEM_1035: Taylor, L.A., B.W. Eakins, K.S. Carignan, R.R. Warnken, T. Sazonova, and D.C. Schoolcraft, 2008. Digital Elevation Model of Corpus Christi, Texas: Procedures, Data Sources and Analysis, NOAA Technical Memorandum NESDIS NGDC-11, National Geophysical Data Center, Boulder, CO, 19 pp.
|
- Corpus_Christi_DEM_1035: Taylor, L.A., B.W. Eakins, K.S. Carignan, R.R. Warnken, T. Sazonova, and D.C. Schoolcraft, 2008. Digital Elevation Model of Corpus Christi, Texas: Procedures, Data Sources and Analysis, NOAA Technical Memorandum NESDIS NGDC-11, National Geophysical Data Center, Boulder, CO, 19 pp.
|
||||||
|
|
|
@ -32,6 +32,8 @@ public interface ITileSource {
|
||||||
|
|
||||||
public String getReferer();
|
public String getReferer();
|
||||||
|
|
||||||
|
public String getUserAgent();
|
||||||
|
|
||||||
public void deleteTiles(String path);
|
public void deleteTiles(String path);
|
||||||
|
|
||||||
public int getAvgSize();
|
public int getAvgSize();
|
||||||
|
|
|
@ -90,6 +90,7 @@ public class MapTileDownloader {
|
||||||
public final int yTile;
|
public final int yTile;
|
||||||
public String url;
|
public String url;
|
||||||
public String referer = null;
|
public String referer = null;
|
||||||
|
public String userAgent = null;
|
||||||
public boolean error;
|
public boolean error;
|
||||||
|
|
||||||
public DownloadRequest(String url, File fileToSave, int xTile, int yTile, int zoom) {
|
public DownloadRequest(String url, File fileToSave, int xTile, int yTile, int zoom) {
|
||||||
|
@ -266,7 +267,7 @@ public class MapTileDownloader {
|
||||||
request.setError(false);
|
request.setError(false);
|
||||||
try {
|
try {
|
||||||
URLConnection connection = NetworkUtils.getHttpURLConnection(request.url);
|
URLConnection connection = NetworkUtils.getHttpURLConnection(request.url);
|
||||||
connection.setRequestProperty("User-Agent", USER_AGENT); //$NON-NLS-1$
|
connection.setRequestProperty("User-Agent", Algorithms.isEmpty(request.userAgent) ? USER_AGENT : request.userAgent); //$NON-NLS-1$
|
||||||
if (request.referer != null)
|
if (request.referer != null)
|
||||||
connection.setRequestProperty("Referer", request.referer); //$NON-NLS-1$
|
connection.setRequestProperty("Referer", request.referer); //$NON-NLS-1$
|
||||||
connection.setConnectTimeout(CONNECTION_TIMEOUT);
|
connection.setConnectTimeout(CONNECTION_TIMEOUT);
|
||||||
|
|
|
@ -68,6 +68,7 @@ public class TileSourceManager {
|
||||||
private String[] randomsArray;
|
private String[] randomsArray;
|
||||||
private String rule;
|
private String rule;
|
||||||
private String referer;
|
private String referer;
|
||||||
|
private String userAgent;
|
||||||
private boolean hidden; // if hidden in configure map settings, for example mapillary sources
|
private boolean hidden; // if hidden in configure map settings, for example mapillary sources
|
||||||
|
|
||||||
private boolean isRuleAcceptable = true;
|
private boolean isRuleAcceptable = true;
|
||||||
|
@ -261,6 +262,14 @@ public class TileSourceManager {
|
||||||
this.referer = referer;
|
this.referer = referer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUserAgent() {
|
||||||
|
return userAgent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserAgent(String userAgent) {
|
||||||
|
this.userAgent = userAgent;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTileSize() {
|
public int getTileSize() {
|
||||||
return tileSize;
|
return tileSize;
|
||||||
|
@ -484,6 +493,9 @@ public class TileSourceManager {
|
||||||
if (!Algorithms.isEmpty(tm.getReferer())) {
|
if (!Algorithms.isEmpty(tm.getReferer())) {
|
||||||
properties.put("referer", tm.getReferer());
|
properties.put("referer", tm.getReferer());
|
||||||
}
|
}
|
||||||
|
if (!Algorithms.isEmpty(tm.getUserAgent())) {
|
||||||
|
properties.put("user_agent", tm.getUserAgent());
|
||||||
|
}
|
||||||
|
|
||||||
properties.put("ext", tm.getTileFormat());
|
properties.put("ext", tm.getTileFormat());
|
||||||
properties.put("min_zoom", tm.getMinimumZoomSupported() + "");
|
properties.put("min_zoom", tm.getMinimumZoomSupported() + "");
|
||||||
|
@ -708,6 +720,12 @@ public class TileSourceManager {
|
||||||
}
|
}
|
||||||
String randoms = attributes.get("randoms");
|
String randoms = attributes.get("randoms");
|
||||||
TileSourceTemplate templ = new TileSourceTemplate(name, urlTemplate, ext, maxZoom, minZoom, tileSize, bitDensity, avgTileSize);
|
TileSourceTemplate templ = new TileSourceTemplate(name, urlTemplate, ext, maxZoom, minZoom, tileSize, bitDensity, avgTileSize);
|
||||||
|
if (attributes.get("referer") != null) {
|
||||||
|
templ.setReferer(attributes.get("referer"));
|
||||||
|
}
|
||||||
|
if (attributes.get("user_agent") != null) {
|
||||||
|
templ.setUserAgent(attributes.get("user_agent"));
|
||||||
|
}
|
||||||
if(expirationTime >= 0) {
|
if(expirationTime >= 0) {
|
||||||
templ.setExpirationTimeMinutes(expirationTime);
|
templ.setExpirationTimeMinutes(expirationTime);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ public class SQLiteTileSource implements ITileSource {
|
||||||
private static final String ELLIPSOID = "ellipsoid";
|
private static final String ELLIPSOID = "ellipsoid";
|
||||||
private static final String INVERTED_Y = "inverted_y";
|
private static final String INVERTED_Y = "inverted_y";
|
||||||
private static final String REFERER = "referer";
|
private static final String REFERER = "referer";
|
||||||
|
private static final String USER_AGENT = "useragent";
|
||||||
private static final String TIME_COLUMN = "timecolumn";
|
private static final String TIME_COLUMN = "timecolumn";
|
||||||
private static final String EXPIRE_MINUTES = "expireminutes";
|
private static final String EXPIRE_MINUTES = "expireminutes";
|
||||||
private static final String RULE = "rule";
|
private static final String RULE = "rule";
|
||||||
|
@ -62,6 +63,7 @@ public class SQLiteTileSource implements ITileSource {
|
||||||
private String[] randomsArray;
|
private String[] randomsArray;
|
||||||
private String rule = null;
|
private String rule = null;
|
||||||
private String referer = null;
|
private String referer = null;
|
||||||
|
private String userAgent = null;
|
||||||
|
|
||||||
int tileSize = 256;
|
int tileSize = 256;
|
||||||
boolean tileSizeSpecified = false;
|
boolean tileSizeSpecified = false;
|
||||||
|
@ -93,7 +95,7 @@ public class SQLiteTileSource implements ITileSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SQLiteTileSource(OsmandApplication ctx, String name, int minZoom, int maxZoom, String urlTemplate,
|
public SQLiteTileSource(OsmandApplication ctx, String name, int minZoom, int maxZoom, String urlTemplate,
|
||||||
String randoms, boolean isEllipsoid, boolean invertedY, String referer,
|
String randoms, boolean isEllipsoid, boolean invertedY, String referer, String userAgent,
|
||||||
boolean timeSupported, long expirationTimeMillis, boolean inversiveZoom, String rule) {
|
boolean timeSupported, long expirationTimeMillis, boolean inversiveZoom, String rule) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -104,6 +106,7 @@ public class SQLiteTileSource implements ITileSource {
|
||||||
this.expirationTimeMillis = expirationTimeMillis;
|
this.expirationTimeMillis = expirationTimeMillis;
|
||||||
this.randoms = randoms;
|
this.randoms = randoms;
|
||||||
this.referer = referer;
|
this.referer = referer;
|
||||||
|
this.userAgent = userAgent;
|
||||||
this.rule = rule;
|
this.rule = rule;
|
||||||
this.invertedY = invertedY;
|
this.invertedY = invertedY;
|
||||||
this.timeSupported = timeSupported;
|
this.timeSupported = timeSupported;
|
||||||
|
@ -120,6 +123,7 @@ public class SQLiteTileSource implements ITileSource {
|
||||||
this.expirationTimeMillis = tileSource.getExpirationTimeMillis();
|
this.expirationTimeMillis = tileSource.getExpirationTimeMillis();
|
||||||
this.randoms = tileSource.getRandoms();
|
this.randoms = tileSource.getRandoms();
|
||||||
this.referer = tileSource.getReferer();
|
this.referer = tileSource.getReferer();
|
||||||
|
this.userAgent = tileSource.getUserAgent();
|
||||||
this.invertedY = tileSource.isInvertedYTile();
|
this.invertedY = tileSource.isInvertedYTile();
|
||||||
this.timeSupported = tileSource.isTimeSupported();
|
this.timeSupported = tileSource.isTimeSupported();
|
||||||
this.inversiveZoom = tileSource.getInversiveZoom();
|
this.inversiveZoom = tileSource.getInversiveZoom();
|
||||||
|
@ -139,6 +143,7 @@ public class SQLiteTileSource implements ITileSource {
|
||||||
addInfoColumn(db, ELLIPSOID, isEllipsoid ? "1" : "0");
|
addInfoColumn(db, ELLIPSOID, isEllipsoid ? "1" : "0");
|
||||||
addInfoColumn(db, INVERTED_Y, invertedY ? "1" : "0");
|
addInfoColumn(db, INVERTED_Y, invertedY ? "1" : "0");
|
||||||
addInfoColumn(db, REFERER, referer);
|
addInfoColumn(db, REFERER, referer);
|
||||||
|
addInfoColumn(db, USER_AGENT, userAgent);
|
||||||
addInfoColumn(db, TIME_COLUMN, timeSupported ? "yes" : "no");
|
addInfoColumn(db, TIME_COLUMN, timeSupported ? "yes" : "no");
|
||||||
addInfoColumn(db, EXPIRE_MINUTES, String.valueOf(getExpirationTimeMinutes()));
|
addInfoColumn(db, EXPIRE_MINUTES, String.valueOf(getExpirationTimeMinutes()));
|
||||||
|
|
||||||
|
@ -264,6 +269,10 @@ public class SQLiteTileSource implements ITileSource {
|
||||||
if(refererId != -1) {
|
if(refererId != -1) {
|
||||||
referer = cursor.getString(refererId);
|
referer = cursor.getString(refererId);
|
||||||
}
|
}
|
||||||
|
int userAgentId = list.indexOf(USER_AGENT);
|
||||||
|
if(userAgentId != -1) {
|
||||||
|
userAgent = cursor.getString(userAgentId);
|
||||||
|
}
|
||||||
int tnumbering = list.indexOf(TILENUMBERING);
|
int tnumbering = list.indexOf(TILENUMBERING);
|
||||||
if(tnumbering != -1) {
|
if(tnumbering != -1) {
|
||||||
inversiveZoom = BIG_PLANET_TILE_NUMBERING.equalsIgnoreCase(cursor.getString(tnumbering));
|
inversiveZoom = BIG_PLANET_TILE_NUMBERING.equalsIgnoreCase(cursor.getString(tnumbering));
|
||||||
|
@ -673,4 +682,8 @@ public class SQLiteTileSource implements ITileSource {
|
||||||
return referer;
|
return referer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUserAgent() {
|
||||||
|
return userAgent;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,7 +392,7 @@ public class EditMapSourceDialogFragment extends BaseOsmAndDialogFragment
|
||||||
SQLiteTileSource sqLiteTileSource =
|
SQLiteTileSource sqLiteTileSource =
|
||||||
new SQLiteTileSource(app, newName, minZoom,
|
new SQLiteTileSource(app, newName, minZoom,
|
||||||
maxZoom, urlToLoad, "",
|
maxZoom, urlToLoad, "",
|
||||||
elliptic, false, "", expireTimeMinutes > 0,
|
elliptic, false, "", "", expireTimeMinutes > 0,
|
||||||
expireTimeMinutes * 60 * 1000L, false, ""
|
expireTimeMinutes * 60 * 1000L, false, ""
|
||||||
);
|
);
|
||||||
sqLiteTileSource.createDataBase();
|
sqLiteTileSource.createDataBase();
|
||||||
|
|
|
@ -17,6 +17,7 @@ import net.osmand.plus.routing.RouteCalculationResult;
|
||||||
import net.osmand.plus.routing.RoutingHelper;
|
import net.osmand.plus.routing.RoutingHelper;
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
import net.osmand.router.RouteCalculationProgress;
|
import net.osmand.router.RouteCalculationProgress;
|
||||||
|
import net.osmand.router.RouteImporter;
|
||||||
import net.osmand.router.RoutePlannerFrontEnd.GpxPoint;
|
import net.osmand.router.RoutePlannerFrontEnd.GpxPoint;
|
||||||
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
||||||
import net.osmand.router.RouteSegmentResult;
|
import net.osmand.router.RouteSegmentResult;
|
||||||
|
@ -25,20 +26,20 @@ import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.*;
|
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.NEXT_SEGMENT;
|
||||||
|
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.WHOLE_TRACK;
|
||||||
|
|
||||||
public class MeasurementEditingContext {
|
public class MeasurementEditingContext {
|
||||||
|
|
||||||
public enum CalculationMode {
|
public final static ApplicationMode DEFAULT_APP_MODE = ApplicationMode.DEFAULT;
|
||||||
NEXT_SEGMENT,
|
|
||||||
WHOLE_TRACK
|
|
||||||
}
|
|
||||||
|
|
||||||
private OsmandApplication application;
|
private OsmandApplication application;
|
||||||
private final MeasurementCommandManager commandManager = new MeasurementCommandManager();
|
private final MeasurementCommandManager commandManager = new MeasurementCommandManager();
|
||||||
|
@ -54,15 +55,55 @@ public class MeasurementEditingContext {
|
||||||
private WptPt originalPointToMove;
|
private WptPt originalPointToMove;
|
||||||
|
|
||||||
private boolean inAddPointMode;
|
private boolean inAddPointMode;
|
||||||
private boolean inSnapToRoadMode;
|
|
||||||
private boolean needUpdateCacheForSnap;
|
private boolean needUpdateCacheForSnap;
|
||||||
private int calculatedPairs;
|
private int calculatedPairs;
|
||||||
private CalculationMode calculationMode = WHOLE_TRACK;
|
private CalculationMode calculationMode = WHOLE_TRACK;
|
||||||
private SnapToRoadProgressListener progressListener;
|
private SnapToRoadProgressListener progressListener;
|
||||||
private ApplicationMode snapToRoadAppMode;
|
private ApplicationMode appMode = DEFAULT_APP_MODE;
|
||||||
private RouteCalculationProgress calculationProgress;
|
private RouteCalculationProgress calculationProgress;
|
||||||
private final Queue<Pair<WptPt, WptPt>> snapToRoadPairsToCalculate = new ConcurrentLinkedQueue<>();
|
private final Queue<Pair<WptPt, WptPt>> snapToRoadPairsToCalculate = new ConcurrentLinkedQueue<>();
|
||||||
private final Map<Pair<WptPt, WptPt>, List<WptPt>> snappedToRoadPoints = new ConcurrentHashMap<>();
|
private final Map<Pair<WptPt, WptPt>, RoadSegmentData> roadSegmentData = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public enum CalculationMode {
|
||||||
|
NEXT_SEGMENT,
|
||||||
|
WHOLE_TRACK
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RoadSegmentData {
|
||||||
|
private ApplicationMode appMode;
|
||||||
|
private WptPt start;
|
||||||
|
private WptPt end;
|
||||||
|
private List<WptPt> snappedToRoadPoints = new ArrayList<>();
|
||||||
|
private List<RouteSegmentResult> snappedToRoadSegments = new ArrayList<>();
|
||||||
|
|
||||||
|
public RoadSegmentData(ApplicationMode appMode, WptPt start, WptPt end, List<WptPt> snappedToRoadPoints, List<RouteSegmentResult> snappedToRoadSegments) {
|
||||||
|
this.appMode = appMode;
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
this.snappedToRoadPoints = snappedToRoadPoints;
|
||||||
|
this.snappedToRoadSegments = snappedToRoadSegments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApplicationMode getAppMode() {
|
||||||
|
return appMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WptPt getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WptPt getEnd() {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WptPt> getSnappedToRoadPoints() {
|
||||||
|
return Collections.unmodifiableList(snappedToRoadPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RouteSegmentResult> getSnappedToRoadSegments() {
|
||||||
|
return Collections.unmodifiableList(snappedToRoadSegments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setApplication(OsmandApplication application) {
|
public void setApplication(OsmandApplication application) {
|
||||||
this.application = application;
|
this.application = application;
|
||||||
|
@ -76,10 +117,6 @@ public class MeasurementEditingContext {
|
||||||
return inAddPointMode;
|
return inAddPointMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isInSnapToRoadMode() {
|
|
||||||
return inSnapToRoadMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNeedUpdateCacheForSnap() {
|
public boolean isNeedUpdateCacheForSnap() {
|
||||||
return needUpdateCacheForSnap;
|
return needUpdateCacheForSnap;
|
||||||
}
|
}
|
||||||
|
@ -109,8 +146,8 @@ public class MeasurementEditingContext {
|
||||||
this.inAddPointMode = inAddPointMode;
|
this.inAddPointMode = inAddPointMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInSnapToRoadMode(boolean inSnapToRoadMode) {
|
boolean isInSnapToRoadMode() {
|
||||||
this.inSnapToRoadMode = inSnapToRoadMode;
|
return appMode != DEFAULT_APP_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NewGpxData getNewGpxData() {
|
NewGpxData getNewGpxData() {
|
||||||
|
@ -141,19 +178,23 @@ public class MeasurementEditingContext {
|
||||||
this.progressListener = progressListener;
|
this.progressListener = progressListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApplicationMode getSnapToRoadAppMode() {
|
@NonNull
|
||||||
return snapToRoadAppMode;
|
public ApplicationMode getAppMode() {
|
||||||
|
return appMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSnapToRoadAppMode(ApplicationMode snapToRoadAppMode) {
|
public void setAppMode(@NonNull ApplicationMode appMode) {
|
||||||
this.snapToRoadAppMode = snapToRoadAppMode;
|
this.appMode = appMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetAppMode() {
|
||||||
|
this.appMode = DEFAULT_APP_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearSnappedToRoadPoints() {
|
public void clearSnappedToRoadPoints() {
|
||||||
snappedToRoadPoints.clear();
|
roadSegmentData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TrkSegment getBeforeTrkSegmentLine() {
|
TrkSegment getBeforeTrkSegmentLine() {
|
||||||
if (beforeCacheForSnap != null) {
|
if (beforeCacheForSnap != null) {
|
||||||
return beforeCacheForSnap;
|
return beforeCacheForSnap;
|
||||||
|
@ -224,7 +265,7 @@ public class MeasurementEditingContext {
|
||||||
public void clearSegments() {
|
public void clearSegments() {
|
||||||
before.points.clear();
|
before.points.clear();
|
||||||
after.points.clear();
|
after.points.clear();
|
||||||
if (inSnapToRoadMode) {
|
if (isInSnapToRoadMode()) {
|
||||||
if (beforeCacheForSnap != null && afterCacheForSnap != null) {
|
if (beforeCacheForSnap != null && afterCacheForSnap != null) {
|
||||||
beforeCacheForSnap.points.clear();
|
beforeCacheForSnap.points.clear();
|
||||||
afterCacheForSnap.points.clear();
|
afterCacheForSnap.points.clear();
|
||||||
|
@ -263,7 +304,7 @@ public class MeasurementEditingContext {
|
||||||
for (List<WptPt> points : pointsList) {
|
for (List<WptPt> points : pointsList) {
|
||||||
for (int i = 0; i < points.size() - 1; i++) {
|
for (int i = 0; i < points.size() - 1; i++) {
|
||||||
Pair<WptPt, WptPt> pair = new Pair<>(points.get(i), points.get(i + 1));
|
Pair<WptPt, WptPt> pair = new Pair<>(points.get(i), points.get(i + 1));
|
||||||
if (snappedToRoadPoints.get(pair) == null) {
|
if (roadSegmentData.get(pair) == null) {
|
||||||
snapToRoadPairsToCalculate.add(pair);
|
snapToRoadPairsToCalculate.add(pair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,11 +315,12 @@ public class MeasurementEditingContext {
|
||||||
if (original.points.size() > 1) {
|
if (original.points.size() > 1) {
|
||||||
for (int i = 0; i < original.points.size() - 1; i++) {
|
for (int i = 0; i < original.points.size() - 1; i++) {
|
||||||
Pair<WptPt, WptPt> pair = new Pair<>(original.points.get(i), original.points.get(i + 1));
|
Pair<WptPt, WptPt> pair = new Pair<>(original.points.get(i), original.points.get(i + 1));
|
||||||
List<WptPt> pts = snappedToRoadPoints.get(pair);
|
RoadSegmentData data = this.roadSegmentData.get(pair);
|
||||||
|
List<WptPt> pts = data != null ? data.getSnappedToRoadPoints() : null;
|
||||||
if (pts != null) {
|
if (pts != null) {
|
||||||
cache.points.addAll(pts);
|
cache.points.addAll(pts);
|
||||||
} else {
|
} else {
|
||||||
if (inSnapToRoadMode) {
|
if (isInSnapToRoadMode()) {
|
||||||
scheduleRouteCalculateIfNotEmpty();
|
scheduleRouteCalculateIfNotEmpty();
|
||||||
}
|
}
|
||||||
cache.points.addAll(Arrays.asList(pair.first, pair.second));
|
cache.points.addAll(Arrays.asList(pair.first, pair.second));
|
||||||
|
@ -296,6 +338,8 @@ public class MeasurementEditingContext {
|
||||||
}
|
}
|
||||||
List<WptPt> points = newGpxData.getTrkSegment().points;
|
List<WptPt> points = newGpxData.getTrkSegment().points;
|
||||||
if (isTrackSnappedToRoad()) {
|
if (isTrackSnappedToRoad()) {
|
||||||
|
RouteImporter routeImporter = new RouteImporter(newGpxData.getGpxFile());
|
||||||
|
List<RouteSegmentResult> segments = routeImporter.importRoute();
|
||||||
List<WptPt> routePoints = newGpxData.getGpxFile().getRoutePoints();
|
List<WptPt> routePoints = newGpxData.getGpxFile().getRoutePoints();
|
||||||
int prevPointIndex = 0;
|
int prevPointIndex = 0;
|
||||||
for (int i = 0; i < routePoints.size() - 1; i++) {
|
for (int i = 0; i < routePoints.size() - 1; i++) {
|
||||||
|
@ -309,12 +353,20 @@ public class MeasurementEditingContext {
|
||||||
endIndex = findPointIndex(pair.second, points, startIndex);
|
endIndex = findPointIndex(pair.second, points, startIndex);
|
||||||
}
|
}
|
||||||
if (startIndex >= 0 && endIndex >= 0) {
|
if (startIndex >= 0 && endIndex >= 0) {
|
||||||
List<WptPt> cacheSegment = new ArrayList<>();
|
List<WptPt> segmentPoints = new ArrayList<>();
|
||||||
for (int j = startIndex; j < endIndex && j < points.size(); j++) {
|
for (int j = startIndex; j < endIndex && j < points.size(); j++) {
|
||||||
cacheSegment.add(points.get(j));
|
segmentPoints.add(points.get(j));
|
||||||
prevPointIndex = j;
|
prevPointIndex = j;
|
||||||
}
|
}
|
||||||
snappedToRoadPoints.put(pair, cacheSegment);
|
Iterator<RouteSegmentResult> it = segments.iterator();
|
||||||
|
int k = endIndex - startIndex;
|
||||||
|
while (it.hasNext() && k >= 0) {
|
||||||
|
RouteSegmentResult s = it.next();
|
||||||
|
it.remove();
|
||||||
|
k -= Math.abs(s.getEndPointIndex() - s.getStartPointIndex());
|
||||||
|
}
|
||||||
|
ApplicationMode appMode = ApplicationMode.valueOfStringKey(pair.first.getProfileType(), DEFAULT_APP_MODE);
|
||||||
|
roadSegmentData.put(pair, new RoadSegmentData(appMode, pair.first, pair.second, segmentPoints, segments));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addPoints(routePoints);
|
addPoints(routePoints);
|
||||||
|
@ -327,7 +379,7 @@ public class MeasurementEditingContext {
|
||||||
if (gpxApproximation == null || Algorithms.isEmpty(gpxApproximation.finalPoints) || Algorithms.isEmpty(gpxApproximation.result)) {
|
if (gpxApproximation == null || Algorithms.isEmpty(gpxApproximation.finalPoints) || Algorithms.isEmpty(gpxApproximation.result)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
snappedToRoadPoints.clear();
|
roadSegmentData.clear();
|
||||||
List<WptPt> routePoints = new ArrayList<>();
|
List<WptPt> routePoints = new ArrayList<>();
|
||||||
List<GpxPoint> gpxPoints = gpxApproximation.finalPoints;
|
List<GpxPoint> gpxPoints = gpxApproximation.finalPoints;
|
||||||
for (int i = 0; i < gpxPoints.size() - 1; i++) {
|
for (int i = 0; i < gpxPoints.size() - 1; i++) {
|
||||||
|
@ -344,15 +396,17 @@ public class MeasurementEditingContext {
|
||||||
p2.lon = rp2.loc.getLongitude();
|
p2.lon = rp2.loc.getLongitude();
|
||||||
routePoints.add(p2);
|
routePoints.add(p2);
|
||||||
Pair<WptPt, WptPt> pair = new Pair<>(p1, p2);
|
Pair<WptPt, WptPt> pair = new Pair<>(p1, p2);
|
||||||
List<WptPt> cacheSegment = new ArrayList<>();
|
List<WptPt> points = new ArrayList<>();
|
||||||
|
List<RouteSegmentResult> segments = new ArrayList<>();
|
||||||
for (RouteSegmentResult seg : rp1.routeToTarget) {
|
for (RouteSegmentResult seg : rp1.routeToTarget) {
|
||||||
|
segments.add(seg);
|
||||||
if (seg.isForwardDirection()) {
|
if (seg.isForwardDirection()) {
|
||||||
for (int ik = seg.getStartPointIndex(); ik <= seg.getEndPointIndex(); ik++) {
|
for (int ik = seg.getStartPointIndex(); ik <= seg.getEndPointIndex(); ik++) {
|
||||||
LatLon l = seg.getPoint(ik);
|
LatLon l = seg.getPoint(ik);
|
||||||
WptPt pt = new WptPt();
|
WptPt pt = new WptPt();
|
||||||
pt.lat = l.getLatitude();
|
pt.lat = l.getLatitude();
|
||||||
pt.lon = l.getLongitude();
|
pt.lon = l.getLongitude();
|
||||||
cacheSegment.add(pt);
|
points.add(pt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int ik = seg.getEndPointIndex(); ik >= seg.getStartPointIndex(); ik--) {
|
for (int ik = seg.getEndPointIndex(); ik >= seg.getStartPointIndex(); ik--) {
|
||||||
|
@ -360,11 +414,11 @@ public class MeasurementEditingContext {
|
||||||
WptPt pt = new WptPt();
|
WptPt pt = new WptPt();
|
||||||
pt.lat = l.getLatitude();
|
pt.lat = l.getLatitude();
|
||||||
pt.lon = l.getLongitude();
|
pt.lon = l.getLongitude();
|
||||||
cacheSegment.add(pt);
|
points.add(pt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
snappedToRoadPoints.put(pair, cacheSegment);
|
roadSegmentData.put(pair, new RoadSegmentData(appMode, pair.first, pair.second, points, segments));
|
||||||
}
|
}
|
||||||
addPoints(routePoints);
|
addPoints(routePoints);
|
||||||
}
|
}
|
||||||
|
@ -386,7 +440,7 @@ public class MeasurementEditingContext {
|
||||||
NewGpxData newGpxData = getNewGpxData();
|
NewGpxData newGpxData = getNewGpxData();
|
||||||
return newGpxData != null && newGpxData.getTrkSegment() != null
|
return newGpxData != null && newGpxData.getTrkSegment() != null
|
||||||
&& !newGpxData.getTrkSegment().points.isEmpty()
|
&& !newGpxData.getTrkSegment().points.isEmpty()
|
||||||
&& !newGpxData.getGpxFile().getRoutePoints().isEmpty();
|
&& newGpxData.getGpxFile().hasRoute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCacheForSnapIfNeeded(boolean both) {
|
private void updateCacheForSnapIfNeeded(boolean both) {
|
||||||
|
@ -427,7 +481,7 @@ public class MeasurementEditingContext {
|
||||||
currentPointSnapToRoadMode = ApplicationMode.valueOfStringKey(currentPair.first.getProfileType(),
|
currentPointSnapToRoadMode = ApplicationMode.valueOfStringKey(currentPair.first.getProfileType(),
|
||||||
null);
|
null);
|
||||||
} else {
|
} else {
|
||||||
currentPointSnapToRoadMode = snapToRoadAppMode;
|
currentPointSnapToRoadMode = appMode;
|
||||||
}
|
}
|
||||||
params.end = end;
|
params.end = end;
|
||||||
if (currentPointSnapToRoadMode == null) {
|
if (currentPointSnapToRoadMode == null) {
|
||||||
|
@ -484,7 +538,7 @@ public class MeasurementEditingContext {
|
||||||
pts.add(pt);
|
pts.add(pt);
|
||||||
}
|
}
|
||||||
calculatedPairs++;
|
calculatedPairs++;
|
||||||
snappedToRoadPoints.put(currentPair, pts);
|
roadSegmentData.put(currentPair, new RoadSegmentData(route.getAppMode(), currentPair.first, currentPair.second, pts, route.getOriginalRoute()));
|
||||||
int trkptIndex = currentPair.first.getTrkPtIndex();
|
int trkptIndex = currentPair.first.getTrkPtIndex();
|
||||||
trkptIndex += pts.size() - 1;
|
trkptIndex += pts.size() - 1;
|
||||||
currentPair.second.setTrkPtIndex(trkptIndex);
|
currentPair.second.setTrkPtIndex(trkptIndex);
|
||||||
|
@ -563,13 +617,13 @@ public class MeasurementEditingContext {
|
||||||
params.start = start;
|
params.start = start;
|
||||||
params.end = end;
|
params.end = end;
|
||||||
params.intermediates = intermediates;
|
params.intermediates = intermediates;
|
||||||
if (snapToRoadAppMode == null) {
|
if (appMode == null) {
|
||||||
ApplicationMode straightLine = ApplicationMode.AIRCRAFT;
|
ApplicationMode straightLine = ApplicationMode.AIRCRAFT;
|
||||||
RoutingHelper.applyApplicationSettings(params, application.getSettings(), straightLine);
|
RoutingHelper.applyApplicationSettings(params, application.getSettings(), straightLine);
|
||||||
params.mode = straightLine;
|
params.mode = straightLine;
|
||||||
} else {
|
} else {
|
||||||
RoutingHelper.applyApplicationSettings(params, application.getSettings(), snapToRoadAppMode);
|
RoutingHelper.applyApplicationSettings(params, application.getSettings(), appMode);
|
||||||
params.mode = snapToRoadAppMode;
|
params.mode = appMode;
|
||||||
}
|
}
|
||||||
params.ctx = application;
|
params.ctx = application;
|
||||||
params.calculationProgress = calculationProgress = new RouteCalculationProgress();
|
params.calculationProgress = calculationProgress = new RouteCalculationProgress();
|
||||||
|
|
|
@ -15,6 +15,7 @@ import android.text.TextWatcher;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
|
@ -243,14 +244,14 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
upDownBtn = (ImageView) mainView.findViewById(R.id.up_down_button);
|
upDownBtn = (ImageView) mainView.findViewById(R.id.up_down_button);
|
||||||
upDownBtn.setImageDrawable(upIcon);
|
upDownBtn.setImageDrawable(upIcon);
|
||||||
|
|
||||||
mainView.findViewById(R.id.cancel_move_point_button).setOnClickListener(new View.OnClickListener() {
|
mainView.findViewById(R.id.cancel_move_point_button).setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
cancelMovePointMode();
|
cancelMovePointMode();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mainView.findViewById(R.id.cancel_point_before_after_button).setOnClickListener(new View.OnClickListener() {
|
mainView.findViewById(R.id.cancel_point_before_after_button).setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
cancelAddPointBeforeOrAfterMode();
|
cancelAddPointBeforeOrAfterMode();
|
||||||
|
@ -258,7 +259,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
});
|
});
|
||||||
|
|
||||||
upDownRow = mainView.findViewById(R.id.up_down_row);
|
upDownRow = mainView.findViewById(R.id.up_down_row);
|
||||||
upDownRow.setOnClickListener(new View.OnClickListener() {
|
upDownRow.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
if (!pointsListOpened && editingCtx.getPointsCount() > 0 && editingCtx.getSelectedPointPosition() == -1) {
|
if (!pointsListOpened && editingCtx.getPointsCount() > 0 && editingCtx.getSelectedPointPosition() == -1) {
|
||||||
|
@ -269,37 +270,35 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mainView.findViewById(R.id.apply_move_point_button).setOnClickListener(new View.OnClickListener() {
|
mainView.findViewById(R.id.apply_move_point_button).setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
applyMovePointMode();
|
applyMovePointMode();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mainView.findViewById(R.id.apply_point_before_after_point_button).setOnClickListener(new View.OnClickListener() {
|
mainView.findViewById(R.id.apply_point_before_after_point_button).setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
applyAddPointBeforeAfterMode();
|
applyAddPointBeforeAfterMode();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mainView.findViewById(R.id.add_point_before_after_button).setOnClickListener(new View.OnClickListener() {
|
mainView.findViewById(R.id.add_point_before_after_button).setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
addPointBeforeAfter();
|
addPointBeforeAfter();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mainView.findViewById(R.id.options_button).setOnClickListener(new View.OnClickListener() {
|
mainView.findViewById(R.id.options_button).setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
OptionsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
OptionsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
||||||
MeasurementToolFragment.this,
|
MeasurementToolFragment.this,
|
||||||
editingCtx.isTrackSnappedToRoad() || editingCtx.isNewData(),
|
editingCtx.isTrackSnappedToRoad() || editingCtx.isNewData(),
|
||||||
editingCtx.isInSnapToRoadMode(),
|
editingCtx.isInSnapToRoadMode(),
|
||||||
editingCtx.getSnapToRoadAppMode() != null
|
editingCtx.getAppMode().getStringKey()
|
||||||
? editingCtx.getSnapToRoadAppMode().getStringKey()
|
|
||||||
: null
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -309,7 +308,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
|
|
||||||
Drawable undoDrawable = getActiveIcon(R.drawable.ic_action_undo_dark);
|
Drawable undoDrawable = getActiveIcon(R.drawable.ic_action_undo_dark);
|
||||||
undoBtn.setImageDrawable(AndroidUtils.getDrawableForDirection(mapActivity, undoDrawable));
|
undoBtn.setImageDrawable(AndroidUtils.getDrawableForDirection(mapActivity, undoDrawable));
|
||||||
undoBtn.setOnClickListener(new View.OnClickListener() {
|
undoBtn.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
editingCtx.getCommandManager().undo();
|
editingCtx.getCommandManager().undo();
|
||||||
|
@ -321,7 +320,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
|
|
||||||
Drawable redoDrawable = getActiveIcon(R.drawable.ic_action_redo_dark);
|
Drawable redoDrawable = getActiveIcon(R.drawable.ic_action_redo_dark);
|
||||||
redoBtn.setImageDrawable(AndroidUtils.getDrawableForDirection(mapActivity, redoDrawable));
|
redoBtn.setImageDrawable(AndroidUtils.getDrawableForDirection(mapActivity, redoDrawable));
|
||||||
redoBtn.setOnClickListener(new View.OnClickListener() {
|
redoBtn.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
editingCtx.getCommandManager().redo();
|
editingCtx.getCommandManager().redo();
|
||||||
|
@ -331,7 +330,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mainView.findViewById(R.id.add_point_button).setOnClickListener(new View.OnClickListener() {
|
mainView.findViewById(R.id.add_point_button).setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
addCenterPoint();
|
addCenterPoint();
|
||||||
|
@ -407,13 +406,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
} else {
|
} else {
|
||||||
toolBarController.setTitle(getString(R.string.plan_route));
|
toolBarController.setTitle(getString(R.string.plan_route));
|
||||||
}
|
}
|
||||||
toolBarController.setOnBackButtonClickListener(new View.OnClickListener() {
|
toolBarController.setOnBackButtonClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
quit(false);
|
quit(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
toolBarController.setOnSaveViewClickListener(new View.OnClickListener() {
|
toolBarController.setOnSaveViewClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (editingCtx.getPointsCount() > 0) {
|
if (editingCtx.getPointsCount() > 0) {
|
||||||
|
@ -451,7 +450,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
|
|
||||||
ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button);
|
ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button);
|
||||||
snapToRoadBtn.setBackgroundResource(nightMode ? R.drawable.btn_circle_night : R.drawable.btn_circle);
|
snapToRoadBtn.setBackgroundResource(nightMode ? R.drawable.btn_circle_night : R.drawable.btn_circle);
|
||||||
snapToRoadBtn.setOnClickListener(new View.OnClickListener() {
|
snapToRoadBtn.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
startSnapToRoad(false);
|
startSnapToRoad(false);
|
||||||
|
@ -486,12 +485,12 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
updateSnapToRoadControls();
|
updateSnapToRoadControls();
|
||||||
if (newGpxData != null && !gpxPointsAdded) {
|
if (newGpxData != null && !gpxPointsAdded) {
|
||||||
List<WptPt> points = newGpxData.getGpxFile().getRoutePoints();
|
List<WptPt> points = newGpxData.getGpxFile().getRoutePoints();
|
||||||
ApplicationMode snapToRoadAppMode = null;
|
|
||||||
if (!points.isEmpty()) {
|
if (!points.isEmpty()) {
|
||||||
snapToRoadAppMode = ApplicationMode
|
ApplicationMode snapToRoadAppMode = ApplicationMode.valueOfStringKey(points.get(points.size() - 1).getProfileType(), null);
|
||||||
.valueOfStringKey(points.get(points.size() - 1).getProfileType(), null);
|
if (snapToRoadAppMode != null) {
|
||||||
|
setSnapToRoadMode(snapToRoadAppMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
enableSnapToRoadMode(snapToRoadAppMode);
|
|
||||||
ActionType actionType = newGpxData.getActionType();
|
ActionType actionType = newGpxData.getActionType();
|
||||||
if (actionType == ActionType.ADD_ROUTE_POINTS) {
|
if (actionType == ActionType.ADD_ROUTE_POINTS) {
|
||||||
displayRoutePoints();
|
displayRoutePoints();
|
||||||
|
@ -608,7 +607,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
if (editingCtx.isNewData() || editingCtx.hasRoutePoints() || editingCtx.isInSnapToRoadMode()) {
|
if (editingCtx.isNewData() || editingCtx.hasRoutePoints() || editingCtx.isInSnapToRoadMode()) {
|
||||||
RouteBetweenPointsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
RouteBetweenPointsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
||||||
this, editingCtx.getCalculationMode(),
|
this, editingCtx.getCalculationMode(),
|
||||||
editingCtx.getSnapToRoadAppMode());
|
editingCtx.getAppMode());
|
||||||
} else {
|
} else {
|
||||||
SnapTrackWarningBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), this);
|
SnapTrackWarningBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), this);
|
||||||
}
|
}
|
||||||
|
@ -985,19 +984,32 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableSnapToRoadMode(ApplicationMode appMode) {
|
private void setSnapToRoadMode(@NonNull ApplicationMode appMode) {
|
||||||
editingCtx.setSnapToRoadAppMode(appMode);
|
editingCtx.setAppMode(appMode);
|
||||||
editingCtx.setInSnapToRoadMode(true);
|
|
||||||
editingCtx.scheduleRouteCalculateIfNotEmpty();
|
editingCtx.scheduleRouteCalculateIfNotEmpty();
|
||||||
updateSnapToRoadControls();
|
updateSnapToRoadControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void resetSnapToRoadMode() {
|
||||||
|
toolBarController.setTopBarSwitchVisible(false);
|
||||||
|
toolBarController.setTitle(previousToolBarTitle);
|
||||||
|
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_ruler));
|
||||||
|
editingCtx.resetAppMode();
|
||||||
|
editingCtx.cancelSnapToRoad();
|
||||||
|
visibleSnapToRoadIcon(false);
|
||||||
|
MapActivity mapActivity = getMapActivity();
|
||||||
|
if (mapActivity != null) {
|
||||||
|
mainView.findViewById(R.id.snap_to_road_progress_bar).setVisibility(View.GONE);
|
||||||
|
mapActivity.refreshMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateSnapToRoadControls() {
|
private void updateSnapToRoadControls() {
|
||||||
final MapActivity mapActivity = getMapActivity();
|
final MapActivity mapActivity = getMapActivity();
|
||||||
final ApplicationMode appMode = editingCtx.getSnapToRoadAppMode();
|
final ApplicationMode appMode = editingCtx.getAppMode();
|
||||||
if (mapActivity != null) {
|
if (mapActivity != null) {
|
||||||
Drawable icon;
|
Drawable icon;
|
||||||
if (appMode == null) {
|
if (appMode == MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||||
icon = getActiveIcon(R.drawable.ic_action_split_interval);
|
icon = getActiveIcon(R.drawable.ic_action_split_interval);
|
||||||
} else {
|
} else {
|
||||||
icon = getIcon(appMode.getIconRes(), appMode.getIconColorInfo().getColor(nightMode));
|
icon = getIcon(appMode.getIconRes(), appMode.getIconColorInfo().getColor(nightMode));
|
||||||
|
@ -1008,20 +1020,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disableSnapToRoadMode() {
|
|
||||||
toolBarController.setTopBarSwitchVisible(false);
|
|
||||||
toolBarController.setTitle(previousToolBarTitle);
|
|
||||||
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_ruler));
|
|
||||||
editingCtx.setInSnapToRoadMode(false);
|
|
||||||
editingCtx.cancelSnapToRoad();
|
|
||||||
visibleSnapToRoadIcon(false);
|
|
||||||
MapActivity mapActivity = getMapActivity();
|
|
||||||
if (mapActivity != null) {
|
|
||||||
mainView.findViewById(R.id.snap_to_road_progress_bar).setVisibility(View.GONE);
|
|
||||||
mapActivity.refreshMap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void visibleSnapToRoadIcon(boolean show) {
|
private void visibleSnapToRoadIcon(boolean show) {
|
||||||
MapActivity mapActivity = getMapActivity();
|
MapActivity mapActivity = getMapActivity();
|
||||||
if (mapActivity != null) {
|
if (mapActivity != null) {
|
||||||
|
@ -1085,8 +1083,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
||||||
if (measurementLayer != null) {
|
if (measurementLayer != null) {
|
||||||
WptPt newPoint = measurementLayer.getMovedPointToApply();
|
WptPt newPoint = measurementLayer.getMovedPointToApply();
|
||||||
ApplicationMode applicationMode = editingCtx.getSnapToRoadAppMode();
|
ApplicationMode applicationMode = editingCtx.getAppMode();
|
||||||
if (applicationMode != null) {
|
if (applicationMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||||
newPoint.setProfileType(applicationMode.getStringKey());
|
newPoint.setProfileType(applicationMode.getStringKey());
|
||||||
}
|
}
|
||||||
WptPt oldPoint = editingCtx.getOriginalPointToMove();
|
WptPt oldPoint = editingCtx.getOriginalPointToMove();
|
||||||
|
@ -1356,7 +1354,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
final View buttonView = view.findViewById(R.id.button_view);
|
final View buttonView = view.findViewById(R.id.button_view);
|
||||||
final SwitchCompat showOnMapToggle = (SwitchCompat) view.findViewById(R.id.toggle_show_on_map);
|
final SwitchCompat showOnMapToggle = (SwitchCompat) view.findViewById(R.id.toggle_show_on_map);
|
||||||
UiUtilities.setupCompoundButton(showOnMapToggle, nightMode, UiUtilities.CompoundButtonType.GLOBAL);
|
UiUtilities.setupCompoundButton(showOnMapToggle, nightMode, UiUtilities.CompoundButtonType.GLOBAL);
|
||||||
buttonView.setOnClickListener(new View.OnClickListener() {
|
buttonView.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
showOnMapToggle.setChecked(!showOnMapToggle.isChecked());
|
showOnMapToggle.setChecked(!showOnMapToggle.isChecked());
|
||||||
|
@ -1615,7 +1613,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
snackbar = Snackbar.make(mapActivity.getLayout(),
|
snackbar = Snackbar.make(mapActivity.getLayout(),
|
||||||
MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getName()),
|
MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getName()),
|
||||||
Snackbar.LENGTH_LONG)
|
Snackbar.LENGTH_LONG)
|
||||||
.setAction(R.string.shared_string_rename, new View.OnClickListener() {
|
.setAction(R.string.shared_string_rename, new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
MapActivity mapActivity = mapActivityRef.get();
|
MapActivity mapActivity = mapActivityRef.get();
|
||||||
|
@ -1783,7 +1781,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
hidePointsList();
|
hidePointsList();
|
||||||
}
|
}
|
||||||
if (editingCtx.isInSnapToRoadMode()) {
|
if (editingCtx.isInSnapToRoadMode()) {
|
||||||
disableSnapToRoadMode();
|
resetSnapToRoadMode();
|
||||||
} else {
|
} else {
|
||||||
visibleSnapToRoadIcon(false);
|
visibleSnapToRoadIcon(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,8 +324,8 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
||||||
boolean allowed = editingCtx.getPointsCount() == 0 || !editingCtx.getPoints().get(editingCtx.getPointsCount() - 1).equals(pt);
|
boolean allowed = editingCtx.getPointsCount() == 0 || !editingCtx.getPoints().get(editingCtx.getPointsCount() - 1).equals(pt);
|
||||||
if (allowed) {
|
if (allowed) {
|
||||||
|
|
||||||
ApplicationMode applicationMode = editingCtx.getSnapToRoadAppMode();
|
ApplicationMode applicationMode = editingCtx.getAppMode();
|
||||||
if (applicationMode != null) {
|
if (applicationMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||||
pt.setProfileType(applicationMode.getStringKey());
|
pt.setProfileType(applicationMode.getStringKey());
|
||||||
}
|
}
|
||||||
editingCtx.addPoint(pt);
|
editingCtx.addPoint(pt);
|
||||||
|
@ -344,8 +344,8 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
||||||
pressedPointLatLon = null;
|
pressedPointLatLon = null;
|
||||||
boolean allowed = editingCtx.getPointsCount() == 0 || !editingCtx.getPoints().get(editingCtx.getPointsCount() - 1).equals(pt);
|
boolean allowed = editingCtx.getPointsCount() == 0 || !editingCtx.getPoints().get(editingCtx.getPointsCount() - 1).equals(pt);
|
||||||
if (allowed) {
|
if (allowed) {
|
||||||
ApplicationMode applicationMode = editingCtx.getSnapToRoadAppMode();
|
ApplicationMode applicationMode = editingCtx.getAppMode();
|
||||||
if (applicationMode != null) {
|
if (applicationMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||||
pt.setProfileType(applicationMode.getStringKey());
|
pt.setProfileType(applicationMode.getStringKey());
|
||||||
}
|
}
|
||||||
editingCtx.addPoint(pt);
|
editingCtx.addPoint(pt);
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class AddPointCommand extends MeasurementModeCommand {
|
||||||
point = new WptPt();
|
point = new WptPt();
|
||||||
point.lat = latLon.getLatitude();
|
point.lat = latLon.getLatitude();
|
||||||
point.lon = latLon.getLongitude();
|
point.lon = latLon.getLongitude();
|
||||||
point.setProfileType(measurementLayer.getEditingCtx().getSnapToRoadAppMode().getStringKey());
|
point.setProfileType(measurementLayer.getEditingCtx().getAppMode().getStringKey());
|
||||||
}
|
}
|
||||||
this.center = center;
|
this.center = center;
|
||||||
position = measurementLayer.getEditingCtx().getPointsCount();
|
position = measurementLayer.getEditingCtx().getPointsCount();
|
||||||
|
|
|
@ -52,9 +52,8 @@ public class ApplyGpxApproximationCommand extends MeasurementModeCommand {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
getEditingCtx().setInSnapToRoadMode(false);
|
getEditingCtx().resetAppMode();
|
||||||
getEditingCtx().clearSegments();
|
getEditingCtx().clearSegments();
|
||||||
getEditingCtx().setSnapToRoadAppMode(null);
|
|
||||||
getEditingCtx().addPoints(points);
|
getEditingCtx().addPoints(points);
|
||||||
if (needUpdateCache) {
|
if (needUpdateCache) {
|
||||||
getEditingCtx().setNeedUpdateCacheForSnap(true);
|
getEditingCtx().setNeedUpdateCacheForSnap(true);
|
||||||
|
@ -69,9 +68,8 @@ public class ApplyGpxApproximationCommand extends MeasurementModeCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyApproximation() {
|
public void applyApproximation() {
|
||||||
getEditingCtx().setInSnapToRoadMode(true);
|
getEditingCtx().setAppMode(mode);
|
||||||
getEditingCtx().clearSegments();
|
getEditingCtx().clearSegments();
|
||||||
getEditingCtx().setSnapToRoadAppMode(mode);
|
|
||||||
getEditingCtx().setPoints(approximation);
|
getEditingCtx().setPoints(approximation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class ChangeRouteModeCommand extends MeasurementModeCommand {
|
||||||
this.newMode = newMode;
|
this.newMode = newMode;
|
||||||
this.newCalculationMode = newCalculationMode;
|
this.newCalculationMode = newCalculationMode;
|
||||||
MeasurementEditingContext editingCtx = getEditingCtx();
|
MeasurementEditingContext editingCtx = getEditingCtx();
|
||||||
oldMode = editingCtx.getSnapToRoadAppMode();
|
oldMode = editingCtx.getAppMode();
|
||||||
oldCalculationMode = editingCtx.getCalculationMode();
|
oldCalculationMode = editingCtx.getCalculationMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,12 +43,11 @@ public class ChangeRouteModeCommand extends MeasurementModeCommand {
|
||||||
MeasurementEditingContext editingCtx = getEditingCtx();
|
MeasurementEditingContext editingCtx = getEditingCtx();
|
||||||
editingCtx.getPoints().clear();
|
editingCtx.getPoints().clear();
|
||||||
editingCtx.addPoints(points);
|
editingCtx.addPoints(points);
|
||||||
editingCtx.setSnapToRoadAppMode(oldMode);
|
editingCtx.setAppMode(oldMode);
|
||||||
if (newCalculationMode == CalculationMode.WHOLE_TRACK) {
|
if (newCalculationMode == CalculationMode.WHOLE_TRACK) {
|
||||||
editingCtx.clearSnappedToRoadPoints();
|
editingCtx.clearSnappedToRoadPoints();
|
||||||
}
|
}
|
||||||
editingCtx.setCalculationMode(oldCalculationMode);
|
editingCtx.setCalculationMode(oldCalculationMode);
|
||||||
editingCtx.setInSnapToRoadMode(true);
|
|
||||||
editingCtx.setNeedUpdateCacheForSnap(true);
|
editingCtx.setNeedUpdateCacheForSnap(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,9 +70,8 @@ public class ChangeRouteModeCommand extends MeasurementModeCommand {
|
||||||
points.get(pointIdx).removeProfileType();
|
points.get(pointIdx).removeProfileType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
editingCtx.setInSnapToRoadMode(true);
|
|
||||||
editingCtx.setCalculationMode(newCalculationMode);
|
editingCtx.setCalculationMode(newCalculationMode);
|
||||||
editingCtx.setSnapToRoadAppMode(newMode);
|
editingCtx.setAppMode(newMode);
|
||||||
if (newCalculationMode == CalculationMode.WHOLE_TRACK) {
|
if (newCalculationMode == CalculationMode.WHOLE_TRACK) {
|
||||||
editingCtx.clearSnappedToRoadPoints();
|
editingCtx.clearSnappedToRoadPoints();
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,20 +63,21 @@ public class ParkingTypeBottomSheetDialogFragment extends MenuBottomSheetDialogF
|
||||||
if (plugin.isParkingEventAdded()) {
|
if (plugin.isParkingEventAdded()) {
|
||||||
plugin.showDeleteEventWarning(mapActivity);
|
plugin.showDeleteEventWarning(mapActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (limited) {
|
if (limited) {
|
||||||
plugin.setParkingPosition(latitude, longitude, true);
|
plugin.setParkingPosition(latitude, longitude, true);
|
||||||
plugin.showSetTimeLimitDialog(mapActivity, new Dialog(getContext()));
|
plugin.showSetTimeLimitDialog(mapActivity, new Dialog(mapActivity));
|
||||||
mapActivity.refreshMap();
|
|
||||||
} else {
|
} else {
|
||||||
plugin.addOrRemoveParkingEvent(false);
|
plugin.addOrRemoveParkingEvent(false);
|
||||||
plugin.setParkingPosition(latitude, longitude, false);
|
plugin.setParkingPosition(latitude, longitude, false);
|
||||||
plugin.showContextMenuIfNeeded(mapActivity, true);
|
|
||||||
|
|
||||||
mapActivity.refreshMap();
|
|
||||||
}
|
}
|
||||||
|
mapActivity.refreshMap();
|
||||||
mapActivity.getMyApplication().getFavorites().setSpecialPoint(
|
mapActivity.getMyApplication().getFavorites().setSpecialPoint(
|
||||||
plugin.getParkingPosition(), SpecialPointType.PARKING, null);
|
plugin.getParkingPosition(), SpecialPointType.PARKING, null);
|
||||||
|
if (!limited) {
|
||||||
|
plugin.showContextMenuIfNeeded(mapActivity, true);
|
||||||
}
|
}
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -105,12 +105,13 @@ public class AsyncLoadingThread extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileLoadDownloadRequest(File dirWithTiles, String url, File fileToSave, String tileId, ITileSource source, int tileX,
|
public TileLoadDownloadRequest(File dirWithTiles, String url, File fileToSave, String tileId, ITileSource source, int tileX,
|
||||||
int tileY, int zoom, String referer) {
|
int tileY, int zoom, String referer, String userAgent) {
|
||||||
super(url, fileToSave, tileX, tileY, zoom);
|
super(url, fileToSave, tileX, tileY, zoom);
|
||||||
this.dirWithTiles = dirWithTiles;
|
this.dirWithTiles = dirWithTiles;
|
||||||
this.tileSource = source;
|
this.tileSource = source;
|
||||||
this.tileId = tileId;
|
this.tileId = tileId;
|
||||||
this.referer = referer;
|
this.referer = referer;
|
||||||
|
this.userAgent = userAgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveTile(InputStream inputStream) throws IOException {
|
public void saveTile(InputStream inputStream) throws IOException {
|
||||||
|
|
|
@ -144,7 +144,7 @@ public abstract class TilesCache<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TileLoadDownloadRequest req = new TileLoadDownloadRequest(dirWithTiles, url, toSave,
|
TileLoadDownloadRequest req = new TileLoadDownloadRequest(dirWithTiles, url, toSave,
|
||||||
tileId, map, x, y, zoom, map.getReferer());
|
tileId, map, x, y, zoom, map.getReferer(), map.getUserAgent());
|
||||||
if (sync) {
|
if (sync) {
|
||||||
return getRequestedTile(req);
|
return getRequestedTile(req);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1845,6 +1845,7 @@ public class OsmandSettings {
|
||||||
public final CommonPreference<RouteService> ROUTE_SERVICE = new EnumStringPreference<>("route_service", RouteService.OSMAND, RouteService.values()).makeProfile().cache();
|
public final CommonPreference<RouteService> ROUTE_SERVICE = new EnumStringPreference<>("route_service", RouteService.OSMAND, RouteService.values()).makeProfile().cache();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
ROUTE_SERVICE.setModeDefaultValue(ApplicationMode.DEFAULT, RouteService.STRAIGHT);
|
||||||
ROUTE_SERVICE.setModeDefaultValue(ApplicationMode.AIRCRAFT, RouteService.STRAIGHT);
|
ROUTE_SERVICE.setModeDefaultValue(ApplicationMode.AIRCRAFT, RouteService.STRAIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2035,6 +2035,7 @@ public class SettingsHelper {
|
||||||
boolean ellipsoid = object.optBoolean("ellipsoid", false);
|
boolean ellipsoid = object.optBoolean("ellipsoid", false);
|
||||||
boolean invertedY = object.optBoolean("inverted_y", false);
|
boolean invertedY = object.optBoolean("inverted_y", false);
|
||||||
String referer = object.optString("referer");
|
String referer = object.optString("referer");
|
||||||
|
String userAgent = object.optString("userAgent");
|
||||||
boolean timeSupported = object.optBoolean("timesupported", false);
|
boolean timeSupported = object.optBoolean("timesupported", false);
|
||||||
long expire = object.optLong("expire", -1);
|
long expire = object.optLong("expire", -1);
|
||||||
boolean inversiveZoom = object.optBoolean("inversiveZoom", false);
|
boolean inversiveZoom = object.optBoolean("inversiveZoom", false);
|
||||||
|
@ -2054,13 +2055,14 @@ public class SettingsHelper {
|
||||||
tileSourceTemplate.setRule(rule);
|
tileSourceTemplate.setRule(rule);
|
||||||
tileSourceTemplate.setRandoms(randoms);
|
tileSourceTemplate.setRandoms(randoms);
|
||||||
tileSourceTemplate.setReferer(referer);
|
tileSourceTemplate.setReferer(referer);
|
||||||
|
tileSourceTemplate.setUserAgent(userAgent);
|
||||||
tileSourceTemplate.setEllipticYTile(ellipsoid);
|
tileSourceTemplate.setEllipticYTile(ellipsoid);
|
||||||
tileSourceTemplate.setInvertedYTile(invertedY);
|
tileSourceTemplate.setInvertedYTile(invertedY);
|
||||||
tileSourceTemplate.setExpirationTimeMillis(timeSupported ? expire : -1);
|
tileSourceTemplate.setExpirationTimeMillis(timeSupported ? expire : -1);
|
||||||
|
|
||||||
template = tileSourceTemplate;
|
template = tileSourceTemplate;
|
||||||
} else {
|
} else {
|
||||||
template = new SQLiteTileSource(app, name, minZoom, maxZoom, url, randoms, ellipsoid, invertedY, referer, timeSupported, expire, inversiveZoom, rule);
|
template = new SQLiteTileSource(app, name, minZoom, maxZoom, url, randoms, ellipsoid, invertedY, referer, userAgent, timeSupported, expire, inversiveZoom, rule);
|
||||||
}
|
}
|
||||||
items.add(template);
|
items.add(template);
|
||||||
}
|
}
|
||||||
|
@ -2087,6 +2089,7 @@ public class SettingsHelper {
|
||||||
jsonObject.put("ellipsoid", template.isEllipticYTile());
|
jsonObject.put("ellipsoid", template.isEllipticYTile());
|
||||||
jsonObject.put("inverted_y", template.isInvertedYTile());
|
jsonObject.put("inverted_y", template.isInvertedYTile());
|
||||||
jsonObject.put("referer", template.getReferer());
|
jsonObject.put("referer", template.getReferer());
|
||||||
|
jsonObject.put("userAgent", template.getUserAgent());
|
||||||
jsonObject.put("timesupported", template.isTimeSupported());
|
jsonObject.put("timesupported", template.isTimeSupported());
|
||||||
jsonObject.put("expire", template.getExpirationTimeMinutes());
|
jsonObject.put("expire", template.getExpirationTimeMinutes());
|
||||||
jsonObject.put("inversiveZoom", template.getInversiveZoom());
|
jsonObject.put("inversiveZoom", template.getInversiveZoom());
|
||||||
|
|
65
README.md
65
README.md
|
@ -5,16 +5,20 @@ To get started, continue with the basic description below, then find more detail
|
||||||
You are welcome to discuss any question regarding the project at the Google group OsmAnd. Please do not use comments on wiki pages because it is rather difficult to find them.
|
You are welcome to discuss any question regarding the project at the Google group OsmAnd. Please do not use comments on wiki pages because it is rather difficult to find them.
|
||||||
|
|
||||||
<a href="https://play.google.com/store/apps/details?id=net.osmand" target="_blank">
|
<a href="https://play.google.com/store/apps/details?id=net.osmand" target="_blank">
|
||||||
<img src="https://raw.githubusercontent.com/osmandapp/osmandapp.github.io/9fc59e5136b6a07045eb96d052b3ce6ddde805c3/website/images/help/badge_store_google_play.png" alt="Get it on Google Play" height="60"/></a>
|
<img src="https://github.com/osmandapp/osmandapp.github.io/blob/master/website/images/help/badge_store_google_play.png" alt="Get it on Google Play" height="60"/></a>
|
||||||
<a href="https://www.amazon.com/OsmAnd-Maps-Navigation/dp/B00D0SA8I8" target="_blank">
|
<a href="https://www.amazon.com/OsmAnd-Maps-Navigation/dp/B00D0SA8I8" target="_blank">
|
||||||
<img src="https://raw.githubusercontent.com/osmandapp/osmandapp.github.io/9fc59e5136b6a07045eb96d052b3ce6ddde805c3/website/images/help/badge_store_amazon.png" alt="Get it on Amazon" height="60"/></a>
|
<img src="https://github.com/osmandapp/osmandapp.github.io/blob/master/website/images/help/badge_store_amazon.png" alt="Get it on Amazon" height="60"/></a>
|
||||||
<a href="https://itunes.apple.com/app/apple-store/id934850257?mt=8" target="_blank">
|
<a href="https://apps.apple.com/app/apple-store/id934850257" target="_blank">
|
||||||
<img src="https://raw.githubusercontent.com/osmandapp/osmandapp.github.io/9fc59e5136b6a07045eb96d052b3ce6ddde805c3/website/images/help/badge_store_appstore.png" alt="Get it on AppStore" height="60"/></a>
|
<img src="https://github.com/osmandapp/osmandapp.github.io/blob/master/website/images/help/badge_store_appstore.png" alt="Get it on AppStore" height="60"/></a>
|
||||||
|
|
||||||
|
|
||||||
Functionality
|
Functionality
|
||||||
-------------
|
-------------
|
||||||
**OsmAnd (OSM Automated Navigation Directions)** is a map and navigation application with access to the free, worldwide, and high-quality OpenStreetMap (OSM) data. All map data can be stored on your device's memory card for offline use. Via your device's GPS, OsmAnd offers routing, with optical and voice guidance, for car, bike, and pedestrian. All the main functionalities work both online and offline (no internet needed).
|
**OsmAnd (OSM Automated Navigation Directions)** is a map and navigation application with access to the free, worldwide, and high-quality OpenStreetMap (OSM) database.
|
||||||
|
All map data can be stored on your device's memory card for offline use.
|
||||||
|
Via your device's GPS, OsmAnd offers routing, with optical and voice guidance, for car, bike, and pedestrian usage.
|
||||||
|
All main functionalities work both online and offline (no internet needed).
|
||||||
|
|
||||||
|
|
||||||
## Some of the main features:
|
## Some of the main features:
|
||||||
|
|
||||||
|
@ -40,7 +44,7 @@ Functionality
|
||||||
* High quality information from the world's best collaborative projects
|
* High quality information from the world's best collaborative projects
|
||||||
* Global maps from OpenStreetMap, available per country or region
|
* Global maps from OpenStreetMap, available per country or region
|
||||||
* Wikipedia POIs, great for sightseeing (not available in free version)
|
* Wikipedia POIs, great for sightseeing (not available in free version)
|
||||||
* Unlimited free download, directly from the app (download limit 16 map files in free version)
|
* Unlimited free downloading, directly from the app (download limit is 16 map files in free version)
|
||||||
* Always up-to-date maps (updated at least once a month)
|
* Always up-to-date maps (updated at least once a month)
|
||||||
* Compact offline vector maps
|
* Compact offline vector maps
|
||||||
* Select between complete map data and just road network (Example: All of Japan is 700 MB, or 200 MB for the road network only)
|
* Select between complete map data and just road network (Example: All of Japan is 700 MB, or 200 MB for the road network only)
|
||||||
|
@ -53,20 +57,26 @@ Functionality
|
||||||
* Share your location so that your friends can find you
|
* Share your location so that your friends can find you
|
||||||
|
|
||||||
#### Bicycle and Pedestrian Features
|
#### Bicycle and Pedestrian Features
|
||||||
* The maps include foot, hiking, and bike paths, great for outdoor activities
|
* The maps include foot, hiking, and bike paths (great for outdoor activities)
|
||||||
* Special routing and display modes for bike and pedestrian
|
* Special routing and display modes for bike and pedestrian usage
|
||||||
* Optional public transport stops (bus, tram, train) including line names
|
* Optional public transport stops (bus, tram, train), including line names
|
||||||
* Optional trip recording to local GPX file or online service
|
* Optional trip recording to local GPX file or online service
|
||||||
* Optional speed and altitude display
|
* Optional speed and altitude display
|
||||||
* Display of contour lines and hill-shading (via additional plugin)
|
* Display of contour lines and hill-shading (via additional paid plugin)
|
||||||
|
|
||||||
#### Directly Contribute to OpenStreetMap
|
#### Directly Contribute to OpenStreetMap
|
||||||
* Report map bugs
|
* Report map bugs
|
||||||
* Upload GPX tracks to OSM directly from the app
|
* Upload GPX tracks to OSM directly from the app
|
||||||
* Add POIs and directly upload them to OSM (or later if offline)
|
* Add POIs and directly upload them to OSM (or later if offline)
|
||||||
* Optional trip recording also in background mode (while device is in sleep mode)
|
* Optional trip recording in background mode (while device is in sleep mode)
|
||||||
|
|
||||||
OsmAnd is open source and actively being developed. Everyone can contribute to the application by reporting bugs, [improving translations](https://hosted.weblate.org/projects/osmand/), or coding new features. The project is in a lively selected of continuous improvement by all these forms of developer and user interaction. The project progress also relies on financial contributions to fund the development, coding, and testing of new functionality. By buying OsmAnd+ and subscribing to OsmAnd Live you help the application to be even more awesome! It is also possible to make a general donation, see http://osmand.net/help-online#buy_app.
|
|
||||||
|
OsmAnd is open-source and actively being developed.
|
||||||
|
Everyone can contribute to the application by reporting bugs, [improving translations](https://hosted.weblate.org/projects/osmand/), or coding new features.
|
||||||
|
The project experiences continuous improvement by all such forms of developer and user interaction.
|
||||||
|
The project progress also relies on financial contributions to fund the development, coding, and testing of new functionality.
|
||||||
|
By buying OsmAnd+ and subscribing to OsmAnd Live, you help the application become even more awesome!
|
||||||
|
It is also possible to make a general donation (see https://osmand.net/help-online#buy_app).
|
||||||
|
|
||||||
|
|
||||||
#### Approximate map coverage and quality:
|
#### Approximate map coverage and quality:
|
||||||
|
@ -84,5 +94,34 @@ OsmAnd is open source and actively being developed. Everyone can contribute to t
|
||||||
| Antarctica | + |
|
| Antarctica | + |
|
||||||
|
|
||||||
##### List of countries supported
|
##### List of countries supported
|
||||||
Basically world wide: Afghanistan, Albania, Algeria, Andorra, Angola, Anguilla, Antigua and Barbuda, Argentina, Armenia, Aruba, Australia, Austria, Azerbaijan, Bahamas, Bahrain, Bangladesh, Barbados, Belarus, Belgium, Belize, Benin, Bermuda, Bhutan, Bolivia, Bonaire, Bosnia and Herzegovina, Botswana, Brazil, British Virgin Islands, Brunei, Bulgaria, Burkina Faso, Burundi, Cambodia, Cameroon, Canada, Cape Verde, Central African Republic, Chad, Chile, China, Colombia, Comoros, Congo, Costa Rica, Croatia, Cuba, Curaçao, Cyprus, Czechia, Denmark, Djibouti, Dominica, Dominican Republic, Ecuador, Egypt, El Salvador, Equatorial Guinea, Eritrea, Estonia, Ethiopia, Fiji, Finland, France, French Guiana, French Polynesia, Gabon, Gambia, Georgia, Germany, Ghana, Gibraltar, Greece, Greenland, Grenada, Guadeloupe, Guam, Guatemala, Guernsey, Guinea, Guinea-Bissau, Guyana, Haiti, Vatican, Honduras, Hong Kong, Hungary, Iceland, India, Indonesia, Iran, Iraq, Ireland, Isle of Man, Israel, Italy, Ivory Coast, Jamaica, Japan, Jersey, Jordan, Kazakhstan, Kenya, Kiribati, North Korea and South Korea, Kuwait, Kyrgyzstan, Laos, Latvia, Lebanon, Lesotho, Liberia, Libya, Liechtenstein, Lithuania, Luxembourg, Macao, Macedonia, Madagascar, Malawi, Malaysia, Maldives, Mali, Malta, Martinique, Mauritania, Mauritius, Mayotte, Mexico, Micronesia, Moldova, Monaco, Mongolia, Montenegro, Montserrat, Morocco, Mozambique, Myanmar, Namibia, Nauru, Nepal, Netherlands, Netherlands Antilles, New Caledonia, New Zealand, Nicaragua, Niger, Nigeria, Norway, Oman, Pakistan, Palau, Palestinian Territory, Panama, Papua New Guinea, Paraguay, Peru, Philippines, Poland, Portugal, Puerto Rico, Qatar, Romania, Russia, Rwanda, Saint Barthelemy, Saint Helena, Saint Kitts and Nevis, Saint Lucia, Saint Martin, Saint Pierre and Miquelon, Saint Vincent and the Grenadines, Samoa, San Marino, Saudi Arabia, Senegal, Serbia, Seychelles, Sierra Leone, Singapore, Slovakia, Slovenia, Somalia, South Africa, South Georgia, South Sudan, Spain, Sri Lanka, Sudan, Suriname, Swaziland, Sweden, Switzerland, Syria, Taiwan, Tajikistan, Tanzania, Thailand, Timor-Leste, Togo, Tokelau, Tonga, Trinidad and Tobago, Tunisia, Turkey, Turkmenistan, Tuvalu, Uganda, Ukraine, United Arab Emirates, United Kingdom (UK), United States of America (USA), Uruguay, Uzbekistan, Vanuatu, Venezuela, Vietnam, Wallis and Futuna, Western Sahara, Yemen, Zambia, Zimbabwe.
|
Basically world wide: Afghanistan, Albania, Algeria, Andorra, Angola, Anguilla,
|
||||||
|
Antigua and Barbuda, Argentina, Armenia, Aruba, Australia, Austria, Azerbaijan,
|
||||||
|
Bahamas, Bahrain, Bangladesh, Barbados, Belarus, Belgium, Belize, Benin, Bermuda,
|
||||||
|
Bhutan, Bolivia, Bonaire, Bosnia and Herzegovina, Botswana, Brazil,
|
||||||
|
British Virgin Islands, Brunei, Bulgaria, Burkina Faso, Burundi, Cambodia, Cameroon,
|
||||||
|
Canada, Cape Verde, Central African Republic, Chad, Chile, China, Colombia, Comoros,
|
||||||
|
Congo, Costa Rica, Croatia, Cuba, Curaçao, Cyprus, Czechia, Denmark, Djibouti, Dominica,
|
||||||
|
Dominican Republic, Ecuador, Egypt, El Salvador, Equatorial Guinea, Eritrea, Estonia,
|
||||||
|
Ethiopia, Fiji, Finland, France, French Guiana, French Polynesia, Gabon, Gambia,
|
||||||
|
Georgia, Germany, Ghana, Gibraltar, Greece, Greenland, Grenada, Guadeloupe, Guam,
|
||||||
|
Guatemala, Guernsey, Guinea, Guinea-Bissau, Guyana, Haiti, Vatican, Honduras, Hong Kong,
|
||||||
|
Hungary, Iceland, India, Indonesia, Iran, Iraq, Ireland, Isle of Man, Israel, Italy,
|
||||||
|
Ivory Coast, Jamaica, Japan, Jersey, Jordan, Kazakhstan, Kenya, Kiribati,
|
||||||
|
North Korea and South Korea, Kuwait, Kyrgyzstan, Laos, Latvia, Lebanon, Lesotho,
|
||||||
|
Liberia, Libya, Liechtenstein, Lithuania, Luxembourg, Macao, Macedonia, Madagascar,
|
||||||
|
Malawi, Malaysia, Maldives, Mali, Malta, Martinique, Mauritania, Mauritius, Mayotte,
|
||||||
|
Mexico, Micronesia, Moldova, Monaco, Mongolia, Montenegro, Montserrat, Morocco,
|
||||||
|
Mozambique, Myanmar, Namibia, Nauru, Nepal, Netherlands, Netherlands Antilles,
|
||||||
|
New Caledonia, New Zealand, Nicaragua, Niger, Nigeria, Norway, Oman, Pakistan, Palau,
|
||||||
|
Palestinian Territory, Panama, Papua New Guinea, Paraguay, Peru, Philippines, Poland,
|
||||||
|
Portugal, Puerto Rico, Qatar, Romania, Russia, Rwanda, Saint Barthelemy, Saint Helena,
|
||||||
|
Saint Kitts and Nevis, Saint Lucia, Saint Martin, Saint Pierre and Miquelon,
|
||||||
|
Saint Vincent and the Grenadines, Samoa, San Marino, Saudi Arabia, Senegal, Serbia,
|
||||||
|
Seychelles, Sierra Leone, Singapore, Slovakia, Slovenia, Somalia, South Africa,
|
||||||
|
South Georgia, South Sudan, Spain, Sri Lanka, Sudan, Suriname, Swaziland, Sweden,
|
||||||
|
Switzerland, Syria, Taiwan, Tajikistan, Tanzania, Thailand, Timor-Leste, Togo,
|
||||||
|
Tokelau, Tonga, Trinidad and Tobago, Tunisia, Turkey, Turkmenistan, Tuvalu, Uganda,
|
||||||
|
Ukraine, United Arab Emirates, United Kingdom (UK), United States of America (USA),
|
||||||
|
Uruguay, Uzbekistan, Vanuatu, Venezuela, Vietnam, Wallis and Futuna, Western Sahara,
|
||||||
|
Yemen, Zambia, Zimbabwe.
|
||||||
</p>
|
</p>
|
||||||
|
|
Loading…
Reference in a new issue