Merge branch 'r3.4'
Conflicts: OsmAnd-java/src/main/java/net/osmand/data/TransportStop.java
This commit is contained in:
commit
8b3441220e
3 changed files with 170 additions and 92 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue