Improve geocoing
This commit is contained in:
parent
8df21aa29a
commit
899ca53231
11 changed files with 451 additions and 54 deletions
|
@ -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);
|
||||
|
|
|
@ -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<Street> streetsList = new ArrayList<Street>();
|
||||
SearchRequest<MapObject> req = buildAddressByNameRequest(new ResultMatcher<MapObject>() {
|
||||
@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<MapObject, Street> resMap = new TreeMap<MapObject, Street>(new Comparator<MapObject>() {
|
||||
|
||||
@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<String, Integer> streetFreq = new HashMap<String, Integer>();
|
||||
|
|
|
@ -215,6 +215,7 @@ public class BinaryMapRouteReaderAdapter {
|
|||
int destinationTypeRule = -1;
|
||||
int destinationRefTypeRule = -1;
|
||||
|
||||
|
||||
public RouteTypeRule quickGetEncodingRule(int id) {
|
||||
return routeEncodingRules.get(id);
|
||||
}
|
||||
|
|
228
OsmAnd-java/src/net/osmand/binary/GeocodingUtilities.java
Normal file
228
OsmAnd-java/src/net/osmand/binary/GeocodingUtilities.java
Normal file
|
@ -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<GeocodingResult> DISTANCE_COMPARATOR = new Comparator<GeocodingResult>() {
|
||||
|
||||
@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<GeocodingResult> reverseGeocodingSearch(RoutingContext ctx, double lat, double lon) throws IOException {
|
||||
RoutePlannerFrontEnd rp = new RoutePlannerFrontEnd(false);
|
||||
List<GeocodingResult> lst = new ArrayList<GeocodingUtilities.GeocodingResult>();
|
||||
List<RouteSegmentPoint> listR = new ArrayList<BinaryRoutePlanner.RouteSegmentPoint>();
|
||||
rp.findRouteSegment(lat, lon, ctx, listR);
|
||||
double dist = 0;
|
||||
TLongHashSet set = new TLongHashSet();
|
||||
Set<String> streetNames = new HashSet<String>();
|
||||
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<GeocodingResult> justifyReverseGeocodingSearch(final GeocodingResult r, BinaryMapIndexReader reader,
|
||||
double knownMinBuidlingDistance) throws IOException {
|
||||
// test address index search
|
||||
final List<GeocodingResult> streetsList = new ArrayList<GeocodingResult>();
|
||||
log.info("Search street by name " + r.streetName);
|
||||
SearchRequest<MapObject> req = BinaryMapIndexReader.buildAddressByNameRequest(new ResultMatcher<MapObject>() {
|
||||
@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<GeocodingResult> res = new ArrayList<GeocodingResult>();
|
||||
// FIXME interpolation
|
||||
for(GeocodingResult s : streetsList) {
|
||||
final List<GeocodingResult> streetBuildings = new ArrayList<GeocodingResult>();
|
||||
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<GeocodingResult> 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;
|
||||
}
|
||||
}
|
|
@ -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<RouteSegmentPoint> list) throws IOException {
|
||||
int px = MapUtils.get31TileNumberX(lon);
|
||||
int py = MapUtils.get31TileNumberY(lat);
|
||||
ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
|
||||
|
@ -63,12 +63,10 @@ public class RoutePlannerFrontEnd {
|
|||
if (dataObjects.isEmpty()) {
|
||||
ctx.loadTileData(px, py, 15, dataObjects);
|
||||
}
|
||||
List<RouteSegmentPoint> list = new ArrayList<BinaryRoutePlanner.RouteSegmentPoint>();
|
||||
if(list == null) {
|
||||
list = new ArrayList<BinaryRoutePlanner.RouteSegmentPoint>();
|
||||
}
|
||||
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<RouteSegmentPoint> 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;
|
||||
|
|
|
@ -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 ");
|
||||
}
|
||||
|
|
|
@ -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<RouteDataObject> result, final boolean storeFound) {
|
||||
private void scheduleRouteSegmentFind(final Location loc, final boolean storeFound, final ResultMatcher<GeocodingResult> geoCoding, final ResultMatcher<RouteDataObject> result) {
|
||||
if (loc != null) {
|
||||
Runnable run = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
RouteDataObject res = runUpdateInThread(loc.getLatitude(), loc.getLongitude(), result);
|
||||
final List<GeocodingResult> 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<GeocodingResult> res, final ResultMatcher<GeocodingResult> result) {
|
||||
double minBuildingDistance = 0;
|
||||
List<GeocodingResult> complete = new ArrayList<GeocodingUtilities.GeocodingResult>();
|
||||
for (GeocodingResult r : res) {
|
||||
if (minBuildingDistance > 0
|
||||
&& r.getDistance() > GeocodingUtilities.THRESHOLD_MULTIPLIER_SKIP_STREETS_AFTER * minBuildingDistance) {
|
||||
break;
|
||||
}
|
||||
Collection<RegionAddressRepository> 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<GeocodingResult> 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<RouteDataObject> result) {
|
||||
scheduleRouteSegmentFind(loc, result, false);
|
||||
scheduleRouteSegmentFind(loc, false, null, result);
|
||||
}
|
||||
|
||||
public void getGeocodingResult(Location loc, ResultMatcher<GeocodingResult> 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<RouteDataObject> resultMatcher) throws IOException {
|
||||
RoutePlannerFrontEnd rp = new RoutePlannerFrontEnd(false);
|
||||
private synchronized List<GeocodingResult> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<RouteDataObject> result) {
|
||||
currentPositionHelper.getRouteSegment(loc, result);
|
||||
}
|
||||
|
||||
public void getGeocodingResult(net.osmand.Location loc, ResultMatcher<GeocodingResult> result) {
|
||||
currentPositionHelper.getGeocodingResult(loc, result);
|
||||
}
|
||||
|
||||
public net.osmand.Location getLastKnownLocation() {
|
||||
return location;
|
||||
|
|
|
@ -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<RouteDataObject>() {
|
||||
.getGeocodingResult(ll, new ResultMatcher<GeocodingResult>() {
|
||||
|
||||
@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()) {
|
||||
|
|
|
@ -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<MapObject> searchMapObjectsByName(String name, ResultMatcher<MapObject> resultMatcher);
|
||||
|
||||
|
||||
public BinaryMapIndexReader getFile();
|
||||
|
||||
public static class MapObjectNameDistanceComparator implements Comparator<MapObject> {
|
||||
|
||||
|
@ -87,4 +90,6 @@ public interface RegionAddressRepository {
|
|||
}
|
||||
}
|
||||
|
||||
public List<GeocodingResult> justifyReverseGeocodingSearch(GeocodingResult r, double minBuildingDistance);
|
||||
|
||||
}
|
||||
|
|
|
@ -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<GeocodingResult> 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
|
||||
|
|
Loading…
Reference in a new issue