diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java index 08a2b4a76a..67c1983ae2 100644 --- a/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java @@ -1,31 +1,48 @@ package net.osmand.binary; +import gnu.trove.iterator.TIntIterator; import gnu.trove.list.array.TIntArrayList; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; 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.InputStream; +import java.io.InputStreamReader; import java.io.RandomAccessFile; +import java.io.Reader; +import java.io.StringReader; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; 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.CollatorStringMatcher; import net.osmand.CollatorStringMatcher.StringMatcherMode; +import net.osmand.Location; import net.osmand.OsmAndCollator; import net.osmand.PlatformUtil; import net.osmand.ResultMatcher; import net.osmand.StringMatcher; import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion; 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.BinaryMapRouteReaderAdapter.RouteRegion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion; @@ -43,10 +60,16 @@ import net.osmand.data.MapObject; import net.osmand.data.Street; import net.osmand.data.TransportRoute; import net.osmand.data.TransportStop; +import net.osmand.osm.edit.Way; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; 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.WireFormat; @@ -1317,6 +1340,8 @@ public class BinaryMapIndexReader { return buildSearchRequest(sleft, sright, stop, sbottom, zoom, searchFilter, null); } + + public static SearchRequest buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchFilter searchFilter, ResultMatcher resultMatcher){ SearchRequest request = new SearchRequest(); @@ -1345,6 +1370,55 @@ public class BinaryMapIndexReader { return request; } + public static SearchRequest buildSearchPoiRequest(List route, double radius, + SearchPoiTypeFilter poiTypeFilter, ResultMatcher resultMatcher) { + SearchRequest request = new SearchRequest(); + float coeff = (float) (radius / MapUtils.getTileDistanceWidth(SearchRequest.ZOOM_TO_SEARCH_POI)); + TIntObjectHashMap> zooms = new TIntObjectHashMap>(); + 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()); + } + List 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 buildSearchPoiRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchPoiTypeFilter poiTypeFilter, ResultMatcher matcher){ @@ -1426,6 +1500,7 @@ public class BinaryMapIndexReader { } public static class SearchRequest { + public final static int ZOOM_TO_SEARCH_POI = 16; private List searchResults = new ArrayList(); private boolean land = false; private boolean ocean = false; @@ -1443,6 +1518,11 @@ public class BinaryMapIndexReader { int zoom = 15; int limit = -1; + + // search on the path + // stores tile of 16 index and pairs (even length always) of points intersecting tile + TIntObjectHashMap> tiles = null; + double radius = -1; String nameQuery = null; @@ -1469,6 +1549,12 @@ public class BinaryMapIndexReader { 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){ 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 testPoiSearch = false; private static boolean testTransportSearch = false; @@ -1805,17 +1891,120 @@ public class BinaryMapIndexReader { PoiRegion poiRegion = reader.getPoiIndexes().get(0); testPoiSearch(reader, poiRegion); testPoiSearchByName(reader); + testSearchOnthePath(reader); } println("MEMORY " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); //$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 locations = readGPX(new File( + "")); + SearchRequest 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 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 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 readGPX(File f) { + List res = new ArrayList(); + 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 { println("Searching by name..."); - int tileZ = 31 - 14; - SearchRequest req = buildSearchPoiRequest(sleft/2+sright/2, stop/2+sbottom/2, "kol", - sleft - 1< req = buildSearchPoiRequest(0, 0, "roch", + 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, null); reader.searchPoiByName(req); for (Amenity a : req.getSearchResults()) { println(a.getType() + " " + a.getSubType() + " " + a.getName() + " " + a.getLocation()); @@ -2107,5 +2296,7 @@ public class BinaryMapIndexReader { routeAdapter.initRouteRegion(routeReg); } } + + } \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java index 24b6b75e1b..72f4eea566 100644 --- a/OsmAnd-java/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java @@ -15,11 +15,13 @@ import java.util.List; import net.osmand.Collator; import net.osmand.CollatorStringMatcher; import net.osmand.CollatorStringMatcher.StringMatcherMode; +import net.osmand.Location; import net.osmand.PlatformUtil; import net.osmand.binary.BinaryMapIndexReader.SearchRequest; import net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData; import net.osmand.data.Amenity; import net.osmand.data.AmenityType; +import net.osmand.data.LatLon; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; import net.sf.junidecode.Junidecode; @@ -588,6 +590,17 @@ public class BinaryMapPoiReaderAdapter { } } + private float dist(LatLon l, List 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, int px, int py, int zoom, SearchRequest req, PoiRegion region, boolean checkBounds) throws IOException { Amenity am = null; @@ -609,6 +622,19 @@ public class BinaryMapPoiReaderAdapter { am.setEnName(Junidecode.unidecode(am.getName())); } req.numberOfAcceptedObjects++; + if (req.radius > 0) { + LatLon loc = am.getLocation(); + List 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; case OsmandOdb.OsmAndPoiBoxDataAtom.DX_FIELD_NUMBER : x = (codedIS.readSInt32() + (px << (24 - zoom))) << 7; @@ -793,16 +819,16 @@ public class BinaryMapPoiReaderAdapter { case OsmandOdb.OsmAndPoiBox.SUBBOXES_FIELD_NUMBER: { int x = dx + (px << (zoom - pzoom)); int y = dy + (py << (zoom - pzoom)); - if(checkBox){ + if (checkBox) { int xL = x << (31 - zoom); int xR = ((x + 1) << (31 - zoom)) - 1; int yT = y << (31 - zoom); int yB = ((y + 1) << (31 - zoom)) - 1; // check intersection - if(left31 > xR || xL > right31 || bottom31 < yT || yB < top31){ + if (left31 > xR || xL > right31 || bottom31 < yT || yB < top31) { codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); return false; - } + } req.numberOfAcceptedSubtrees++; checkBox = false; } @@ -824,10 +850,20 @@ public class BinaryMapPoiReaderAdapter { int x = dx + (px << (zoom - pzoom)); int y = dy + (py << (zoom - pzoom)); long l = ((((x << zoom) | y) << 5) | zoom); - offsetsMap.put(readInt(), l); - if(skipTiles != null && zoom >= zoomToSkip){ - long val = ((((long) x) >> (zoom - zoomToSkip)) << zoomToSkip) | (((long) y) >> (zoom - zoomToSkip)); - skipTiles.add(val); + boolean read = true; + if(req.tiles != null) { + int zx = x << (SearchRequest.ZOOM_TO_SEARCH_POI - zoom); + 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; default: diff --git a/OsmAnd-java/src/net/osmand/data/Amenity.java b/OsmAnd-java/src/net/osmand/data/Amenity.java index 98c56d6070..fc34c34d61 100644 --- a/OsmAnd-java/src/net/osmand/data/Amenity.java +++ b/OsmAnd-java/src/net/osmand/data/Amenity.java @@ -18,6 +18,7 @@ public class Amenity extends MapObject { // duplicate for fast access private String openingHours; private Map additionalInfo; + private double deviateDistance; // for search on path public Amenity(){ } @@ -62,6 +63,13 @@ public class Amenity extends MapObject { 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) { if(this.additionalInfo == null){ diff --git a/OsmAnd-java/src/net/osmand/util/MapUtils.java b/OsmAnd-java/src/net/osmand/util/MapUtils.java index 098c7e6545..26539d57d1 100644 --- a/OsmAnd-java/src/net/osmand/util/MapUtils.java +++ b/OsmAnd-java/src/net/osmand/util/MapUtils.java @@ -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) { return x / getPowZoom(zoom) * 360.0 - 180.0; } diff --git a/OsmAnd/res/values/no_translate.xml b/OsmAnd/res/values/no_translate.xml index 25e804ab19..929963a4da 100644 --- a/OsmAnd/res/values/no_translate.xml +++ b/OsmAnd/res/values/no_translate.xml @@ -1,7 +1,7 @@ OsmAnd~ - 1.8 alpha + 1.9 alpha UA-28342846-2 10 diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java index 99acc6552b..30fd5c7b3e 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java @@ -820,6 +820,7 @@ public class MapActivityActions implements DialogProvider { } else { routingHelper.setRoutePlanningMode(true); routingHelper.setFollowingMode(false); + routingHelper.setPauseNaviation(true); } mapActivity.getMapViewTrackingUtilities().switchToRoutePlanningMode(); mapActivity.refreshMap(); diff --git a/OsmAnd/src/net/osmand/plus/monitoring/SettingsMonitoringActivity.java b/OsmAnd/src/net/osmand/plus/monitoring/SettingsMonitoringActivity.java index e019245a45..a7eeb5b5b2 100644 --- a/OsmAnd/src/net/osmand/plus/monitoring/SettingsMonitoringActivity.java +++ b/OsmAnd/src/net/osmand/plus/monitoring/SettingsMonitoringActivity.java @@ -39,6 +39,7 @@ public class SettingsMonitoringActivity extends SettingsBaseActivity { @Override public void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); + requestWindowFeature(Window.FEATURE_PROGRESS); super.onCreate(savedInstanceState); setSupportProgressBarIndeterminateVisibility(false); getSupportActionBar().setTitle(R.string.monitoring_settings); diff --git a/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepository.java b/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepository.java index 439e498bc9..c8ea50691b 100644 --- a/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepository.java +++ b/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepository.java @@ -2,6 +2,7 @@ package net.osmand.plus.resources; import java.util.List; +import net.osmand.Location; import net.osmand.ResultMatcher; import net.osmand.data.Amenity; import net.osmand.plus.PoiFilter; @@ -20,5 +21,7 @@ public interface AmenityIndexRepository { public List searchAmenities(int stop, int sleft, int sbottom, int sright, int zoom, PoiFilter filter, List amenities, ResultMatcher matcher); + public List searchAmenitiesOnThePath(List locations, double radius, PoiFilter filter, ResultMatcher matcher); + } diff --git a/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java b/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java index 82a41ece38..d07dcf6c6a 100644 --- a/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java +++ b/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import net.osmand.Location; import net.osmand.PlatformUtil; import net.osmand.ResultMatcher; import net.osmand.binary.BinaryMapIndexReader; @@ -105,5 +106,30 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { } return amenities; } + + @Override + public synchronized List searchAmenitiesOnThePath(List locations, double radius, final PoiFilter filter, ResultMatcher matcher) { + long now = System.currentTimeMillis(); + SearchPoiTypeFilter poiTypeFilter = new SearchPoiTypeFilter(){ + @Override + public boolean accept(AmenityType type, String subcategory) { + return filter.acceptTypeSubtype(type, subcategory); + } + }; + List result = null; + SearchRequest 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; + + } } diff --git a/OsmAnd/src/net/osmand/plus/resources/AsyncLoadingThread.java b/OsmAnd/src/net/osmand/plus/resources/AsyncLoadingThread.java index 5a7192b0c3..a9a3320dda 100644 --- a/OsmAnd/src/net/osmand/plus/resources/AsyncLoadingThread.java +++ b/OsmAnd/src/net/osmand/plus/resources/AsyncLoadingThread.java @@ -29,7 +29,6 @@ public class AsyncLoadingThread extends Thread { private static final Log log = PlatformUtil.getLog(AsyncLoadingThread.class); - private Handler asyncLoadingPoi; private Handler asyncLoadingTransport; Stack requests = new Stack(); @@ -43,11 +42,7 @@ public class AsyncLoadingThread extends Thread { this.resourceManger = resourceManger; } - private void startPoiLoadingThread() { - HandlerThread h = new HandlerThread("Loading poi"); - h.start(); - asyncLoadingPoi = new Handler(h.getLooper()); - } + private void startTransportLoadingThread() { HandlerThread h = new HandlerThread("Loading transport"); @@ -61,6 +56,8 @@ public class AsyncLoadingThread extends Thread { progress = BusyIndicator.STATUS_GREEN; } else if (resourceManger.getContext().getRoutingHelper().isRouteBeingCalculated()) { progress = BusyIndicator.STATUS_ORANGE; + } else if (resourceManger.isSearchAmenitiesInProgress()) { + progress = BusyIndicator.STATUS_BLACK; } else if (!requests.isEmpty()) { progress = BusyIndicator.STATUS_BLACK; } else if (transportLoadRequest != null && transportLoadRequest.isRunning()) { diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index 36b92ae011..f751d70d9f 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -1,8 +1,6 @@ package net.osmand.plus.resources; -import gnu.trove.list.array.TIntArrayList; - import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -23,6 +21,7 @@ import net.osmand.AndroidUtils; import net.osmand.GeoidAltitudeCorrection; import net.osmand.IProgress; import net.osmand.IndexConstants; +import net.osmand.Location; import net.osmand.PlatformUtil; import net.osmand.ResultMatcher; import net.osmand.binary.BinaryMapIndexReader; @@ -271,6 +270,7 @@ public class ResourceManager { protected StringBuilder builder = new StringBuilder(40); protected char[] tileId = new char[120]; private GeoidAltitudeCorrection geoidAltitudeCorrection; + private boolean searchAmenitiesInProgress; public synchronized String calculateTileId(ITileSource map, int x, int y, int zoom) { builder.setLength(0); @@ -719,41 +719,47 @@ public class ResourceManager { public List searchAmenities(PoiFilter filter, double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, final ResultMatcher matcher) { final List amenities = new ArrayList(); - if(filter instanceof NameFinderPoiFilter || filter instanceof SearchByNameFilter){ - List tempResults = filter instanceof NameFinderPoiFilter ? - ((NameFinderPoiFilter) filter).getSearchedAmenities() :((SearchByNameFilter) filter).getSearchedAmenities() ; - for(Amenity a : tempResults){ - LatLon l = a.getLocation(); - if(l != null && l.getLatitude() <= topLatitude && l.getLatitude() >= bottomLatitude && l.getLongitude() >= leftLongitude && l.getLongitude() <= rightLongitude){ - if(matcher.publish(a) ){ - amenities.add(a); + searchAmenitiesInProgress = true; + try { + if (filter instanceof NameFinderPoiFilter || filter instanceof SearchByNameFilter) { + List tempResults = filter instanceof NameFinderPoiFilter ? ((NameFinderPoiFilter) filter) + .getSearchedAmenities() : ((SearchByNameFilter) filter).getSearchedAmenities(); + for (Amenity a : tempResults) { + LatLon l = a.getLocation(); + 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() { + + @Override + public boolean publish(Amenity object) { + if (checkNameFilter(object, filterByName)) { + return matcher.publish(object); + } + return false; + } + + @Override + public boolean isCancelled() { + return matcher.isCancelled(); + } + }); } } } - } 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), -1, filter, amenities, - new ResultMatcher() { - - @Override - public boolean publish(Amenity object) { - if (checkNameFilter(object, filterByName)) { - return matcher.publish(object); - } - return false; - } - - @Override - public boolean isCancelled() { - return matcher.isCancelled(); - } - }); - } - } + } finally { + searchAmenitiesInProgress = false; } return amenities; } @@ -814,33 +820,40 @@ public class ResourceManager { return map; } - public void searchAmenitiesOnTheArea(TIntArrayList tiles16z, PoiFilter filter, ResultMatcher results) { - if (tiles16z.size() > 0) { - int z = 16; - int x = tiles16z.get(0) >> z; - int y = tiles16z.get(0) & ((1 << z) - 1); - List repos = new ArrayList(); - double topLatitude = MapUtils.getLatitudeFromTile(z, y); - double bottomLatitude = MapUtils.getLatitudeFromTile(z, y + 1); - double leftLongitude = MapUtils.getLongitudeFromTile(z, x); - double rightLongitude = MapUtils.getLongitudeFromTile(z, x + 1); - for (int k = 1; k < tiles16z.size(); k++) { - topLatitude = Math.max(topLatitude, MapUtils.getLatitudeFromTile(z, y)); - bottomLatitude = Math.min(bottomLatitude, MapUtils.getLatitudeFromTile(z, y + 1)); - leftLongitude = Math.min(leftLongitude, MapUtils.getLongitudeFromTile(z, x)); - rightLongitude = Math.max(rightLongitude, MapUtils.getLongitudeFromTile(z, x + 1)); - } - for (AmenityIndexRepository index : amenityRepositories) { - if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) { - repos.add(index); - } - } - if (!repos.isEmpty()) { - for(AmenityIndexRepository r : repos) { -// r.searchAmenities(stop, sleft, sbottom, sright, zoom, filter, amenities, matcher) + public List searchAmenitiesOnThePath(List locations, double radius, PoiFilter filter, ResultMatcher matcher) { + searchAmenitiesInProgress = true; + final List amenities = new ArrayList(); + try { + if (locations != null && locations.size() > 0) { + List repos = new ArrayList(); + double topLatitude = locations.get(0).getLatitude(); + double bottomLatitude = locations.get(0).getLatitude(); + double leftLongitude = locations.get(0).getLongitude(); + double rightLongitude = locations.get(0).getLongitude(); + for (Location l : locations) { + topLatitude = Math.max(topLatitude, l.getLatitude()); + bottomLatitude = Math.min(bottomLatitude, l.getLatitude()); + leftLongitude = Math.min(leftLongitude, l.getLongitude()); + rightLongitude = Math.max(rightLongitude, l.getLongitude()); + } + for (AmenityIndexRepository index : amenityRepositories) { + if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) { + repos.add(index); + } + } + if (!repos.isEmpty()) { + for (AmenityIndexRepository r : repos) { + List res = r.searchAmenitiesOnThePath(locations, radius, filter, matcher); + if (res != null) { + amenities.addAll(res); + } + } } } + }finally { + searchAmenitiesInProgress = false; } + return amenities; } ////////////////////////////////////////////// Working with address /////////////////////////////////////////// @@ -896,6 +909,10 @@ public class ResourceManager { renderer.interruptLoadingMap(); } + public boolean isSearchAmenitiesInProgress() { + return searchAmenitiesInProgress; + } + public MapRenderRepositories getRenderer() { return renderer; } diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java index fd56ad6b3a..6d4236c57b 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java @@ -50,8 +50,8 @@ public class RoutingHelper { private OsmandApplication app; private boolean isFollowingMode = false; - private boolean isRoutePlanningMode = false; + private boolean isPauseNavigation = false; private GPXRouteParamsBuilder currentGPXRoute = null; @@ -79,6 +79,7 @@ public class RoutingHelper { private RouteCalculationProgressCallback progressRoute; private SearchOnTheRouteHelper searchOnTheRouteHelper; + // private ProgressBar progress; // private Handler progressHandler; @@ -101,8 +102,17 @@ public class RoutingHelper { return isFollowingMode; } + public void setPauseNaviation(boolean b) { + this.isPauseNavigation = b; + } + + public boolean isPauseNavigation() { + return isPauseNavigation; + } + public void setFollowingMode(boolean follow) { isFollowingMode = follow; + isPauseNavigation = false; if (!follow) { if (app.getNavigationService() != null) { app.getNavigationService().stopIfNeeded(app, NavigationService.USED_BY_NAVIGATION); @@ -932,4 +942,5 @@ public class RoutingHelper { } } + } diff --git a/OsmAnd/src/net/osmand/plus/views/POIMapLayer.java b/OsmAnd/src/net/osmand/plus/views/POIMapLayer.java index 451917d8a1..090b2aaf64 100644 --- a/OsmAnd/src/net/osmand/plus/views/POIMapLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/POIMapLayer.java @@ -21,6 +21,10 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.render.RenderingIcons; 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 android.app.AlertDialog; import android.app.AlertDialog.Builder; @@ -36,7 +40,7 @@ import android.net.Uri; import android.widget.Toast; public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider, - MapTextProvider { + MapTextProvider, IRouteInformationListener { private static final int startZoom = 10; 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 ResourceManager resourceManager; + private RoutingHelper routingHelper; private PoiFilter filter; private MapTextLayer mapTextLayer; /// cache for displayed POI // Work with cache (for map copied from AmenityIndexRepositoryOdb) private MapLayerData> data; + private boolean path = false; + private double radius = 100; public POIMapLayer(MapActivity activity) { + routingHelper = activity.getRoutingHelper(); + routingHelper.addListener(this); data = new OsmandMapLayer.MapLayerData>() { { ZOOM_THRESHOLD = 0; @@ -70,19 +79,24 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon @Override protected List calculateResult(RotatedTileBox tileBox) { QuadRect latLonBounds = tileBox.getLatLonBounds(); - return resourceManager.searchAmenities(filter, latLonBounds.top, latLonBounds.left, - latLonBounds.bottom, latLonBounds.right, tileBox.getZoom(), new ResultMatcher() { + if(path) { + 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() { - @Override - public boolean publish(Amenity object) { - return true; - } + @Override + public boolean publish(Amenity object) { + return true; + } - @Override - public boolean isCancelled() { - return isInterrupted(); - } - }); + @Override + public boolean isCancelled() { + return isInterrupted(); + } + }); + } } }; } @@ -92,9 +106,21 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon } public void setFilter(PoiFilter filter) { + // TODO parameter this.filter = filter; +// this.radius = 100; +// this.path = true; + this.path = false; 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 am) { List objects = data.getResults(); @@ -224,6 +250,7 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon @Override public void destroyLayer() { + routingHelper.removeListener(this); } @Override @@ -317,7 +344,7 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon } return null; } - + @Override public LatLon getTextLocation(Amenity o) { return o.getLocation(); @@ -333,4 +360,16 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon return o.getName(view.getSettings().usingEnglishNames()); } + @Override + public void newRouteIsCalculated(boolean newRoute) { + if(path) { + data.clearCache(); + } + } + + @Override + public void routeWasCancelled() { + } + + } diff --git a/OsmAnd/src/net/osmand/plus/views/controls/MapNavigateControl.java b/OsmAnd/src/net/osmand/plus/views/controls/MapNavigateControl.java index 1e2c292136..6c96984c95 100644 --- a/OsmAnd/src/net/osmand/plus/views/controls/MapNavigateControl.java +++ b/OsmAnd/src/net/osmand/plus/views/controls/MapNavigateControl.java @@ -111,7 +111,7 @@ public class MapNavigateControl extends MapControls { startNavigation(); } }); - if(!mapActivity.getRoutingHelper().isFollowingMode()) { + if(!mapActivity.getRoutingHelper().isFollowingMode() && !mapActivity.getRoutingHelper().isPauseNavigation()) { startCounter(); } }