This commit is contained in:
Victor Shcherb 2020-07-09 19:34:49 +02:00
parent 608f41dda9
commit e63e9b6865
5 changed files with 79 additions and 15 deletions

View file

@ -4,6 +4,7 @@ import net.osmand.PlatformUtil;
import net.osmand.ResultMatcher; import net.osmand.ResultMatcher;
import net.osmand.CollatorStringMatcher.StringMatcherMode; import net.osmand.CollatorStringMatcher.StringMatcherMode;
import net.osmand.binary.BinaryMapIndexReader.SearchRequest; import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
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;
@ -23,9 +24,11 @@ import java.text.Collator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import gnu.trove.set.hash.TLongHashSet; import gnu.trove.set.hash.TLongHashSet;
@ -40,7 +43,7 @@ public class GeocodingUtilities {
public static final float STOP_SEARCHING_STREET_WITH_MULTIPLIER_RADIUS = 250; public static final float STOP_SEARCHING_STREET_WITH_MULTIPLIER_RADIUS = 250;
public static final float STOP_SEARCHING_STREET_WITHOUT_MULTIPLIER_RADIUS = 400; public static final float STOP_SEARCHING_STREET_WITHOUT_MULTIPLIER_RADIUS = 400;
public static final int DISTANCE_STREET_NAME_PROXIMITY_BY_NAME = 15000; public static final int DISTANCE_STREET_NAME_PROXIMITY_BY_NAME = 45000;
public static final float DISTANCE_STREET_FROM_CLOSEST_WITH_SAME_NAME = 1000; public static final float DISTANCE_STREET_FROM_CLOSEST_WITH_SAME_NAME = 1000;
public static final float THRESHOLD_MULTIPLIER_SKIP_BUILDINGS_AFTER = 1.5f; public static final float THRESHOLD_MULTIPLIER_SKIP_BUILDINGS_AFTER = 1.5f;
@ -142,15 +145,12 @@ public class GeocodingUtilities {
RoutePlannerFrontEnd rp = new RoutePlannerFrontEnd(); RoutePlannerFrontEnd rp = new RoutePlannerFrontEnd();
List<GeocodingResult> lst = new ArrayList<GeocodingUtilities.GeocodingResult>(); List<GeocodingResult> lst = new ArrayList<GeocodingUtilities.GeocodingResult>();
List<RouteSegmentPoint> listR = new ArrayList<BinaryRoutePlanner.RouteSegmentPoint>(); List<RouteSegmentPoint> listR = new ArrayList<BinaryRoutePlanner.RouteSegmentPoint>();
rp.findRouteSegment(lat, lon, ctx, listR); // we allow duplications to search in both files for boundary regions
rp.findRouteSegment(lat, lon, ctx, listR, false, true);
double distSquare = 0; double distSquare = 0;
TLongHashSet set = new TLongHashSet(); Map<String, List<RouteRegion>> streetNames = new HashMap<>();
Set<String> streetNames = new HashSet<String>();
for (RouteSegmentPoint p : listR) { for (RouteSegmentPoint p : listR) {
RouteDataObject road = p.getRoad(); RouteDataObject road = p.getRoad();
if (!set.add(road.getId())) {
continue;
}
// System.out.println(road.toString() + " " + Math.sqrt(p.distSquare)); // System.out.println(road.toString() + " " + Math.sqrt(p.distSquare));
String name = Algorithms.isEmpty(road.getName()) ? road.getRef("", false, true) : road.getName(); String name = Algorithms.isEmpty(road.getName()) ? road.getRef("", false, true) : road.getName();
if (allowEmptyNames || !Algorithms.isEmpty(name)) { if (allowEmptyNames || !Algorithms.isEmpty(name)) {
@ -164,7 +164,13 @@ public class GeocodingUtilities {
sr.connectionPoint = new LatLon(MapUtils.get31LatitudeY(p.preciseY), MapUtils.get31LongitudeX(p.preciseX)); sr.connectionPoint = new LatLon(MapUtils.get31LatitudeY(p.preciseY), MapUtils.get31LongitudeX(p.preciseX));
sr.regionFP = road.region.getFilePointer(); sr.regionFP = road.region.getFilePointer();
sr.regionLen = road.region.getLength(); sr.regionLen = road.region.getLength();
if (streetNames.add(sr.streetName)) { List<RouteRegion> plst = streetNames.get(sr.streetName);
if (plst == null) {
plst = new ArrayList<BinaryMapRouteReaderAdapter.RouteRegion>();
streetNames.put(sr.streetName, plst);
}
if (!plst.contains(road.region)) {
plst.add(road.region);
lst.add(sr); lst.add(sr);
} }
} }
@ -308,6 +314,48 @@ public class GeocodingUtilities {
return res; return res;
} }
public void filterDuplicateRegionResults(final List<GeocodingResult> res) {
Collections.sort(res, DISTANCE_COMPARATOR);
// filter duplicate city results (when building is in both regions on boundary)
for (int i = 0; i < res.size() - 1;) {
int cmp = cmpResult(res.get(i), res.get(i + 1));
if (cmp > 0) {
res.remove(i);
} else if (cmp < 0) {
res.remove(i + 1);
} else {
// nothing to delete
i++;
}
}
}
private int cmpResult(GeocodingResult gr1, GeocodingResult gr2) {
boolean eqStreet = Algorithms.stringsEqual(gr1.streetName, gr2.streetName);
if (eqStreet) {
boolean sameObj = false;
if (gr1.building != null && gr2.building != null) {
if (Algorithms.stringsEqual(gr1.building.getName(), gr2.building.getName())) {
// same building
sameObj = true;
}
} else if (gr1.building == null && gr2.building == null) {
// same street
sameObj = true;
}
if (sameObj) {
double cityDist1 = MapUtils.getDistance(gr1.searchPoint, gr1.city.getLocation());
double cityDist2 = MapUtils.getDistance(gr2.searchPoint, gr2.city.getLocation());
if (cityDist1 < cityDist2) {
return -1;
} else {
return 1;
}
}
}
return 0;
}
private List<GeocodingResult> loadStreetBuildings(final GeocodingResult road, BinaryMapIndexReader reader, private List<GeocodingResult> loadStreetBuildings(final GeocodingResult road, BinaryMapIndexReader reader,
GeocodingResult street) throws IOException { GeocodingResult street) throws IOException {
final List<GeocodingResult> streetBuildings = new ArrayList<GeocodingResult>(); final List<GeocodingResult> streetBuildings = new ArrayList<GeocodingResult>();

View file

@ -117,15 +117,20 @@ public class RoutePlannerFrontEnd {
} }
public RouteSegmentPoint findRouteSegment(double lat, double lon, RoutingContext ctx, List<RouteSegmentPoint> list, boolean transportStop) throws IOException { public RouteSegmentPoint findRouteSegment(double lat, double lon, RoutingContext ctx, List<RouteSegmentPoint> list, boolean transportStop) throws IOException {
return findRouteSegment(lat, lon, ctx, list, false, false);
}
public RouteSegmentPoint findRouteSegment(double lat, double lon, RoutingContext ctx, List<RouteSegmentPoint> list, boolean transportStop,
boolean allowDuplications) 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>();
ctx.loadTileData(px, py, 17, dataObjects); ctx.loadTileData(px, py, 17, dataObjects, allowDuplications);
if (dataObjects.isEmpty()) { if (dataObjects.isEmpty()) {
ctx.loadTileData(px, py, 15, dataObjects); ctx.loadTileData(px, py, 15, dataObjects, allowDuplications);
} }
if (dataObjects.isEmpty()) { if (dataObjects.isEmpty()) {
ctx.loadTileData(px, py, 14, dataObjects); ctx.loadTileData(px, py, 14, dataObjects, allowDuplications);
} }
if (list == null) { if (list == null) {
list = new ArrayList<BinaryRoutePlanner.RouteSegmentPoint>(); list = new ArrayList<BinaryRoutePlanner.RouteSegmentPoint>();

View file

@ -412,6 +412,10 @@ public class RoutingContext {
} }
public void loadTileData(int x31, int y31, int zoomAround, final List<RouteDataObject> toFillIn) { public void loadTileData(int x31, int y31, int zoomAround, final List<RouteDataObject> toFillIn) {
loadTileData(x31, y31, zoomAround, toFillIn, false);
}
public void loadTileData(int x31, int y31, int zoomAround, final List<RouteDataObject> toFillIn, boolean allowDuplications) {
int t = config.ZOOM_TO_LOAD_TILES - zoomAround; int t = config.ZOOM_TO_LOAD_TILES - zoomAround;
int coordinatesShift = (1 << (31 - config.ZOOM_TO_LOAD_TILES)); int coordinatesShift = (1 << (31 - config.ZOOM_TO_LOAD_TILES));
if(t <= 0) { if(t <= 0) {
@ -432,6 +436,9 @@ public class RoutingContext {
TLongObjectHashMap<RouteDataObject> excludeDuplications = new TLongObjectHashMap<RouteDataObject>(); TLongObjectHashMap<RouteDataObject> excludeDuplications = new TLongObjectHashMap<RouteDataObject>();
while (it.hasNext()) { while (it.hasNext()) {
getAllObjects(it.next(), toFillIn, excludeDuplications); getAllObjects(it.next(), toFillIn, excludeDuplications);
if (allowDuplications) {
excludeDuplications.clear();
}
} }
timeToFindInitialSegments += (System.nanoTime() - now); timeToFindInitialSegments += (System.nanoTime() - now);
} }

View file

@ -237,6 +237,7 @@ public class CurrentPositionHelper {
List<GeocodingResult> complete = new ArrayList<>(); List<GeocodingResult> complete = new ArrayList<>();
double minBuildingDistance = 0; double minBuildingDistance = 0;
if (res != null) { if (res != null) {
GeocodingUtilities gu = new GeocodingUtilities();
for (GeocodingResult r : res) { for (GeocodingResult r : res) {
BinaryMapIndexReader foundRepo = null; BinaryMapIndexReader foundRepo = null;
List<BinaryMapReaderResource> rts = usedReaders; List<BinaryMapReaderResource> rts = usedReaders;
@ -259,7 +260,7 @@ public class CurrentPositionHelper {
} else if (foundRepo != null) { } else if (foundRepo != null) {
List<GeocodingResult> justified = null; List<GeocodingResult> justified = null;
try { try {
justified = new GeocodingUtilities().justifyReverseGeocodingSearch(r, foundRepo, justified = gu.justifyReverseGeocodingSearch(r, foundRepo,
minBuildingDistance, result); minBuildingDistance, result);
} catch (IOException e) { } catch (IOException e) {
log.error("Exception happened during reverse geocoding", e); log.error("Exception happened during reverse geocoding", e);
@ -277,6 +278,7 @@ public class CurrentPositionHelper {
complete.add(r); complete.add(r);
} }
} }
gu.filterDuplicateRegionResults(complete);
} }
if (result.isCancelled()) { if (result.isCancelled()) {
@ -287,7 +289,7 @@ public class CurrentPositionHelper {
}); });
return; return;
} }
Collections.sort(complete, GeocodingUtilities.DISTANCE_COMPARATOR); // Collections.sort(complete, GeocodingUtilities.DISTANCE_COMPARATOR);
// for(GeocodingResult rt : complete) { // for(GeocodingResult rt : complete) {
// System.out.println(rt.toString()); // System.out.println(rt.toString());
// } // }

View file

@ -191,6 +191,7 @@ public class CurrentPositionHelper {
private void justifyResult(List<GeocodingResult> res, final ResultMatcher<GeocodingResult> result) { private void justifyResult(List<GeocodingResult> res, final ResultMatcher<GeocodingResult> result) {
List<GeocodingResult> complete = new ArrayList<>(); List<GeocodingResult> complete = new ArrayList<>();
double minBuildingDistance = 0; double minBuildingDistance = 0;
GeocodingUtilities gu = new GeocodingUtilities();
if (res != null) { if (res != null) {
for (GeocodingResult r : res) { for (GeocodingResult r : res) {
BinaryMapIndexReader foundRepo = null; BinaryMapIndexReader foundRepo = null;
@ -208,7 +209,7 @@ public class CurrentPositionHelper {
} else if (foundRepo != null) { } else if (foundRepo != null) {
List<GeocodingResult> justified = null; List<GeocodingResult> justified = null;
try { try {
justified = new GeocodingUtilities().justifyReverseGeocodingSearch(r, foundRepo, justified = gu.justifyReverseGeocodingSearch(r, foundRepo,
minBuildingDistance, result); minBuildingDistance, result);
} catch (IOException e) { } catch (IOException e) {
log.error("Exception happened during reverse geocoding", e); log.error("Exception happened during reverse geocoding", e);
@ -227,6 +228,7 @@ public class CurrentPositionHelper {
complete.add(r); complete.add(r);
} }
} }
gu.filterDuplicateRegionResults(complete);
} }
if (result.isCancelled()) { if (result.isCancelled()) {
@ -237,7 +239,7 @@ public class CurrentPositionHelper {
}); });
return; return;
} }
Collections.sort(complete, GeocodingUtilities.DISTANCE_COMPARATOR); // Collections.sort(complete, GeocodingUtilities.DISTANCE_COMPARATOR);
// for(GeocodingResult rt : complete) { // for(GeocodingResult rt : complete) {
// System.out.println(rt.toString()); // System.out.println(rt.toString());
// } // }