Merge remote-tracking branch 'origin/master'

This commit is contained in:
Weblate 2014-08-06 01:29:24 +02:00
commit 91b2faef41
14 changed files with 427 additions and 91 deletions

View file

@ -1,31 +1,48 @@
package net.osmand.binary; package net.osmand.binary;
import gnu.trove.iterator.TIntIterator;
import gnu.trove.list.array.TIntArrayList; import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.TIntObjectMap; import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.set.hash.TIntHashSet; import gnu.trove.set.hash.TIntHashSet;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.osmand.Collator; import net.osmand.Collator;
import net.osmand.CollatorStringMatcher; import net.osmand.CollatorStringMatcher;
import net.osmand.CollatorStringMatcher.StringMatcherMode; import net.osmand.CollatorStringMatcher.StringMatcherMode;
import net.osmand.Location;
import net.osmand.OsmAndCollator; import net.osmand.OsmAndCollator;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.ResultMatcher; import net.osmand.ResultMatcher;
import net.osmand.StringMatcher; import net.osmand.StringMatcher;
import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion; import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion;
import net.osmand.binary.BinaryMapAddressReaderAdapter.CitiesBlock; import net.osmand.binary.BinaryMapAddressReaderAdapter.CitiesBlock;
import net.osmand.binary.BinaryMapIndexReader.SearchPoiTypeFilter;
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion; import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion;
@ -43,10 +60,16 @@ import net.osmand.data.MapObject;
import net.osmand.data.Street; import net.osmand.data.Street;
import net.osmand.data.TransportRoute; import net.osmand.data.TransportRoute;
import net.osmand.data.TransportStop; import net.osmand.data.TransportStop;
import net.osmand.osm.edit.Way;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.google.protobuf.CodedInputStream; import com.google.protobuf.CodedInputStream;
import com.google.protobuf.WireFormat; import com.google.protobuf.WireFormat;
@ -1317,6 +1340,8 @@ public class BinaryMapIndexReader {
return buildSearchRequest(sleft, sright, stop, sbottom, zoom, searchFilter, null); return buildSearchRequest(sleft, sright, stop, sbottom, zoom, searchFilter, null);
} }
public static SearchRequest<BinaryMapDataObject> buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchFilter searchFilter, public static SearchRequest<BinaryMapDataObject> buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchFilter searchFilter,
ResultMatcher<BinaryMapDataObject> resultMatcher){ ResultMatcher<BinaryMapDataObject> resultMatcher){
SearchRequest<BinaryMapDataObject> request = new SearchRequest<BinaryMapDataObject>(); SearchRequest<BinaryMapDataObject> request = new SearchRequest<BinaryMapDataObject>();
@ -1345,6 +1370,55 @@ public class BinaryMapIndexReader {
return request; return request;
} }
public static SearchRequest<Amenity> buildSearchPoiRequest(List<Location> route, double radius,
SearchPoiTypeFilter poiTypeFilter, ResultMatcher<Amenity> resultMatcher) {
SearchRequest<Amenity> request = new SearchRequest<Amenity>();
float coeff = (float) (radius / MapUtils.getTileDistanceWidth(SearchRequest.ZOOM_TO_SEARCH_POI));
TIntObjectHashMap<List<Location>> zooms = new TIntObjectHashMap<List<Location>>();
for(int i = 1; i < route.size(); i++) {
Location cr = route.get(i);
Location pr = route.get(i - 1);
double tx = MapUtils.getTileNumberX(SearchRequest.ZOOM_TO_SEARCH_POI, cr.getLongitude());
double ty = MapUtils.getTileNumberY(SearchRequest.ZOOM_TO_SEARCH_POI, cr.getLatitude());
double px = MapUtils.getTileNumberX(SearchRequest.ZOOM_TO_SEARCH_POI, pr.getLongitude());
double py = MapUtils.getTileNumberY(SearchRequest.ZOOM_TO_SEARCH_POI, pr.getLatitude());
double topLeftX = Math.min(tx, px) - coeff;
double topLeftY = Math.min(ty, py) - coeff;
double bottomRightX = Math.max(tx, px) + coeff;
double bottomRightY = Math.max(ty, py) + coeff;
for(int x = (int) topLeftX; x <= bottomRightX; x++) {
for(int y = (int) topLeftY; y <= bottomRightY; y++) {
int hash = (x << SearchRequest.ZOOM_TO_SEARCH_POI) + y;
if(!zooms.containsKey(hash)) {
zooms.put(hash, new LinkedList<Location>());
}
List<Location> ll = zooms.get(hash);
ll.add(pr);
ll.add(cr);
}
}
}
int sleft = 0, sright = Integer.MAX_VALUE, stop = 0, sbottom = Integer.MAX_VALUE;
for(int vl : zooms.keys()) {
int x = (vl >> SearchRequest.ZOOM_TO_SEARCH_POI) << (31 - SearchRequest.ZOOM_TO_SEARCH_POI);
int y = (vl & ((1 << SearchRequest.ZOOM_TO_SEARCH_POI) -1)) << (31 - SearchRequest.ZOOM_TO_SEARCH_POI);
sleft = Math.min(x, sleft);
stop = Math.min(y, stop);
sbottom = Math.max(y, sbottom);
sright = Math.max(x, sright);
}
request.radius = radius;
request.left = sleft;
request.zoom = -1;
request.right = sright;
request.top = stop;
request.bottom = sbottom;
request.tiles = zooms;
request.poiTypeFilter = poiTypeFilter;
request.resultMatcher = resultMatcher;
return request;
}
public static SearchRequest<Amenity> buildSearchPoiRequest(int sleft, int sright, int stop, int sbottom, int zoom, public static SearchRequest<Amenity> buildSearchPoiRequest(int sleft, int sright, int stop, int sbottom, int zoom,
SearchPoiTypeFilter poiTypeFilter, ResultMatcher<Amenity> matcher){ SearchPoiTypeFilter poiTypeFilter, ResultMatcher<Amenity> matcher){
@ -1426,6 +1500,7 @@ public class BinaryMapIndexReader {
} }
public static class SearchRequest<T> { public static class SearchRequest<T> {
public final static int ZOOM_TO_SEARCH_POI = 16;
private List<T> searchResults = new ArrayList<T>(); private List<T> searchResults = new ArrayList<T>();
private boolean land = false; private boolean land = false;
private boolean ocean = false; private boolean ocean = false;
@ -1443,6 +1518,11 @@ public class BinaryMapIndexReader {
int zoom = 15; int zoom = 15;
int limit = -1; int limit = -1;
// search on the path
// stores tile of 16 index and pairs (even length always) of points intersecting tile
TIntObjectHashMap<List<Location>> tiles = null;
double radius = -1;
String nameQuery = null; String nameQuery = null;
@ -1469,6 +1549,12 @@ public class BinaryMapIndexReader {
protected SearchRequest(){ protected SearchRequest(){
} }
public int getTileHashOnPath(double lat, double lon) {
int x = (int) MapUtils.getTileNumberX(SearchRequest.ZOOM_TO_SEARCH_POI, lon);
int y = (int) MapUtils.getTileNumberY(SearchRequest.ZOOM_TO_SEARCH_POI, lat);
return (x << SearchRequest.ZOOM_TO_SEARCH_POI) | y;
}
public boolean publish(T obj){ public boolean publish(T obj){
if(resultMatcher == null || resultMatcher.publish(obj)){ if(resultMatcher == null || resultMatcher.publish(obj)){
@ -1769,7 +1855,7 @@ public class BinaryMapIndexReader {
} }
private static boolean testMapSearch = true; private static boolean testMapSearch = false;
private static boolean testAddressSearch = false; private static boolean testAddressSearch = false;
private static boolean testPoiSearch = false; private static boolean testPoiSearch = false;
private static boolean testTransportSearch = false; private static boolean testTransportSearch = false;
@ -1805,17 +1891,120 @@ public class BinaryMapIndexReader {
PoiRegion poiRegion = reader.getPoiIndexes().get(0); PoiRegion poiRegion = reader.getPoiIndexes().get(0);
testPoiSearch(reader, poiRegion); testPoiSearch(reader, poiRegion);
testPoiSearchByName(reader); testPoiSearchByName(reader);
testSearchOnthePath(reader);
} }
println("MEMORY " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); //$NON-NLS-1$ println("MEMORY " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); //$NON-NLS-1$
println("Time " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ println("Time " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
} }
private static void testSearchOnthePath(BinaryMapIndexReader reader) throws IOException {
float radius = 1000;
long now = System.currentTimeMillis();
println("Searching poi on the path...");
final List<Location> locations = readGPX(new File(
""));
SearchRequest<Amenity> req = buildSearchPoiRequest(locations, radius, new SearchPoiTypeFilter() {
@Override
public boolean accept(AmenityType type, String subcategory) {
if (type == AmenityType.SHOP && subcategory.contains("super")) {
return true;
}
return false;
}
}, null);
req.zoom = -1;
List<Amenity> results = reader.searchPoi(req);
int k = 0;
println("Search done in " + (System.currentTimeMillis() - now) + " ms ");
now = System.currentTimeMillis();
for (Amenity a : results) {
final float dds = dist(a.getLocation(), locations);
if (dds <= radius) {
println("+ " + a.getType() + " " + a.getSubType() + " Dist " + dds + " (=" + (float)a.getDeviateDistance() + ") " + a.getName() + " " + a.getLocation());
k++;
} else {
println(a.getType() + " " + a.getSubType() + " Dist " + dds + " " + a.getName() + " " + a.getLocation());
}
}
println("Filtered in " + (System.currentTimeMillis() - now) + "ms " + k + " of " + results.size());
}
private static float dist(LatLon l, List<Location> locations) {
float dist = Float.POSITIVE_INFINITY;
for(int i = 1; i < locations.size(); i++){
dist = Math.min(dist,(float) MapUtils.getOrthogonalDistance(l.getLatitude(), l.getLongitude(),
locations.get(i-1).getLatitude(), locations.get(i-1).getLongitude(),
locations.get(i).getLatitude(), locations.get(i).getLongitude()));
}
return dist;
}
private static Reader getUTF8Reader(InputStream f) throws IOException {
BufferedInputStream bis = new BufferedInputStream(f);
assert bis.markSupported();
bis.mark(3);
boolean reset = true;
byte[] t = new byte[3];
bis.read(t);
if (t[0] == ((byte) 0xef) && t[1] == ((byte) 0xbb) && t[2] == ((byte) 0xbf)) {
reset = false;
}
if (reset) {
bis.reset();
}
return new InputStreamReader(bis, "UTF-8");
}
private static List<Location> readGPX(File f) {
List<Location> res = new ArrayList<Location>();
try {
StringBuilder content = new StringBuilder();
BufferedReader reader = new BufferedReader(getUTF8Reader(new FileInputStream(f)));
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder dom = factory.newDocumentBuilder();
// {
// String s = null;
// boolean fist = true;
// while ((s = reader.readLine()) != null) {
// if (fist) {
// fist = false;
// }
// content.append(s).append("\n");
// }
// }
// Document doc = dom.parse(new InputSource(new StringReader(content.toString())));
Document doc = dom.parse(new InputSource(reader));
NodeList list = doc.getElementsByTagName("trkpt");
Way w = new Way(-1);
for (int i = 0; i < list.getLength(); i++) {
Element item = (Element) list.item(i);
try {
double lon = Double.parseDouble(item.getAttribute("lon"));
double lat = Double.parseDouble(item.getAttribute("lat"));
final Location o = new Location("");
o.setLatitude(lat);
o.setLongitude(lon);
res.add(o);
} catch (NumberFormatException e) {
}
}
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
} catch (SAXException e) {
throw new RuntimeException(e);
}
return res;
}
private static void testPoiSearchByName(BinaryMapIndexReader reader) throws IOException { private static void testPoiSearchByName(BinaryMapIndexReader reader) throws IOException {
println("Searching by name..."); println("Searching by name...");
int tileZ = 31 - 14; SearchRequest<Amenity> req = buildSearchPoiRequest(0, 0, "roch",
SearchRequest<Amenity> req = buildSearchPoiRequest(sleft/2+sright/2, stop/2+sbottom/2, "kol", 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, null);
sleft - 1<<tileZ, sleft + 1<<tileZ, stop - 1<<tileZ, stop + 1<<tileZ, null);
reader.searchPoiByName(req); reader.searchPoiByName(req);
for (Amenity a : req.getSearchResults()) { for (Amenity a : req.getSearchResults()) {
println(a.getType() + " " + a.getSubType() + " " + a.getName() + " " + a.getLocation()); println(a.getType() + " " + a.getSubType() + " " + a.getName() + " " + a.getLocation());
@ -2107,5 +2296,7 @@ public class BinaryMapIndexReader {
routeAdapter.initRouteRegion(routeReg); routeAdapter.initRouteRegion(routeReg);
} }
} }
} }

View file

@ -15,11 +15,13 @@ import java.util.List;
import net.osmand.Collator; import net.osmand.Collator;
import net.osmand.CollatorStringMatcher; import net.osmand.CollatorStringMatcher;
import net.osmand.CollatorStringMatcher.StringMatcherMode; import net.osmand.CollatorStringMatcher.StringMatcherMode;
import net.osmand.Location;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.binary.BinaryMapIndexReader.SearchRequest; import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
import net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData; import net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData;
import net.osmand.data.Amenity; import net.osmand.data.Amenity;
import net.osmand.data.AmenityType; import net.osmand.data.AmenityType;
import net.osmand.data.LatLon;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import net.sf.junidecode.Junidecode; import net.sf.junidecode.Junidecode;
@ -588,6 +590,17 @@ public class BinaryMapPoiReaderAdapter {
} }
} }
private float dist(LatLon l, List<Location> locations) {
float dist = Float.POSITIVE_INFINITY;
// Special iterations because points stored by pairs!
for (int i = 1; i < locations.size(); i += 2) {
dist = Math.min(dist, (float) MapUtils.getOrthogonalDistance(
l.getLatitude(), l.getLongitude(),
locations.get(i - 1).getLatitude(), locations.get(i - 1).getLongitude(),
locations.get(i).getLatitude(), locations.get(i).getLongitude()));
}
return dist;
}
private Amenity readPoiPoint(int left31, int right31, int top31, int bottom31, private Amenity readPoiPoint(int left31, int right31, int top31, int bottom31,
int px, int py, int zoom, SearchRequest<Amenity> req, PoiRegion region, boolean checkBounds) throws IOException { int px, int py, int zoom, SearchRequest<Amenity> req, PoiRegion region, boolean checkBounds) throws IOException {
Amenity am = null; Amenity am = null;
@ -609,6 +622,19 @@ public class BinaryMapPoiReaderAdapter {
am.setEnName(Junidecode.unidecode(am.getName())); am.setEnName(Junidecode.unidecode(am.getName()));
} }
req.numberOfAcceptedObjects++; req.numberOfAcceptedObjects++;
if (req.radius > 0) {
LatLon loc = am.getLocation();
List<Location> locs = req.tiles.get(req.getTileHashOnPath(loc.getLatitude(), loc.getLongitude()));
if (locs == null) {
return null;
}
float d = dist(am.getLocation(), locs);
if (d > req.radius) {
return null;
} else {
am.setDeviateDistance(d);
}
}
return am; return am;
case OsmandOdb.OsmAndPoiBoxDataAtom.DX_FIELD_NUMBER : case OsmandOdb.OsmAndPoiBoxDataAtom.DX_FIELD_NUMBER :
x = (codedIS.readSInt32() + (px << (24 - zoom))) << 7; x = (codedIS.readSInt32() + (px << (24 - zoom))) << 7;
@ -793,16 +819,16 @@ public class BinaryMapPoiReaderAdapter {
case OsmandOdb.OsmAndPoiBox.SUBBOXES_FIELD_NUMBER: { case OsmandOdb.OsmAndPoiBox.SUBBOXES_FIELD_NUMBER: {
int x = dx + (px << (zoom - pzoom)); int x = dx + (px << (zoom - pzoom));
int y = dy + (py << (zoom - pzoom)); int y = dy + (py << (zoom - pzoom));
if(checkBox){ if (checkBox) {
int xL = x << (31 - zoom); int xL = x << (31 - zoom);
int xR = ((x + 1) << (31 - zoom)) - 1; int xR = ((x + 1) << (31 - zoom)) - 1;
int yT = y << (31 - zoom); int yT = y << (31 - zoom);
int yB = ((y + 1) << (31 - zoom)) - 1; int yB = ((y + 1) << (31 - zoom)) - 1;
// check intersection // check intersection
if(left31 > xR || xL > right31 || bottom31 < yT || yB < top31){ if (left31 > xR || xL > right31 || bottom31 < yT || yB < top31) {
codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
return false; return false;
} }
req.numberOfAcceptedSubtrees++; req.numberOfAcceptedSubtrees++;
checkBox = false; checkBox = false;
} }
@ -824,10 +850,20 @@ public class BinaryMapPoiReaderAdapter {
int x = dx + (px << (zoom - pzoom)); int x = dx + (px << (zoom - pzoom));
int y = dy + (py << (zoom - pzoom)); int y = dy + (py << (zoom - pzoom));
long l = ((((x << zoom) | y) << 5) | zoom); long l = ((((x << zoom) | y) << 5) | zoom);
offsetsMap.put(readInt(), l); boolean read = true;
if(skipTiles != null && zoom >= zoomToSkip){ if(req.tiles != null) {
long val = ((((long) x) >> (zoom - zoomToSkip)) << zoomToSkip) | (((long) y) >> (zoom - zoomToSkip)); int zx = x << (SearchRequest.ZOOM_TO_SEARCH_POI - zoom);
skipTiles.add(val); int zy = y << (SearchRequest.ZOOM_TO_SEARCH_POI - zoom);
read = req.tiles.contains((zx << SearchRequest.ZOOM_TO_SEARCH_POI) + zy);
}
int offset = readInt();
if (read) {
offsetsMap.put(offset, l);
if (skipTiles != null && zoom >= zoomToSkip) {
long val = ((((long) x) >> (zoom - zoomToSkip)) << zoomToSkip)
| (((long) y) >> (zoom - zoomToSkip));
skipTiles.add(val);
}
} }
} break; } break;
default: default:

View file

@ -18,6 +18,7 @@ public class Amenity extends MapObject {
// duplicate for fast access // duplicate for fast access
private String openingHours; private String openingHours;
private Map<String, String> additionalInfo; private Map<String, String> additionalInfo;
private double deviateDistance; // for search on path
public Amenity(){ public Amenity(){
} }
@ -62,6 +63,13 @@ public class Amenity extends MapObject {
openingHours = additionalInfo.get(OPENING_HOURS); openingHours = additionalInfo.get(OPENING_HOURS);
} }
public double getDeviateDistance() {
return deviateDistance;
}
public void setDeviateDistance(double deviateDistance) {
this.deviateDistance = deviateDistance;
}
public void setAdditionalInfo(String tag, String value) { public void setAdditionalInfo(String tag, String value) {
if(this.additionalInfo == null){ if(this.additionalInfo == null){

View file

@ -220,6 +220,12 @@ public class MapUtils {
} }
public static double getTileDistanceWidth(float zoom) {
LatLon ll = new LatLon(30, MapUtils.getLongitudeFromTile(zoom, 0));
LatLon ll2 = new LatLon(30, MapUtils.getLongitudeFromTile(zoom, 1));
return getDistance(ll, ll2) ;
}
public static double getLongitudeFromTile(float zoom, double x) { public static double getLongitudeFromTile(float zoom, double x) {
return x / getPowZoom(zoom) * 360.0 - 180.0; return x / getPowZoom(zoom) * 360.0 - 180.0;
} }

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<resources> <resources>
<string name="app_name">OsmAnd~</string> <string name="app_name">OsmAnd~</string>
<string name="app_version">1.8 alpha</string> <string name="app_version">1.9 alpha</string>
<!-- Not translatable --> <!-- Not translatable -->
<string name="ga_api_key">UA-28342846-2</string> <string name="ga_api_key">UA-28342846-2</string>
<string name="ga_dispatchPeriod">10</string> <string name="ga_dispatchPeriod">10</string>

View file

@ -820,6 +820,7 @@ public class MapActivityActions implements DialogProvider {
} else { } else {
routingHelper.setRoutePlanningMode(true); routingHelper.setRoutePlanningMode(true);
routingHelper.setFollowingMode(false); routingHelper.setFollowingMode(false);
routingHelper.setPauseNaviation(true);
} }
mapActivity.getMapViewTrackingUtilities().switchToRoutePlanningMode(); mapActivity.getMapViewTrackingUtilities().switchToRoutePlanningMode();
mapActivity.refreshMap(); mapActivity.refreshMap();

View file

@ -39,6 +39,7 @@ public class SettingsMonitoringActivity extends SettingsBaseActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_PROGRESS);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setSupportProgressBarIndeterminateVisibility(false); setSupportProgressBarIndeterminateVisibility(false);
getSupportActionBar().setTitle(R.string.monitoring_settings); getSupportActionBar().setTitle(R.string.monitoring_settings);

View file

@ -2,6 +2,7 @@ package net.osmand.plus.resources;
import java.util.List; import java.util.List;
import net.osmand.Location;
import net.osmand.ResultMatcher; import net.osmand.ResultMatcher;
import net.osmand.data.Amenity; import net.osmand.data.Amenity;
import net.osmand.plus.PoiFilter; import net.osmand.plus.PoiFilter;
@ -20,5 +21,7 @@ public interface AmenityIndexRepository {
public List<Amenity> searchAmenities(int stop, int sleft, int sbottom, int sright, int zoom, PoiFilter filter, List<Amenity> amenities, public List<Amenity> searchAmenities(int stop, int sleft, int sbottom, int sright, int zoom, PoiFilter filter, List<Amenity> amenities,
ResultMatcher<Amenity> matcher); ResultMatcher<Amenity> matcher);
public List<Amenity> searchAmenitiesOnThePath(List<Location> locations, double radius, PoiFilter filter, ResultMatcher<Amenity> matcher);
} }

View file

@ -6,6 +6,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import net.osmand.Location;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.ResultMatcher; import net.osmand.ResultMatcher;
import net.osmand.binary.BinaryMapIndexReader; import net.osmand.binary.BinaryMapIndexReader;
@ -105,5 +106,30 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository {
} }
return amenities; return amenities;
} }
@Override
public synchronized List<Amenity> searchAmenitiesOnThePath(List<Location> locations, double radius, final PoiFilter filter, ResultMatcher<Amenity> matcher) {
long now = System.currentTimeMillis();
SearchPoiTypeFilter poiTypeFilter = new SearchPoiTypeFilter(){
@Override
public boolean accept(AmenityType type, String subcategory) {
return filter.acceptTypeSubtype(type, subcategory);
}
};
List<Amenity> result = null;
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(locations, radius,
poiTypeFilter, filter == null ? matcher : filter.getResultMatcher(matcher));
try {
result = index.searchPoi(req);
} catch (IOException e) {
log.error("Error searching amenities", e); //$NON-NLS-1$
return result;
}
if (log.isDebugEnabled() && result != null) {
log.debug(String.format("Search done in %s ms found %s.", (System.currentTimeMillis() - now), result.size())); //$NON-NLS-1$
}
return result;
}
} }

View file

@ -29,7 +29,6 @@ public class AsyncLoadingThread extends Thread {
private static final Log log = PlatformUtil.getLog(AsyncLoadingThread.class); private static final Log log = PlatformUtil.getLog(AsyncLoadingThread.class);
private Handler asyncLoadingPoi;
private Handler asyncLoadingTransport; private Handler asyncLoadingTransport;
Stack<Object> requests = new Stack<Object>(); Stack<Object> requests = new Stack<Object>();
@ -43,11 +42,7 @@ public class AsyncLoadingThread extends Thread {
this.resourceManger = resourceManger; this.resourceManger = resourceManger;
} }
private void startPoiLoadingThread() {
HandlerThread h = new HandlerThread("Loading poi");
h.start();
asyncLoadingPoi = new Handler(h.getLooper());
}
private void startTransportLoadingThread() { private void startTransportLoadingThread() {
HandlerThread h = new HandlerThread("Loading transport"); HandlerThread h = new HandlerThread("Loading transport");
@ -61,6 +56,8 @@ public class AsyncLoadingThread extends Thread {
progress = BusyIndicator.STATUS_GREEN; progress = BusyIndicator.STATUS_GREEN;
} else if (resourceManger.getContext().getRoutingHelper().isRouteBeingCalculated()) { } else if (resourceManger.getContext().getRoutingHelper().isRouteBeingCalculated()) {
progress = BusyIndicator.STATUS_ORANGE; progress = BusyIndicator.STATUS_ORANGE;
} else if (resourceManger.isSearchAmenitiesInProgress()) {
progress = BusyIndicator.STATUS_BLACK;
} else if (!requests.isEmpty()) { } else if (!requests.isEmpty()) {
progress = BusyIndicator.STATUS_BLACK; progress = BusyIndicator.STATUS_BLACK;
} else if (transportLoadRequest != null && transportLoadRequest.isRunning()) { } else if (transportLoadRequest != null && transportLoadRequest.isRunning()) {

View file

@ -1,8 +1,6 @@
package net.osmand.plus.resources; package net.osmand.plus.resources;
import gnu.trove.list.array.TIntArrayList;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -23,6 +21,7 @@ import net.osmand.AndroidUtils;
import net.osmand.GeoidAltitudeCorrection; import net.osmand.GeoidAltitudeCorrection;
import net.osmand.IProgress; import net.osmand.IProgress;
import net.osmand.IndexConstants; import net.osmand.IndexConstants;
import net.osmand.Location;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.ResultMatcher; import net.osmand.ResultMatcher;
import net.osmand.binary.BinaryMapIndexReader; import net.osmand.binary.BinaryMapIndexReader;
@ -271,6 +270,7 @@ public class ResourceManager {
protected StringBuilder builder = new StringBuilder(40); protected StringBuilder builder = new StringBuilder(40);
protected char[] tileId = new char[120]; protected char[] tileId = new char[120];
private GeoidAltitudeCorrection geoidAltitudeCorrection; private GeoidAltitudeCorrection geoidAltitudeCorrection;
private boolean searchAmenitiesInProgress;
public synchronized String calculateTileId(ITileSource map, int x, int y, int zoom) { public synchronized String calculateTileId(ITileSource map, int x, int y, int zoom) {
builder.setLength(0); builder.setLength(0);
@ -719,41 +719,47 @@ public class ResourceManager {
public List<Amenity> searchAmenities(PoiFilter filter, public List<Amenity> searchAmenities(PoiFilter filter,
double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, final ResultMatcher<Amenity> matcher) { double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, final ResultMatcher<Amenity> matcher) {
final List<Amenity> amenities = new ArrayList<Amenity>(); final List<Amenity> amenities = new ArrayList<Amenity>();
if(filter instanceof NameFinderPoiFilter || filter instanceof SearchByNameFilter){ searchAmenitiesInProgress = true;
List<Amenity> tempResults = filter instanceof NameFinderPoiFilter ? try {
((NameFinderPoiFilter) filter).getSearchedAmenities() :((SearchByNameFilter) filter).getSearchedAmenities() ; if (filter instanceof NameFinderPoiFilter || filter instanceof SearchByNameFilter) {
for(Amenity a : tempResults){ List<Amenity> tempResults = filter instanceof NameFinderPoiFilter ? ((NameFinderPoiFilter) filter)
LatLon l = a.getLocation(); .getSearchedAmenities() : ((SearchByNameFilter) filter).getSearchedAmenities();
if(l != null && l.getLatitude() <= topLatitude && l.getLatitude() >= bottomLatitude && l.getLongitude() >= leftLongitude && l.getLongitude() <= rightLongitude){ for (Amenity a : tempResults) {
if(matcher.publish(a) ){ LatLon l = a.getLocation();
amenities.add(a); if (l != null && l.getLatitude() <= topLatitude && l.getLatitude() >= bottomLatitude
&& l.getLongitude() >= leftLongitude && l.getLongitude() <= rightLongitude) {
if (matcher.publish(a)) {
amenities.add(a);
}
}
}
} else {
final String filterByName = filter.getFilterByName();
for (AmenityIndexRepository index : amenityRepositories) {
if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) {
index.searchAmenities(MapUtils.get31TileNumberY(topLatitude),
MapUtils.get31TileNumberX(leftLongitude), MapUtils.get31TileNumberY(bottomLatitude),
MapUtils.get31TileNumberX(rightLongitude), zoom, filter, amenities,
new ResultMatcher<Amenity>() {
@Override
public boolean publish(Amenity object) {
if (checkNameFilter(object, filterByName)) {
return matcher.publish(object);
}
return false;
}
@Override
public boolean isCancelled() {
return matcher.isCancelled();
}
});
} }
} }
} }
} else { } finally {
final String filterByName = filter.getFilterByName(); searchAmenitiesInProgress = false;
for (AmenityIndexRepository index : amenityRepositories) {
if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) {
index.searchAmenities(MapUtils.get31TileNumberY(topLatitude),
MapUtils.get31TileNumberX(leftLongitude), MapUtils.get31TileNumberY(bottomLatitude),
MapUtils.get31TileNumberX(rightLongitude), -1, filter, amenities,
new ResultMatcher<Amenity>() {
@Override
public boolean publish(Amenity object) {
if (checkNameFilter(object, filterByName)) {
return matcher.publish(object);
}
return false;
}
@Override
public boolean isCancelled() {
return matcher.isCancelled();
}
});
}
}
} }
return amenities; return amenities;
} }
@ -814,33 +820,40 @@ public class ResourceManager {
return map; return map;
} }
public void searchAmenitiesOnTheArea(TIntArrayList tiles16z, PoiFilter filter, ResultMatcher<Amenity> results) { public List<Amenity> searchAmenitiesOnThePath(List<Location> locations, double radius, PoiFilter filter, ResultMatcher<Amenity> matcher) {
if (tiles16z.size() > 0) { searchAmenitiesInProgress = true;
int z = 16; final List<Amenity> amenities = new ArrayList<Amenity>();
int x = tiles16z.get(0) >> z; try {
int y = tiles16z.get(0) & ((1 << z) - 1); if (locations != null && locations.size() > 0) {
List<AmenityIndexRepository> repos = new ArrayList<AmenityIndexRepository>(); List<AmenityIndexRepository> repos = new ArrayList<AmenityIndexRepository>();
double topLatitude = MapUtils.getLatitudeFromTile(z, y); double topLatitude = locations.get(0).getLatitude();
double bottomLatitude = MapUtils.getLatitudeFromTile(z, y + 1); double bottomLatitude = locations.get(0).getLatitude();
double leftLongitude = MapUtils.getLongitudeFromTile(z, x); double leftLongitude = locations.get(0).getLongitude();
double rightLongitude = MapUtils.getLongitudeFromTile(z, x + 1); double rightLongitude = locations.get(0).getLongitude();
for (int k = 1; k < tiles16z.size(); k++) { for (Location l : locations) {
topLatitude = Math.max(topLatitude, MapUtils.getLatitudeFromTile(z, y)); topLatitude = Math.max(topLatitude, l.getLatitude());
bottomLatitude = Math.min(bottomLatitude, MapUtils.getLatitudeFromTile(z, y + 1)); bottomLatitude = Math.min(bottomLatitude, l.getLatitude());
leftLongitude = Math.min(leftLongitude, MapUtils.getLongitudeFromTile(z, x)); leftLongitude = Math.min(leftLongitude, l.getLongitude());
rightLongitude = Math.max(rightLongitude, MapUtils.getLongitudeFromTile(z, x + 1)); rightLongitude = Math.max(rightLongitude, l.getLongitude());
} }
for (AmenityIndexRepository index : amenityRepositories) { for (AmenityIndexRepository index : amenityRepositories) {
if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) { if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) {
repos.add(index); repos.add(index);
} }
} }
if (!repos.isEmpty()) { if (!repos.isEmpty()) {
for(AmenityIndexRepository r : repos) { for (AmenityIndexRepository r : repos) {
// r.searchAmenities(stop, sleft, sbottom, sright, zoom, filter, amenities, matcher) List<Amenity> res = r.searchAmenitiesOnThePath(locations, radius, filter, matcher);
if (res != null) {
amenities.addAll(res);
}
}
} }
} }
}finally {
searchAmenitiesInProgress = false;
} }
return amenities;
} }
////////////////////////////////////////////// Working with address /////////////////////////////////////////// ////////////////////////////////////////////// Working with address ///////////////////////////////////////////
@ -896,6 +909,10 @@ public class ResourceManager {
renderer.interruptLoadingMap(); renderer.interruptLoadingMap();
} }
public boolean isSearchAmenitiesInProgress() {
return searchAmenitiesInProgress;
}
public MapRenderRepositories getRenderer() { public MapRenderRepositories getRenderer() {
return renderer; return renderer;
} }

View file

@ -50,8 +50,8 @@ public class RoutingHelper {
private OsmandApplication app; private OsmandApplication app;
private boolean isFollowingMode = false; private boolean isFollowingMode = false;
private boolean isRoutePlanningMode = false; private boolean isRoutePlanningMode = false;
private boolean isPauseNavigation = false;
private GPXRouteParamsBuilder currentGPXRoute = null; private GPXRouteParamsBuilder currentGPXRoute = null;
@ -79,6 +79,7 @@ public class RoutingHelper {
private RouteCalculationProgressCallback progressRoute; private RouteCalculationProgressCallback progressRoute;
private SearchOnTheRouteHelper searchOnTheRouteHelper; private SearchOnTheRouteHelper searchOnTheRouteHelper;
// private ProgressBar progress; // private ProgressBar progress;
// private Handler progressHandler; // private Handler progressHandler;
@ -101,8 +102,17 @@ public class RoutingHelper {
return isFollowingMode; return isFollowingMode;
} }
public void setPauseNaviation(boolean b) {
this.isPauseNavigation = b;
}
public boolean isPauseNavigation() {
return isPauseNavigation;
}
public void setFollowingMode(boolean follow) { public void setFollowingMode(boolean follow) {
isFollowingMode = follow; isFollowingMode = follow;
isPauseNavigation = false;
if (!follow) { if (!follow) {
if (app.getNavigationService() != null) { if (app.getNavigationService() != null) {
app.getNavigationService().stopIfNeeded(app, NavigationService.USED_BY_NAVIGATION); app.getNavigationService().stopIfNeeded(app, NavigationService.USED_BY_NAVIGATION);
@ -932,4 +942,5 @@ public class RoutingHelper {
} }
} }
} }

View file

@ -21,6 +21,10 @@ import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.render.RenderingIcons; import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.resources.ResourceManager; import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.IRouteInformationListener;
import net.osmand.plus.routing.RoutingHelper.RouteCalculationProgressCallback;
import net.osmand.plus.views.MapTextLayer.MapTextProvider; import net.osmand.plus.views.MapTextLayer.MapTextProvider;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.AlertDialog.Builder; import android.app.AlertDialog.Builder;
@ -36,7 +40,7 @@ import android.net.Uri;
import android.widget.Toast; import android.widget.Toast;
public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider, public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider,
MapTextProvider<Amenity> { MapTextProvider<Amenity>, IRouteInformationListener {
private static final int startZoom = 10; private static final int startZoom = 10;
public static final org.apache.commons.logging.Log log = PlatformUtil.getLog(POIMapLayer.class); public static final org.apache.commons.logging.Log log = PlatformUtil.getLog(POIMapLayer.class);
@ -48,15 +52,20 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
private final static int MAXIMUM_SHOW_AMENITIES = 5; private final static int MAXIMUM_SHOW_AMENITIES = 5;
private ResourceManager resourceManager; private ResourceManager resourceManager;
private RoutingHelper routingHelper;
private PoiFilter filter; private PoiFilter filter;
private MapTextLayer mapTextLayer; private MapTextLayer mapTextLayer;
/// cache for displayed POI /// cache for displayed POI
// Work with cache (for map copied from AmenityIndexRepositoryOdb) // Work with cache (for map copied from AmenityIndexRepositoryOdb)
private MapLayerData<List<Amenity>> data; private MapLayerData<List<Amenity>> data;
private boolean path = false;
private double radius = 100;
public POIMapLayer(MapActivity activity) { public POIMapLayer(MapActivity activity) {
routingHelper = activity.getRoutingHelper();
routingHelper.addListener(this);
data = new OsmandMapLayer.MapLayerData<List<Amenity>>() { data = new OsmandMapLayer.MapLayerData<List<Amenity>>() {
{ {
ZOOM_THRESHOLD = 0; ZOOM_THRESHOLD = 0;
@ -70,19 +79,24 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
@Override @Override
protected List<Amenity> calculateResult(RotatedTileBox tileBox) { protected List<Amenity> calculateResult(RotatedTileBox tileBox) {
QuadRect latLonBounds = tileBox.getLatLonBounds(); QuadRect latLonBounds = tileBox.getLatLonBounds();
return resourceManager.searchAmenities(filter, latLonBounds.top, latLonBounds.left, if(path) {
latLonBounds.bottom, latLonBounds.right, tileBox.getZoom(), new ResultMatcher<Amenity>() { RouteCalculationResult result = routingHelper.getRoute();
return resourceManager.searchAmenitiesOnThePath(result.getImmutableAllLocations(), radius, filter, null);
} else {
return resourceManager.searchAmenities(filter, latLonBounds.top, latLonBounds.left,
latLonBounds.bottom, latLonBounds.right, tileBox.getZoom(), new ResultMatcher<Amenity>() {
@Override @Override
public boolean publish(Amenity object) { public boolean publish(Amenity object) {
return true; return true;
} }
@Override @Override
public boolean isCancelled() { public boolean isCancelled() {
return isInterrupted(); return isInterrupted();
} }
}); });
}
} }
}; };
} }
@ -92,9 +106,21 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
} }
public void setFilter(PoiFilter filter) { public void setFilter(PoiFilter filter) {
// TODO parameter
this.filter = filter; this.filter = filter;
// this.radius = 100;
// this.path = true;
this.path = false;
data.clearCache(); data.clearCache();
} }
public void setFilter(PoiFilter filter, double radius) {
this.filter = filter;
this.radius = radius;
this.path = true;
data.clearCache();
}
public void getAmenityFromPoint(RotatedTileBox tb, PointF point, List<? super Amenity> am) { public void getAmenityFromPoint(RotatedTileBox tb, PointF point, List<? super Amenity> am) {
List<Amenity> objects = data.getResults(); List<Amenity> objects = data.getResults();
@ -224,6 +250,7 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
@Override @Override
public void destroyLayer() { public void destroyLayer() {
routingHelper.removeListener(this);
} }
@Override @Override
@ -317,7 +344,7 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
} }
return null; return null;
} }
@Override @Override
public LatLon getTextLocation(Amenity o) { public LatLon getTextLocation(Amenity o) {
return o.getLocation(); return o.getLocation();
@ -333,4 +360,16 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
return o.getName(view.getSettings().usingEnglishNames()); return o.getName(view.getSettings().usingEnglishNames());
} }
@Override
public void newRouteIsCalculated(boolean newRoute) {
if(path) {
data.clearCache();
}
}
@Override
public void routeWasCancelled() {
}
} }

View file

@ -111,7 +111,7 @@ public class MapNavigateControl extends MapControls {
startNavigation(); startNavigation();
} }
}); });
if(!mapActivity.getRoutingHelper().isFollowingMode()) { if(!mapActivity.getRoutingHelper().isFollowingMode() && !mapActivity.getRoutingHelper().isPauseNavigation()) {
startCounter(); startCounter();
} }
} }