Merge branch 'r3.4'

Conflicts:
	OsmAnd-java/src/main/java/net/osmand/data/TransportStop.java
This commit is contained in:
Victor Shcherb 2019-07-29 16:28:30 +02:00
commit 8b3441220e
3 changed files with 170 additions and 92 deletions

View file

@ -8,7 +8,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class TransportStop extends MapObject {
private static final int DELETED_STOP = -1;
@ -33,6 +32,13 @@ public class TransportStop extends MapObject {
public void setRoutes(List<TransportRoute> routes) {
this.routes = routes;
}
public void addRoute(TransportRoute rt) {
if (this.routes == null) {
this.routes = new ArrayList<TransportRoute>();
}
this.routes.add(rt);
}
public int[] getReferencesToRoutes() {
return referencesToRoutes;
@ -187,8 +193,18 @@ public class TransportStop extends MapObject {
// ((this.routesIds == null && thatObj.routesIds == null) || (this.routesIds != null && this.routesIds.equals(thatObj.routesIds))) &&
((this.exits == null && thatObj.exits == null) || (this.exits != null && thatObj.exits != null && this.exits.size() == thatObj.exits.size()))) {
if (this.exits != null) {
for (int i = 0; i < this.exits.size(); i++) {
if (!this.exits.get(i).compareExit(thatObj.exits.get(i))) {
for (TransportStopExit exit1 : this.exits) {
boolean contains = false;
for (TransportStopExit exit2 : thatObj.exits) {
if (exit1.getId().equals(exit2.getId())) {
contains = true;
if (!exit1.compareExit(exit2)) {
return false;
}
break;
}
}
if (!contains) {
return false;
}
}

View file

@ -1,5 +1,20 @@
package net.osmand.router;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import gnu.trove.iterator.TIntIterator;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.map.hash.TLongObjectHashMap;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
import net.osmand.data.LatLon;
@ -11,20 +26,6 @@ import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Way;
import net.osmand.util.MapUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import gnu.trove.iterator.TIntIterator;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.map.hash.TLongObjectHashMap;
public class TransportRoutePlanner {
private static final boolean MEASURE_TIME = false;
@ -761,91 +762,152 @@ public class TransportRoutePlanner {
int pz = (31 - cfg.ZOOM_TO_LOAD_TILES);
SearchRequest<TransportStop> sr = BinaryMapIndexReader.buildSearchTransportRequest(x << pz, (x + 1) << pz,
y << pz, (y + 1) << pz, -1, null);
TIntArrayList references = new TIntArrayList();
TIntArrayList referencesToLoad = new TIntArrayList();
// should it be global?
// could be global ?
TLongObjectHashMap<TransportStop> loadedTransportStops = new TLongObjectHashMap<TransportStop>();
TIntArrayList localFileRoutesToLoad = new TIntArrayList();
for (BinaryMapIndexReader r : routeMap.keySet()) {
sr.clearSearchResults();
references.clear();
referencesToLoad.clear();
List<TransportStop> existingStops = null;
List<TransportStop> stops = r.searchTransportIndex(sr);
for (TransportStop s : stops) {
if (!loadedTransportStops.contains(s.getId())) {
loadedTransportStops.put(s.getId(), s);
if (!s.isDeleted()) {
references.addAll(s.getReferencesToRoutes());
}
} else {
if (existingStops == null) {
existingStops = new ArrayList<>();
}
existingStops.add(s);
}
}
if (existingStops != null && existingStops.size() > 0) {
stops.removeAll(existingStops);
}
if (references.size() > 0) {
references.sort();
localFileRoutesToLoad.clear();
prepareRoutesToLoad(loadedTransportStops, stops, localFileRoutesToLoad);
// load routes and create transport segments
TIntObjectHashMap<TransportRoute> localFileRoutes = new TIntObjectHashMap<TransportRoute>();
if (localFileRoutesToLoad.size() > 0) {
localFileRoutesToLoad.sort();
TIntArrayList referencesToLoad = new TIntArrayList();
TIntObjectHashMap<TransportRoute> loadedRoutes = routeMap.get(r);
TIntObjectHashMap<TransportRoute> routes = new TIntObjectHashMap<TransportRoute>();
TIntIterator it = references.iterator();
int p = references.get(0) + 1; // different
TIntIterator it = localFileRoutesToLoad.iterator();
int p = localFileRoutesToLoad.get(0) + 1; // different
while (it.hasNext()) {
int nxt = it.next();
if (p != nxt) {
if (loadedRoutes.contains(nxt)) {
routes.put(nxt, loadedRoutes.get(nxt));
localFileRoutes.put(nxt, loadedRoutes.get(nxt));
} else {
referencesToLoad.add(nxt);
}
}
}
r.loadTransportRoutes(referencesToLoad.toArray(), routes);
loadedRoutes.putAll(routes);
loadTransportSegments(routes, r, stops, lst);
r.loadTransportRoutes(referencesToLoad.toArray(), localFileRoutes);
loadedRoutes.putAll(localFileRoutes);
}
for (TransportStop stop : stops) {
long stopId = stop.getId();
TransportStop multifileStop = loadedTransportStops.get(stopId);
int[] rrs = stop.getReferencesToRoutes();
if (multifileStop == stop) {
// clear up so it won't be used as it is multi file stop
stop.setReferencesToRoutes(null);
} else {
// add other routes
stop.setReferencesToRoutes(null);
}
if(rrs != null && !multifileStop.isDeleted()) {
for(int i = 0; i < rrs.length; i++) {
TransportRoute route = localFileRoutes.get(rrs[i]);
if(route == null) {
System.err.println(String.format("Something went wrong by loading route %d for stop %s", rrs[i], stop));
} else if(multifileStop == stop ||
(!multifileStop.hasRoute(route.getId()) &&
!multifileStop.isRouteDeleted(route.getId()))){
// duplicates won't be added
multifileStop.addRouteId(route.getId());
multifileStop.addRoute(route);
}
}
}
}
}
loadTransportSegments(loadedTransportStops.valueCollection(), lst);
readTime += System.nanoTime() - nanoTime;
return lst;
}
private void loadTransportSegments(TIntObjectHashMap<TransportRoute> routes, BinaryMapIndexReader r,
List<TransportStop> stops, List<TransportRouteSegment> lst) throws IOException {
private List<TransportStop> prepareRoutesToLoad(TLongObjectHashMap<TransportStop> loadedTransportStops,
List<TransportStop> stops, TIntArrayList resRoutesToLoad) {
Iterator<TransportStop> it = stops.iterator();
while (it.hasNext()) {
TransportStop stop = it.next();
long stopId = stop.getId();
TransportStop multifileStop = loadedTransportStops.get(stopId);
long[] routesIds = stop.getRoutesIds();
long[] delRIds = stop.getDeletedRoutesIds();
if (multifileStop == null) {
loadedTransportStops.put(stopId, stop);
if(!stop.isDeleted()) {
resRoutesToLoad.addAll(stop.getReferencesToRoutes());
}
} else if(multifileStop.isDeleted()){
// stop has noting to load, so not needed
it.remove();
} else {
if (delRIds != null) {
for (long deletedRouteId : delRIds) {
multifileStop.addDeletedRouteId(deletedRouteId);
}
}
if (routesIds != null && routesIds.length > 0) {
int[] refs = stop.getReferencesToRoutes();
for (int i = 0; i < routesIds.length; i++) {
long routeId = routesIds[i];
if (!multifileStop.hasRoute(routeId) && !multifileStop.isRouteDeleted(routeId)) {
resRoutesToLoad.add(refs[i]);
}
}
} else {
if (stop.hasReferencesToRoutes()) {
// old format
resRoutesToLoad.addAll(stop.getReferencesToRoutes());
} else {
// stop has noting to load, so not needed
it.remove();
}
}
}
}
return stops;
}
private void loadTransportSegments(Collection<TransportStop> stops, List<TransportRouteSegment> lst) throws IOException {
for(TransportStop s : stops) {
if (s.isDeleted()) {
if (s.isDeleted() || s.getRoutes() == null) {
continue;
}
for (int ref : s.getReferencesToRoutes()) {
TransportRoute route = routes.get(ref);
if (route != null) {
int stopIndex = -1;
double dist = TransportRoute.SAME_STOP;
for (int k = 0; k < route.getForwardStops().size(); k++) {
TransportStop st = route.getForwardStops().get(k);
double d = MapUtils.getDistance(st.getLocation(), s.getLocation());
if (d < dist) {
stopIndex = k;
dist = d;
}
for (TransportRoute route : s.getRoutes()) {
int stopIndex = -1;
double dist = TransportRoute.SAME_STOP;
for (int k = 0; k < route.getForwardStops().size(); k++) {
TransportStop st = route.getForwardStops().get(k);
if(st.getId().longValue() == s.getId().longValue() ) {
stopIndex = k;
break;
}
if (stopIndex != -1) {
if(cfg.useSchedule) {
loadScheduleRouteSegment(lst, route, stopIndex);
} else {
TransportRouteSegment segment = new TransportRouteSegment(route, stopIndex);
lst.add(segment);
}
double d = MapUtils.getDistance(st.getLocation(), s.getLocation());
if (d < dist) {
stopIndex = k;
dist = d;
}
}
if (stopIndex != -1) {
if (cfg.useSchedule) {
loadScheduleRouteSegment(lst, route, stopIndex);
} else {
// MapUtils.getDistance(s.getLocation(), route.getForwardStops().get(158).getLocation());
System.err.println(
String.format("Routing error: missing stop '%s' in route '%s' id: %d",
s.toString(), route.getRef(), route.getId() / 2));
TransportRouteSegment segment = new TransportRouteSegment(route, stopIndex);
lst.add(segment);
}
} else {
// MapUtils.getDistance(s.getLocation(), route.getForwardStops().get(158).getLocation());
System.err.println(String.format("Routing error: missing stop '%s' in route '%s' id: %d",
s.toString(), route.getRef(), route.getId() / 2));
}
}
}

View file

@ -948,27 +948,27 @@ public class ResourceManager {
}
return repos;
}
public List<TransportStop> searchTransportSync(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, ResultMatcher<TransportStop> matcher){
List<TransportIndexRepository> repos = new ArrayList<TransportIndexRepository>();
public List<TransportStop> searchTransportSync(double topLat, double leftLon, double bottomLat, double rightLon, ResultMatcher<TransportStop> matcher) {
List<TransportIndexRepository> repos = new ArrayList<>();
List<TransportStop> stops = new ArrayList<>();
for (TransportIndexRepository index : transportRepositories.values()) {
if (index.isUseForPublicTransport() && index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) {
if (index.isUseForPublicTransport() && index.checkContains(topLat, leftLon, bottomLat, rightLon)) {
repos.add(index);
}
}
if (!repos.isEmpty()){
TLongArrayList addedTransportStops = new TLongArrayList();
for (TransportIndexRepository repository : repos) {
List<TransportStop> ls = new ArrayList<>();
repository.searchTransportStops(topLatitude, leftLongitude, bottomLatitude, rightLongitude,
-1, ls, matcher);
for (TransportStop tstop : ls) {
if (!addedTransportStops.contains(tstop.getId())) {
addedTransportStops.add(tstop.getId());
if (!tstop.isDeleted()) {
stops.add(tstop);
if (!repos.isEmpty()) {
TLongArrayList addedStops = new TLongArrayList();
for (int i = repos.size() - 1; i >= 0; i--) {
TransportIndexRepository r = repos.get(i);
List<TransportStop> repStops = new ArrayList<>();
r.searchTransportStops(topLat, leftLon, bottomLat, rightLon, -1, repStops, matcher);
for (TransportStop s : repStops) {
if (!addedStops.contains(s.getId())) {
addedStops.add(s.getId());
if (!s.isDeleted()) {
stops.add(s);
}
}
}