From 899ca5323125461364bb26ee4d674e46e4b14049 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sun, 29 Nov 2015 15:20:36 +0100 Subject: [PATCH] Improve geocoing --- .../binary/BinaryMapAddressReaderAdapter.java | 1 + .../osmand/binary/BinaryMapIndexReader.java | 76 +++++- .../binary/BinaryMapRouteReaderAdapter.java | 1 + .../net/osmand/binary/GeocodingUtilities.java | 228 ++++++++++++++++++ .../osmand/router/RoutePlannerFrontEnd.java | 14 +- .../src/net/osmand/router/TestRouting.java | 4 +- .../osmand/plus/CurrentPositionHelper.java | 114 ++++++--- .../osmand/plus/OsmAndLocationProvider.java | 6 +- .../mapcontextmenu/MenuTitleController.java | 38 ++- .../resources/RegionAddressRepository.java | 5 + .../RegionAddressRepositoryBinary.java | 18 ++ 11 files changed, 451 insertions(+), 54 deletions(-) create mode 100644 OsmAnd-java/src/net/osmand/binary/GeocodingUtilities.java diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapAddressReaderAdapter.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapAddressReaderAdapter.java index 5ca2e53894..2805f8d5d0 100644 --- a/OsmAnd-java/src/net/osmand/binary/BinaryMapAddressReaderAdapter.java +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapAddressReaderAdapter.java @@ -594,6 +594,7 @@ public class BinaryMapAddressReaderAdapter { int old = codedIS.pushLimit(len); LatLon l = obj.getLocation(); Street s = new Street(obj); + s.setFileOffset(list.get(j)); readStreet(s, null, false, MapUtils.get31TileNumberX(l.getLongitude()) >> 7, MapUtils.get31TileNumberY(l.getLatitude()) >> 7, obj.isPostcode() ? obj.getName() : null, reg.attributeTagsTable); diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java index 31ad40ec61..32e50fff77 100644 --- a/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java @@ -21,10 +21,12 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.TreeMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -1951,7 +1953,8 @@ public class BinaryMapIndexReader { private static boolean testMapSearch = false; private static boolean testAddressSearch = false; - private static boolean testPoiSearch = true; + private static boolean testAddressJustifySearch = true; + private static boolean testPoiSearch = false; private static boolean testPoiSearchOnPath = false; private static boolean testTransportSearch = false; private static int sleft = MapUtils.get31TileNumberX(6.3); @@ -1965,7 +1968,8 @@ public class BinaryMapIndexReader { } public static void main(String[] args) throws IOException { - File fl = new File("/Users/victorshcherb/osmand/maps/Synthetic_test_rendering.obf"); +// File fl = new File("/Users/victorshcherb/osmand/maps/Synthetic_test_rendering.obf"); + File fl = new File("/Users/victorshcherb/osmand/maps/Netherlands_europe_2.road.obf"); RandomAccessFile raf = new RandomAccessFile(fl, "r"); BinaryMapIndexReader reader = new BinaryMapIndexReader(raf, fl); @@ -1979,6 +1983,9 @@ public class BinaryMapIndexReader { testAddressSearchByName(reader); testAddressSearch(reader); } + if(testAddressJustifySearch) { + testAddressJustifySearch(reader); + } if(testTransportSearch) { testTransportSearch(reader); } @@ -2259,6 +2266,71 @@ public class BinaryMapIndexReader { reader.searchAddressDataByName(req); } + /** + * @param reader + * @throws IOException + */ + /** + * @param reader + * @throws IOException + */ + private static void testAddressJustifySearch(BinaryMapIndexReader reader) throws IOException { + final String streetName = "Logger"; + final double lat = 52.28212d; + final double lon = 4.86269d; + // test address index search + final List streetsList = new ArrayList(); + SearchRequest req = buildAddressByNameRequest(new ResultMatcher() { + @Override + public boolean publish(MapObject object) { + if(object instanceof Street && object.getName().equalsIgnoreCase(streetName)) { + if(MapUtils.getDistance(object.getLocation(), lat, lon) < 20000) { + streetsList.add((Street) object); + return true; + } + return false; + } + return false; + } + @Override + public boolean isCancelled() { + return false; + } + }, streetName); + reader.searchAddressDataByName(req); + TreeMap resMap = new TreeMap(new Comparator() { + + @Override + public int compare(MapObject o1, MapObject o2) { + LatLon l1 = o1.getLocation(); + LatLon l2 = o2.getLocation(); + if(l1 == null || l2 == null){ + return l2 == l1 ? 0 : (l1 == null ? -1 : 1); + } + return Double.compare(MapUtils.getDistance(l1, lat, lon), MapUtils.getDistance(l2, lat, lon)); + } + }); + for(Street s : streetsList) { + resMap.put(s, s); + reader.preloadBuildings(s, null); + for(Building b : s.getBuildings()) { + if(MapUtils.getDistance(b.getLocation(), lat, lon) < 100) { + resMap.put(b, s); + } + } + } + for(MapObject e : resMap.keySet()) { + Street s = resMap.get(e); + if(e instanceof Building && MapUtils.getDistance(e.getLocation(), lat, lon) < 40) { + Building b = (Building) e; + System.out.println(b.getName() + " " + s); + } else if(e instanceof Street){ + System.out.println(s + " " + ((Street) s).getCity()); + } + } + + } + private static void testAddressSearch(BinaryMapIndexReader reader) throws IOException { // test address index search final Map streetFreq = new HashMap(); diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java index e17e884fda..902dd7e7d9 100644 --- a/OsmAnd-java/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java @@ -215,6 +215,7 @@ public class BinaryMapRouteReaderAdapter { int destinationTypeRule = -1; int destinationRefTypeRule = -1; + public RouteTypeRule quickGetEncodingRule(int id) { return routeEncodingRules.get(id); } diff --git a/OsmAnd-java/src/net/osmand/binary/GeocodingUtilities.java b/OsmAnd-java/src/net/osmand/binary/GeocodingUtilities.java new file mode 100644 index 0000000000..2bb8084297 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/GeocodingUtilities.java @@ -0,0 +1,228 @@ +package net.osmand.binary; + +import gnu.trove.set.hash.TLongHashSet; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; + +import net.osmand.PlatformUtil; +import net.osmand.ResultMatcher; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.data.Building; +import net.osmand.data.City; +import net.osmand.data.LatLon; +import net.osmand.data.MapObject; +import net.osmand.data.Street; +import net.osmand.router.BinaryRoutePlanner; +import net.osmand.router.RoutePlannerFrontEnd; +import net.osmand.router.RoutingConfiguration; +import net.osmand.router.BinaryRoutePlanner.RouteSegmentPoint; +import net.osmand.router.RoutingContext; +import net.osmand.util.Algorithms; +import net.osmand.util.MapUtils; + +public class GeocodingUtilities { + + private static final Log log = PlatformUtil.getLog(GeocodingUtilities.class); + + public static final float THRESHOLD_MULTIPLIER_SKIP_BUILDINGS_AFTER = 1.5f; + public static final float THRESHOLD_MULTIPLIER_SKIP_STREETS_AFTER = 3; + public static final float DISTANCE_STREET_NAME_PROXIMITY_BY_NAME = 20000; + public static final float DISTANCE_BULDING_PROXIMITY = 100; + public static final float THRESHOLD_STREET_CHANGE_CONNECTION_POINT = 400; // not important + public static final Comparator DISTANCE_COMPARATOR = new Comparator() { + + @Override + public int compare(GeocodingResult o1, GeocodingResult o2) { + LatLon l1 = o1.getLocation(); + LatLon l2 = o2.getLocation(); + if(l1 == null || l2 == null){ + return l2 == l1 ? 0 : (l1 == null ? -1 : 1); + } + return Double.compare(MapUtils.getDistance(l1, o1.searchPoint), + MapUtils.getDistance(l2, o2.searchPoint)); + } + }; + + public static class GeocodingResult { + public GeocodingResult(){ + } + + public GeocodingResult(GeocodingResult r){ + this.searchPoint = r.searchPoint; + this.regionFP = r.regionFP; + this.regionLen = r.regionLen; + this.connectionPoint = r.connectionPoint; + this.streetName = r.streetName; + this.point = r.point; + this.building = r.building; + this.city = r.city; + this.street = r.street; + this.streetName = r.streetName; + } + + // input + public LatLon searchPoint; + // 1st step + public LatLon connectionPoint; + public int regionFP; + public int regionLen; + public RouteSegmentPoint point; + public String streetName; + // justification + public Building building; + public Street street; + public City city; + private double dist = -1; + + public LatLon getLocation() { + return connectionPoint; + } + + public double getDistance() { + if(dist == -1) { + dist = MapUtils.getDistance(connectionPoint, searchPoint); + } + return dist; + } + + @Override + public String toString() { + StringBuilder bld = new StringBuilder(); + if(building != null) { + bld.append(building.getName()); + } + if(street != null) { + bld.append(" str. ").append(street.getName()).append(" city ").append(city.getName()); + } else if(streetName != null) { + bld.append(" str. ").append(streetName); + } else if(city != null) { + bld.append(" city ").append(city.getName()); + } + if(connectionPoint != null && searchPoint != null) { + + bld.append(" dist=").append((int) getDistance()); + } + return bld.toString(); + } + } + + public List reverseGeocodingSearch(RoutingContext ctx, double lat, double lon) throws IOException { + RoutePlannerFrontEnd rp = new RoutePlannerFrontEnd(false); + List lst = new ArrayList(); + List listR = new ArrayList(); + rp.findRouteSegment(lat, lon, ctx, listR); + double dist = 0; + TLongHashSet set = new TLongHashSet(); + Set streetNames = new HashSet(); + for(RouteSegmentPoint p : listR) { + RouteDataObject road = p.getRoad(); + if(!set.add(road.getId())) { + continue; + } + boolean emptyName = Algorithms.isEmpty(road.getName()) && Algorithms.isEmpty(road.getRef()) ; + if(!emptyName) { + if(dist == 0) { + dist = p.dist; + } + GeocodingResult sr = new GeocodingResult(); + sr.searchPoint = new LatLon(lat, lon); + sr.streetName = Algorithms.isEmpty(road.getName())? road.getRef() : road.getName(); + sr.point = p; + + sr.connectionPoint = new LatLon(MapUtils.get31LatitudeY(p.preciseY), MapUtils.get31LongitudeX(p.preciseX)); + sr.regionFP = road.region.getFilePointer(); + sr.regionLen = road.region.getLength(); + if(streetNames.add(sr.streetName)) { + lst.add(sr); + } + } + if(p.dist > 100*100 && dist != 0 && p.dist > 4 * dist ) { + break; + } + if(p.dist > 300*300) { + break; + } + } + Collections.sort(lst, GeocodingUtilities.DISTANCE_COMPARATOR); + return lst; + } + + public List justifyReverseGeocodingSearch(final GeocodingResult r, BinaryMapIndexReader reader, + double knownMinBuidlingDistance) throws IOException { + // test address index search + final List streetsList = new ArrayList(); + log.info("Search street by name " + r.streetName); + SearchRequest req = BinaryMapIndexReader.buildAddressByNameRequest(new ResultMatcher() { + @Override + public boolean publish(MapObject object) { + if(object instanceof Street && object.getName().equalsIgnoreCase(r.streetName)) { + double d = MapUtils.getDistance(object.getLocation(), r.searchPoint.getLatitude(), + r.searchPoint.getLongitude()); + if(d < DISTANCE_STREET_NAME_PROXIMITY_BY_NAME) { + GeocodingResult rs = new GeocodingResult(r); + rs.street = (Street) object; + rs.city = rs.street.getCity(); + if(d > THRESHOLD_STREET_CHANGE_CONNECTION_POINT) { + rs.connectionPoint = rs.street.getLocation(); + } + streetsList.add(rs); + return true; + } + return false; + } + return false; + } + @Override + public boolean isCancelled() { + return false; + } + }, r.streetName); + reader.searchAddressDataByName(req); + + final List res = new ArrayList(); + // FIXME interpolation + for(GeocodingResult s : streetsList) { + final List streetBuildings = new ArrayList(); + reader.preloadBuildings(s.street, null); + log.info("Preload buildings " + s.street.getName() + " " + s.city.getName() + " " + s.street.getId()); + for(Building b : s.street.getBuildings()) { + if(MapUtils.getDistance(b.getLocation(), r.searchPoint) < DISTANCE_BULDING_PROXIMITY) { + GeocodingResult bld = new GeocodingResult(s); + bld.building = b; + bld.connectionPoint = b.getLocation(); + streetBuildings.add(bld); + } + } + Collections.sort(streetBuildings, DISTANCE_COMPARATOR); + if(streetBuildings.size() > 0) { + Iterator it = streetBuildings.iterator(); + if(knownMinBuidlingDistance == 0) { + GeocodingResult firstBld = it.next(); + knownMinBuidlingDistance = firstBld.getDistance(); + res.add(firstBld); + } + while(it.hasNext()) { + GeocodingResult nextBld = it.next(); + if(nextBld.getDistance() > knownMinBuidlingDistance * THRESHOLD_MULTIPLIER_SKIP_BUILDINGS_AFTER) { + break; + } + res.add(nextBld); + } + } + res.add(s); + } + Collections.sort(res, DISTANCE_COMPARATOR); + return res; + } +} diff --git a/OsmAnd-java/src/net/osmand/router/RoutePlannerFrontEnd.java b/OsmAnd-java/src/net/osmand/router/RoutePlannerFrontEnd.java index 690c061244..0104b5ee72 100644 --- a/OsmAnd-java/src/net/osmand/router/RoutePlannerFrontEnd.java +++ b/OsmAnd-java/src/net/osmand/router/RoutePlannerFrontEnd.java @@ -55,7 +55,7 @@ public class RoutePlannerFrontEnd { return dx * dx + dy * dy; } - public RouteSegmentPoint findRouteSegment(double lat, double lon, boolean searchWithName, RoutingContext ctx) throws IOException { + public RouteSegmentPoint findRouteSegment(double lat, double lon, RoutingContext ctx, List list) throws IOException { int px = MapUtils.get31TileNumberX(lon); int py = MapUtils.get31TileNumberY(lat); ArrayList dataObjects = new ArrayList(); @@ -63,12 +63,10 @@ public class RoutePlannerFrontEnd { if (dataObjects.isEmpty()) { ctx.loadTileData(px, py, 15, dataObjects); } - List list = new ArrayList(); + if(list == null) { + list = new ArrayList(); + } for (RouteDataObject r : dataObjects) { - boolean emptyName = Algorithms.isEmpty(r.getName()) && Algorithms.isEmpty(r.getRef()) ; - if(searchWithName && emptyName) { - continue; - } if (r.getPointsLength() > 1) { RouteSegmentPoint road = null; for (int j = 1; j < r.getPointsLength(); j++) { @@ -95,7 +93,7 @@ public class RoutePlannerFrontEnd { } }); if(list.size() > 0) { - RouteSegmentPoint ps = list.remove(0); + RouteSegmentPoint ps = list.get(0); ps.others = list; return ps; } @@ -284,7 +282,7 @@ public class RoutePlannerFrontEnd { } private boolean addSegment(LatLon s, RoutingContext ctx, int indexNotFound, List res) throws IOException { - RouteSegmentPoint f = findRouteSegment(s.getLatitude(), s.getLongitude(), false, ctx); + RouteSegmentPoint f = findRouteSegment(s.getLatitude(), s.getLongitude(), ctx, null); if(f == null){ ctx.calculationProgress.segmentNotFound = indexNotFound; return false; diff --git a/OsmAnd-java/src/net/osmand/router/TestRouting.java b/OsmAnd-java/src/net/osmand/router/TestRouting.java index dacdf62c01..77f5fc1142 100644 --- a/OsmAnd-java/src/net/osmand/router/TestRouting.java +++ b/OsmAnd-java/src/net/osmand/router/TestRouting.java @@ -310,8 +310,8 @@ public class TestRouting { RoutingConfiguration rconfig = config.build(vehicle, MEMORY_TEST_LIMIT); RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(oldRouting); RoutingContext ctx = router.buildRoutingContext(rconfig, lib, rs); - RouteSegment startSegment = router.findRouteSegment(startLat, startLon, false, ctx); - RouteSegment endSegment = router.findRouteSegment(endLat, endLon, false, ctx); + RouteSegment startSegment = router.findRouteSegment(startLat, startLon, ctx, null); + RouteSegment endSegment = router.findRouteSegment(endLat, endLon, ctx, null); if(startSegment == null){ throw new IllegalArgumentException("Start segment is not found "); } diff --git a/OsmAnd/src/net/osmand/plus/CurrentPositionHelper.java b/OsmAnd/src/net/osmand/plus/CurrentPositionHelper.java index 3450eef08e..3a6624c2ea 100644 --- a/OsmAnd/src/net/osmand/plus/CurrentPositionHelper.java +++ b/OsmAnd/src/net/osmand/plus/CurrentPositionHelper.java @@ -1,11 +1,22 @@ package net.osmand.plus; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import net.osmand.Location; import net.osmand.ResultMatcher; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.binary.GeocodingUtilities; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.GeocodingUtilities.GeocodingResult; import net.osmand.binary.RouteDataObject; +import net.osmand.osm.edit.Node; +import net.osmand.osm.edit.OSMSettings.OSMTagKey; +import net.osmand.plus.resources.RegionAddressRepository; import net.osmand.router.BinaryRoutePlanner.RouteSegment; import net.osmand.router.BinaryRoutePlanner.RouteSegmentPoint; import net.osmand.router.GeneralRouter.GeneralRouterProfile; @@ -46,16 +57,25 @@ public class CurrentPositionHelper { - private void scheduleRouteSegmentFind(final Location loc, final ResultMatcher result, final boolean storeFound) { + private void scheduleRouteSegmentFind(final Location loc, final boolean storeFound, final ResultMatcher geoCoding, final ResultMatcher result) { if (loc != null) { Runnable run = new Runnable() { @Override public void run() { try { - RouteDataObject res = runUpdateInThread(loc.getLatitude(), loc.getLongitude(), result); + final List gr = runUpdateInThread(loc.getLatitude(), loc.getLongitude()); if (storeFound) { lastAskedLocation = loc; - lastFound = res; + lastFound = gr.isEmpty() ? null : gr.get(0).point.getRoad(); + } else if(geoCoding != null) { + justifyResult(gr, geoCoding); + } else if(result != null) { + app.runInUIThread(new Runnable() { + @Override + public void run() { + result.publish(gr.isEmpty() ? null : gr.get(0).point.getRoad()); + } + }); } } catch (IOException e) { e.printStackTrace(); @@ -66,6 +86,59 @@ public class CurrentPositionHelper { } } + protected void justifyResult(List res, final ResultMatcher result) { + double minBuildingDistance = 0; + List complete = new ArrayList(); + for (GeocodingResult r : res) { + if (minBuildingDistance > 0 + && r.getDistance() > GeocodingUtilities.THRESHOLD_MULTIPLIER_SKIP_STREETS_AFTER * minBuildingDistance) { + break; + } + Collection rar = app.getResourceManager().getAddressRepositories(); + RegionAddressRepository foundRepo = null; + for(RegionAddressRepository repo : rar) { + BinaryMapIndexReader reader = repo.getFile(); + for (RouteRegion rb : reader.getRoutingIndexes()) { + if (r.regionFP == rb.getFilePointer() && r.regionLen == rb.getLength()) { + foundRepo = repo; + break; + } + } + if(foundRepo != null) { + break; + } + } + if (foundRepo != null) { + List justified = foundRepo.justifyReverseGeocodingSearch(r, minBuildingDistance); + if(!justified.isEmpty()) { + double md = justified.get(0).getDistance(); + if(minBuildingDistance == 0){ + minBuildingDistance = md; + } else { + minBuildingDistance = Math.min(md, minBuildingDistance); + } + complete.addAll(justified); + } + } else { + complete.add(r); + } + } + Collections.sort(complete, GeocodingUtilities.DISTANCE_COMPARATOR); + for(final GeocodingResult r : complete) { + if(r.building != null && + r.getDistance() > minBuildingDistance * GeocodingUtilities.THRESHOLD_MULTIPLIER_SKIP_BUILDINGS_AFTER) { + continue; + } + app.runInUIThread(new Runnable() { + public void run() { + result.publish(r); + } + }); + break; + } + + } + private static double getOrthogonalDistance(RouteDataObject r, Location loc){ double d = 1000; if (r.getPointsLength() > 0) { @@ -86,7 +159,11 @@ public class CurrentPositionHelper { } public void getRouteSegment(Location loc, ResultMatcher result) { - scheduleRouteSegmentFind(loc, result, false); + scheduleRouteSegmentFind(loc, false, null, result); + } + + public void getGeocodingResult(Location loc, ResultMatcher result) { + scheduleRouteSegmentFind(loc, false, result, null); } public RouteDataObject getLastKnownRouteSegment(Location loc) { @@ -99,12 +176,12 @@ public class CurrentPositionHelper { return r; } if (r == null) { - scheduleRouteSegmentFind(loc, null, true); + scheduleRouteSegmentFind(loc, true, null, null); return null; } double d = getOrthogonalDistance(r, loc); if (d > 25) { - scheduleRouteSegmentFind(loc, null, true); + scheduleRouteSegmentFind(loc, true, null, null); } if (d < 70) { return r; @@ -113,34 +190,13 @@ public class CurrentPositionHelper { } - private synchronized RouteDataObject runUpdateInThread(double lat, double lon, final ResultMatcher resultMatcher) throws IOException { - RoutePlannerFrontEnd rp = new RoutePlannerFrontEnd(false); + private synchronized List runUpdateInThread(double lat, double lon) throws IOException { if (ctx == null || am != app.getSettings().getApplicationMode()) { initCtx(app); if (ctx == null) { return null; } } - final RouteSegmentPoint sg = rp.findRouteSegment(lat, lon, true, ctx); - final RouteDataObject res; - if(sg == null) { - res = null; - } else { - RouteSegmentPoint ff = rp.findRouteSegment(lat, lon, false, ctx); - if(ff == null || ff.dist + 70 * 70 < sg.dist) { - res = null; - } else { - res = sg.getRoad(); - } - } - if(resultMatcher != null) { - app.runInUIThread(new Runnable() { - public void run() { - resultMatcher.publish(res); - } - }); - } - return res; - + return new GeocodingUtilities().reverseGeocodingSearch(ctx, lat, lon); } } diff --git a/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java b/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java index 48f40a6cbc..bceb894695 100644 --- a/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java +++ b/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java @@ -19,11 +19,11 @@ import android.os.Bundle; import android.provider.Settings; import android.support.v7.app.AlertDialog; import android.util.Log; - import net.osmand.GeoidAltitudeCorrection; import net.osmand.PlatformUtil; import net.osmand.ResultMatcher; import net.osmand.access.NavigationInfo; +import net.osmand.binary.GeocodingUtilities.GeocodingResult; import net.osmand.binary.RouteDataObject; import net.osmand.data.LatLon; import net.osmand.data.QuadPoint; @@ -848,6 +848,10 @@ public class OsmAndLocationProvider implements SensorEventListener { public void getRouteSegment(net.osmand.Location loc, ResultMatcher result) { currentPositionHelper.getRouteSegment(loc, result); } + + public void getGeocodingResult(net.osmand.Location loc, ResultMatcher result) { + currentPositionHelper.getGeocodingResult(loc, result); + } public net.osmand.Location getLastKnownLocation() { return location; diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuTitleController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuTitleController.java index 08b8927311..337dffdd36 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuTitleController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuTitleController.java @@ -3,6 +3,7 @@ package net.osmand.plus.mapcontextmenu; import android.graphics.drawable.Drawable; import net.osmand.Location; import net.osmand.ResultMatcher; +import net.osmand.binary.GeocodingUtilities.GeocodingResult; import net.osmand.binary.RouteDataObject; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; @@ -134,24 +135,37 @@ public abstract class MenuTitleController { ll.setLatitude(getLatLon().getLatitude()); ll.setLongitude(getLatLon().getLongitude()); getMapActivity().getMyApplication().getLocationProvider() - .getRouteSegment(ll, new ResultMatcher() { + .getGeocodingResult(ll, new ResultMatcher() { @Override - public boolean publish(RouteDataObject object) { + public boolean publish(GeocodingResult object) { if (object != null) { OsmandSettings settings = getMapActivity().getMyApplication().getSettings(); - String streetName = object.getName(settings.MAP_PREFERRED_LOCALE.get()); - String ref = object.getRef(); - if(Algorithms.isEmpty(streetName)) { - streetName = ""; - } - if(!Algorithms.isEmpty(ref)) { - if(!Algorithms.isEmpty(streetName)) { - streetName += ", "; + String lang = settings.MAP_PREFERRED_LOCALE.get(); + String geocodingResult = ""; + if(object.building != null) { + geocodingResult = object.street.getName(lang) + ", " + object.building.getName(lang)+ ", " + object.city.getName(lang); + } else if(object.street != null) { + geocodingResult = object.street.getName(lang) + ", " + object.city.getName(lang); + } else if(object.city != null) { + geocodingResult = object.city.getName(lang); + } else if(object.point != null) { + RouteDataObject rd = object.point.getRoad(); + String sname = rd.getName(lang); + if(Algorithms.isEmpty(sname)) { + sname = ""; } - streetName += ref; + String ref = rd.getRef(); + if(!Algorithms.isEmpty(ref)) { + if(!Algorithms.isEmpty(sname)) { + sname += ", "; + } + sname += ref; + } + geocodingResult = sname; } - streetStr = streetName; + + streetStr = geocodingResult; if (!Algorithms.isEmpty(streetStr)) { MenuController menuController = getMenuController(); if (menuController == null || menuController.displayStreetNameInTitle()) { diff --git a/OsmAnd/src/net/osmand/plus/resources/RegionAddressRepository.java b/OsmAnd/src/net/osmand/plus/resources/RegionAddressRepository.java index a763006b41..33225b9df3 100644 --- a/OsmAnd/src/net/osmand/plus/resources/RegionAddressRepository.java +++ b/OsmAnd/src/net/osmand/plus/resources/RegionAddressRepository.java @@ -5,6 +5,8 @@ import java.util.Comparator; import java.util.List; import net.osmand.ResultMatcher; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.binary.GeocodingUtilities.GeocodingResult; import net.osmand.data.Building; import net.osmand.data.City; import net.osmand.data.LatLon; @@ -56,6 +58,7 @@ public interface RegionAddressRepository { public List searchMapObjectsByName(String name, ResultMatcher resultMatcher); + public BinaryMapIndexReader getFile(); public static class MapObjectNameDistanceComparator implements Comparator { @@ -87,4 +90,6 @@ public interface RegionAddressRepository { } } + public List justifyReverseGeocodingSearch(GeocodingResult r, double minBuildingDistance); + } diff --git a/OsmAnd/src/net/osmand/plus/resources/RegionAddressRepositoryBinary.java b/OsmAnd/src/net/osmand/plus/resources/RegionAddressRepositoryBinary.java index 72b3256a57..636e18cc47 100644 --- a/OsmAnd/src/net/osmand/plus/resources/RegionAddressRepositoryBinary.java +++ b/OsmAnd/src/net/osmand/plus/resources/RegionAddressRepositoryBinary.java @@ -4,6 +4,7 @@ package net.osmand.plus.resources; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -18,6 +19,8 @@ import net.osmand.ResultMatcher; import net.osmand.binary.BinaryMapAddressReaderAdapter; import net.osmand.binary.BinaryMapIndexReader; import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.GeocodingUtilities; +import net.osmand.binary.GeocodingUtilities.GeocodingResult; import net.osmand.data.Building; import net.osmand.data.City; import net.osmand.data.LatLon; @@ -59,6 +62,21 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository { public void close(){ this.file = null; } + + @Override + public BinaryMapIndexReader getFile() { + return file; + } + + @Override + public synchronized List justifyReverseGeocodingSearch(GeocodingResult r, double minBuildingDistance) { + try { + return new GeocodingUtilities().justifyReverseGeocodingSearch(r, file, minBuildingDistance); + } catch(IOException e) { + log.error("Disk operation failed", e); //$NON-NLS-1$ + } + return Collections.emptyList(); + } @Override