Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
9ca2b0fe61
11 changed files with 451 additions and 54 deletions
|
@ -594,6 +594,7 @@ public class BinaryMapAddressReaderAdapter {
|
||||||
int old = codedIS.pushLimit(len);
|
int old = codedIS.pushLimit(len);
|
||||||
LatLon l = obj.getLocation();
|
LatLon l = obj.getLocation();
|
||||||
Street s = new Street(obj);
|
Street s = new Street(obj);
|
||||||
|
s.setFileOffset(list.get(j));
|
||||||
readStreet(s, null, false, MapUtils.get31TileNumberX(l.getLongitude()) >> 7,
|
readStreet(s, null, false, MapUtils.get31TileNumberX(l.getLongitude()) >> 7,
|
||||||
MapUtils.get31TileNumberY(l.getLatitude()) >> 7, obj.isPostcode() ? obj.getName() : null,
|
MapUtils.get31TileNumberY(l.getLatitude()) >> 7, obj.isPostcode() ? obj.getName() : null,
|
||||||
reg.attributeTagsTable);
|
reg.attributeTagsTable);
|
||||||
|
|
|
@ -21,10 +21,12 @@ import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
@ -1951,7 +1953,8 @@ public class BinaryMapIndexReader {
|
||||||
|
|
||||||
private static boolean testMapSearch = false;
|
private static boolean testMapSearch = false;
|
||||||
private static boolean testAddressSearch = 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 testPoiSearchOnPath = false;
|
||||||
private static boolean testTransportSearch = false;
|
private static boolean testTransportSearch = false;
|
||||||
private static int sleft = MapUtils.get31TileNumberX(6.3);
|
private static int sleft = MapUtils.get31TileNumberX(6.3);
|
||||||
|
@ -1965,7 +1968,8 @@ public class BinaryMapIndexReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
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");
|
RandomAccessFile raf = new RandomAccessFile(fl, "r");
|
||||||
|
|
||||||
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf, fl);
|
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf, fl);
|
||||||
|
@ -1979,6 +1983,9 @@ public class BinaryMapIndexReader {
|
||||||
testAddressSearchByName(reader);
|
testAddressSearchByName(reader);
|
||||||
testAddressSearch(reader);
|
testAddressSearch(reader);
|
||||||
}
|
}
|
||||||
|
if(testAddressJustifySearch) {
|
||||||
|
testAddressJustifySearch(reader);
|
||||||
|
}
|
||||||
if(testTransportSearch) {
|
if(testTransportSearch) {
|
||||||
testTransportSearch(reader);
|
testTransportSearch(reader);
|
||||||
}
|
}
|
||||||
|
@ -2259,6 +2266,71 @@ public class BinaryMapIndexReader {
|
||||||
reader.searchAddressDataByName(req);
|
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 {
|
private static void testAddressSearch(BinaryMapIndexReader reader) throws IOException {
|
||||||
// test address index search
|
// test address index search
|
||||||
final Map<String, Integer> streetFreq = new HashMap<String, Integer>();
|
final Map<String, Integer> streetFreq = new HashMap<String, Integer>();
|
||||||
|
|
|
@ -215,6 +215,7 @@ public class BinaryMapRouteReaderAdapter {
|
||||||
int destinationTypeRule = -1;
|
int destinationTypeRule = -1;
|
||||||
int destinationRefTypeRule = -1;
|
int destinationRefTypeRule = -1;
|
||||||
|
|
||||||
|
|
||||||
public RouteTypeRule quickGetEncodingRule(int id) {
|
public RouteTypeRule quickGetEncodingRule(int id) {
|
||||||
return routeEncodingRules.get(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;
|
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 px = MapUtils.get31TileNumberX(lon);
|
||||||
int py = MapUtils.get31TileNumberY(lat);
|
int py = MapUtils.get31TileNumberY(lat);
|
||||||
ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
|
ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
|
||||||
|
@ -63,12 +63,10 @@ public class RoutePlannerFrontEnd {
|
||||||
if (dataObjects.isEmpty()) {
|
if (dataObjects.isEmpty()) {
|
||||||
ctx.loadTileData(px, py, 15, dataObjects);
|
ctx.loadTileData(px, py, 15, dataObjects);
|
||||||
}
|
}
|
||||||
List<RouteSegmentPoint> list = new ArrayList<BinaryRoutePlanner.RouteSegmentPoint>();
|
if(list == null) {
|
||||||
for (RouteDataObject r : dataObjects) {
|
list = new ArrayList<BinaryRoutePlanner.RouteSegmentPoint>();
|
||||||
boolean emptyName = Algorithms.isEmpty(r.getName()) && Algorithms.isEmpty(r.getRef()) ;
|
|
||||||
if(searchWithName && emptyName) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
for (RouteDataObject r : dataObjects) {
|
||||||
if (r.getPointsLength() > 1) {
|
if (r.getPointsLength() > 1) {
|
||||||
RouteSegmentPoint road = null;
|
RouteSegmentPoint road = null;
|
||||||
for (int j = 1; j < r.getPointsLength(); j++) {
|
for (int j = 1; j < r.getPointsLength(); j++) {
|
||||||
|
@ -95,7 +93,7 @@ public class RoutePlannerFrontEnd {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(list.size() > 0) {
|
if(list.size() > 0) {
|
||||||
RouteSegmentPoint ps = list.remove(0);
|
RouteSegmentPoint ps = list.get(0);
|
||||||
ps.others = list;
|
ps.others = list;
|
||||||
return ps;
|
return ps;
|
||||||
}
|
}
|
||||||
|
@ -284,7 +282,7 @@ public class RoutePlannerFrontEnd {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addSegment(LatLon s, RoutingContext ctx, int indexNotFound, List<RouteSegmentPoint> res) throws IOException {
|
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){
|
if(f == null){
|
||||||
ctx.calculationProgress.segmentNotFound = indexNotFound;
|
ctx.calculationProgress.segmentNotFound = indexNotFound;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -310,8 +310,8 @@ public class TestRouting {
|
||||||
RoutingConfiguration rconfig = config.build(vehicle, MEMORY_TEST_LIMIT);
|
RoutingConfiguration rconfig = config.build(vehicle, MEMORY_TEST_LIMIT);
|
||||||
RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(oldRouting);
|
RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(oldRouting);
|
||||||
RoutingContext ctx = router.buildRoutingContext(rconfig, lib, rs);
|
RoutingContext ctx = router.buildRoutingContext(rconfig, lib, rs);
|
||||||
RouteSegment startSegment = router.findRouteSegment(startLat, startLon, false, ctx);
|
RouteSegment startSegment = router.findRouteSegment(startLat, startLon, ctx, null);
|
||||||
RouteSegment endSegment = router.findRouteSegment(endLat, endLon, false, ctx);
|
RouteSegment endSegment = router.findRouteSegment(endLat, endLon, ctx, null);
|
||||||
if(startSegment == null){
|
if(startSegment == null){
|
||||||
throw new IllegalArgumentException("Start segment is not found ");
|
throw new IllegalArgumentException("Start segment is not found ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
package net.osmand.plus;
|
package net.osmand.plus;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import net.osmand.Location;
|
import net.osmand.Location;
|
||||||
import net.osmand.ResultMatcher;
|
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.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.RouteSegment;
|
||||||
import net.osmand.router.BinaryRoutePlanner.RouteSegmentPoint;
|
import net.osmand.router.BinaryRoutePlanner.RouteSegmentPoint;
|
||||||
import net.osmand.router.GeneralRouter.GeneralRouterProfile;
|
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) {
|
if (loc != null) {
|
||||||
Runnable run = new Runnable() {
|
Runnable run = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
RouteDataObject res = runUpdateInThread(loc.getLatitude(), loc.getLongitude(), result);
|
final List<GeocodingResult> gr = runUpdateInThread(loc.getLatitude(), loc.getLongitude());
|
||||||
if (storeFound) {
|
if (storeFound) {
|
||||||
lastAskedLocation = loc;
|
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) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
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){
|
private static double getOrthogonalDistance(RouteDataObject r, Location loc){
|
||||||
double d = 1000;
|
double d = 1000;
|
||||||
if (r.getPointsLength() > 0) {
|
if (r.getPointsLength() > 0) {
|
||||||
|
@ -86,7 +159,11 @@ public class CurrentPositionHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getRouteSegment(Location loc, ResultMatcher<RouteDataObject> result) {
|
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) {
|
public RouteDataObject getLastKnownRouteSegment(Location loc) {
|
||||||
|
@ -99,12 +176,12 @@ public class CurrentPositionHelper {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if (r == null) {
|
if (r == null) {
|
||||||
scheduleRouteSegmentFind(loc, null, true);
|
scheduleRouteSegmentFind(loc, true, null, null);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
double d = getOrthogonalDistance(r, loc);
|
double d = getOrthogonalDistance(r, loc);
|
||||||
if (d > 25) {
|
if (d > 25) {
|
||||||
scheduleRouteSegmentFind(loc, null, true);
|
scheduleRouteSegmentFind(loc, true, null, null);
|
||||||
}
|
}
|
||||||
if (d < 70) {
|
if (d < 70) {
|
||||||
return r;
|
return r;
|
||||||
|
@ -113,34 +190,13 @@ public class CurrentPositionHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private synchronized RouteDataObject runUpdateInThread(double lat, double lon, final ResultMatcher<RouteDataObject> resultMatcher) throws IOException {
|
private synchronized List<GeocodingResult> runUpdateInThread(double lat, double lon) throws IOException {
|
||||||
RoutePlannerFrontEnd rp = new RoutePlannerFrontEnd(false);
|
|
||||||
if (ctx == null || am != app.getSettings().getApplicationMode()) {
|
if (ctx == null || am != app.getSettings().getApplicationMode()) {
|
||||||
initCtx(app);
|
initCtx(app);
|
||||||
if (ctx == null) {
|
if (ctx == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final RouteSegmentPoint sg = rp.findRouteSegment(lat, lon, true, ctx);
|
return new GeocodingUtilities().reverseGeocodingSearch(ctx, lat, lon);
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,11 @@ import android.os.Bundle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.osmand.GeoidAltitudeCorrection;
|
import net.osmand.GeoidAltitudeCorrection;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
import net.osmand.ResultMatcher;
|
import net.osmand.ResultMatcher;
|
||||||
import net.osmand.access.NavigationInfo;
|
import net.osmand.access.NavigationInfo;
|
||||||
|
import net.osmand.binary.GeocodingUtilities.GeocodingResult;
|
||||||
import net.osmand.binary.RouteDataObject;
|
import net.osmand.binary.RouteDataObject;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.QuadPoint;
|
import net.osmand.data.QuadPoint;
|
||||||
|
@ -849,6 +849,10 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
currentPositionHelper.getRouteSegment(loc, result);
|
currentPositionHelper.getRouteSegment(loc, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void getGeocodingResult(net.osmand.Location loc, ResultMatcher<GeocodingResult> result) {
|
||||||
|
currentPositionHelper.getGeocodingResult(loc, result);
|
||||||
|
}
|
||||||
|
|
||||||
public net.osmand.Location getLastKnownLocation() {
|
public net.osmand.Location getLastKnownLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package net.osmand.plus.mapcontextmenu;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import net.osmand.Location;
|
import net.osmand.Location;
|
||||||
import net.osmand.ResultMatcher;
|
import net.osmand.ResultMatcher;
|
||||||
|
import net.osmand.binary.GeocodingUtilities.GeocodingResult;
|
||||||
import net.osmand.binary.RouteDataObject;
|
import net.osmand.binary.RouteDataObject;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.PointDescription;
|
import net.osmand.data.PointDescription;
|
||||||
|
@ -134,24 +135,37 @@ public abstract class MenuTitleController {
|
||||||
ll.setLatitude(getLatLon().getLatitude());
|
ll.setLatitude(getLatLon().getLatitude());
|
||||||
ll.setLongitude(getLatLon().getLongitude());
|
ll.setLongitude(getLatLon().getLongitude());
|
||||||
getMapActivity().getMyApplication().getLocationProvider()
|
getMapActivity().getMyApplication().getLocationProvider()
|
||||||
.getRouteSegment(ll, new ResultMatcher<RouteDataObject>() {
|
.getGeocodingResult(ll, new ResultMatcher<GeocodingResult>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean publish(RouteDataObject object) {
|
public boolean publish(GeocodingResult object) {
|
||||||
if (object != null) {
|
if (object != null) {
|
||||||
OsmandSettings settings = getMapActivity().getMyApplication().getSettings();
|
OsmandSettings settings = getMapActivity().getMyApplication().getSettings();
|
||||||
String streetName = object.getName(settings.MAP_PREFERRED_LOCALE.get());
|
String lang = settings.MAP_PREFERRED_LOCALE.get();
|
||||||
String ref = object.getRef();
|
String geocodingResult = "";
|
||||||
if(Algorithms.isEmpty(streetName)) {
|
if(object.building != null) {
|
||||||
streetName = "";
|
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 = "";
|
||||||
}
|
}
|
||||||
|
String ref = rd.getRef();
|
||||||
if(!Algorithms.isEmpty(ref)) {
|
if(!Algorithms.isEmpty(ref)) {
|
||||||
if(!Algorithms.isEmpty(streetName)) {
|
if(!Algorithms.isEmpty(sname)) {
|
||||||
streetName += ", ";
|
sname += ", ";
|
||||||
}
|
}
|
||||||
streetName += ref;
|
sname += ref;
|
||||||
}
|
}
|
||||||
streetStr = streetName;
|
geocodingResult = sname;
|
||||||
|
}
|
||||||
|
|
||||||
|
streetStr = geocodingResult;
|
||||||
if (!Algorithms.isEmpty(streetStr)) {
|
if (!Algorithms.isEmpty(streetStr)) {
|
||||||
MenuController menuController = getMenuController();
|
MenuController menuController = getMenuController();
|
||||||
if (menuController == null || menuController.displayStreetNameInTitle()) {
|
if (menuController == null || menuController.displayStreetNameInTitle()) {
|
||||||
|
|
|
@ -5,6 +5,8 @@ import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.osmand.ResultMatcher;
|
import net.osmand.ResultMatcher;
|
||||||
|
import net.osmand.binary.BinaryMapIndexReader;
|
||||||
|
import net.osmand.binary.GeocodingUtilities.GeocodingResult;
|
||||||
import net.osmand.data.Building;
|
import net.osmand.data.Building;
|
||||||
import net.osmand.data.City;
|
import net.osmand.data.City;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
|
@ -56,6 +58,7 @@ public interface RegionAddressRepository {
|
||||||
public List<MapObject> searchMapObjectsByName(String name, ResultMatcher<MapObject> resultMatcher);
|
public List<MapObject> searchMapObjectsByName(String name, ResultMatcher<MapObject> resultMatcher);
|
||||||
|
|
||||||
|
|
||||||
|
public BinaryMapIndexReader getFile();
|
||||||
|
|
||||||
public static class MapObjectNameDistanceComparator implements Comparator<MapObject> {
|
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.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -18,6 +19,8 @@ import net.osmand.ResultMatcher;
|
||||||
import net.osmand.binary.BinaryMapAddressReaderAdapter;
|
import net.osmand.binary.BinaryMapAddressReaderAdapter;
|
||||||
import net.osmand.binary.BinaryMapIndexReader;
|
import net.osmand.binary.BinaryMapIndexReader;
|
||||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
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.Building;
|
||||||
import net.osmand.data.City;
|
import net.osmand.data.City;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
|
@ -60,6 +63,21 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
|
||||||
this.file = null;
|
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
|
@Override
|
||||||
public synchronized void preloadCities(ResultMatcher<City> resultMatcher) {
|
public synchronized void preloadCities(ResultMatcher<City> resultMatcher) {
|
||||||
|
|
Loading…
Reference in a new issue