Use live changes for public transport

This commit is contained in:
crimean 2019-03-04 14:29:26 +03:00
parent 73778122cb
commit cc94ead73d
19 changed files with 238 additions and 52 deletions

View file

@ -267,18 +267,11 @@ public class Amenity extends MapObject {
setAdditionalInfo(OPENING_HOURS, openingHours);
}
public boolean comparePoi(Amenity thatObj) {
if (this.id.longValue() == thatObj.id.longValue() &&
return this.compareObject(thatObj) &&
Algorithms.objectEquals(this.type.getKeyName(), thatObj.type.getKeyName()) &&
Algorithms.objectEquals(getLocation(), thatObj.getLocation()) &&
Algorithms.objectEquals(this.subType, thatObj.subType) &&
Algorithms.objectEquals(this.additionalInfo, thatObj.additionalInfo) &&
Algorithms.objectEquals(this.getName(), thatObj.getName()) &&
Algorithms.objectEquals(this.getNamesMap(true), thatObj.getNamesMap(true))) {
return true;
}
return false;
Algorithms.objectEquals(this.additionalInfo, thatObj.additionalInfo);
}
@Override

View file

@ -9,6 +9,7 @@ import net.osmand.util.TransliterationHelper;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@ -28,7 +29,6 @@ public abstract class MapObject implements Comparable<MapObject> {
public static final byte WAY_MODULO_REMAINDER = 1;
protected String name = null;
protected String enName = null;
/**
@ -258,6 +258,17 @@ public abstract class MapObject implements Comparable<MapObject> {
return true;
}
public boolean compareObject(MapObject thatObj) {
if (this == thatObj) {
return true;
} else {
return this.id.longValue() == thatObj.id.longValue() &&
Algorithms.objectEquals(getLocation(), thatObj.getLocation()) &&
Algorithms.objectEquals(this.getName(), thatObj.getName()) &&
Algorithms.objectEquals(this.getNamesMap(true), thatObj.getNamesMap(true));
}
}
public static class MapObjectComparator implements Comparator<MapObject> {
private final String l;
Collator collator = OsmAndCollator.primaryCollator();

View file

@ -2,6 +2,7 @@ package net.osmand.data;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Way;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import java.util.ArrayList;
@ -23,7 +24,7 @@ public class TransportRoute extends MapObject {
private TransportSchedule schedule;
public static final double SAME_STOP = 25;
public TransportRoute(){
public TransportRoute() {
}
public TransportSchedule getSchedule() {
@ -31,7 +32,7 @@ public class TransportRoute extends MapObject {
}
public TransportSchedule getOrCreateSchedule() {
if(schedule == null) {
if (schedule == null) {
schedule = new TransportSchedule();
}
return schedule;
@ -221,4 +222,35 @@ public class TransportRoute extends MapObject {
}
return ref;
}
public boolean compareRoute(TransportRoute thatObj) {
if (this.compareObject(thatObj) &&
Algorithms.objectEquals(this.ref, thatObj.ref) &&
Algorithms.objectEquals(this.operator, thatObj.operator) &&
Algorithms.objectEquals(this.type, thatObj.type) &&
Algorithms.objectEquals(this.color, thatObj.color) &&
this.getDistance() == thatObj.getDistance() &&
((this.schedule == null && thatObj.schedule == null) ||
(this.schedule != null && thatObj.schedule != null && this.schedule.compareSchedule(thatObj.schedule))) &&
this.forwardStops.size() == thatObj.forwardStops.size() &&
((this.forwardWays == null && thatObj.forwardWays == null) ||
(this.forwardWays != null && thatObj.forwardWays != null && this.forwardWays.size() == thatObj.forwardWays.size()))) {
for (int i = 0; i < this.forwardStops.size(); i++) {
if (!this.forwardStops.get(i).compareStop(thatObj.forwardStops.get(i))) {
return false;
}
}
if (this.forwardWays != null) {
for (int i = 0; i < this.forwardWays.size(); i++) {
if (!this.forwardWays.get(i).compareWay(thatObj.forwardWays.get(i))) {
return false;
}
}
}
return true;
} else {
return false;
}
}
}

View file

@ -20,4 +20,14 @@ public class TransportSchedule {
public int[] getAvgWaitIntervals() {
return avgWaitIntervals.toArray();
}
public boolean compareSchedule(TransportSchedule thatObj) {
if (this == thatObj) {
return true;
} else {
return tripIntervals.equals(thatObj.tripIntervals) &&
avgStopIntervals.equals(thatObj.avgStopIntervals) &&
avgWaitIntervals.equals(thatObj.avgWaitIntervals);
}
}
}

View file

@ -4,20 +4,20 @@ import net.osmand.util.MapUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TransportStop extends MapObject {
private static final int DELETED_STOP = -1;
private int[] referencesToRoutes = null;
private Amenity amenity;
public int distance;
public int x31;
public int y31;
private List<TransportStopExit> exits;
private HashMap<String,String> names;
public TransportStop(){
public TransportStop() {
}
public int[] getReferencesToRoutes() {
@ -28,6 +28,14 @@ public class TransportStop extends MapObject {
this.referencesToRoutes = referencesToRoutes;
}
public boolean isDeleted() {
return referencesToRoutes != null && referencesToRoutes.length == 1 && referencesToRoutes[0] == DELETED_STOP;
}
public void setDeleted() {
this.referencesToRoutes = new int[] { DELETED_STOP };
}
public Amenity getAmenity() {
return amenity;
}
@ -54,20 +62,20 @@ public class TransportStop extends MapObject {
exits.add(transportStopExit);
}
public List<TransportStopExit> getExits () {
public List<TransportStopExit> getExits() {
if (exits == null) {
return Collections.emptyList();
}
return this.exits;
}
public String getExitsString () {
public String getExitsString() {
String exitsString = "";
String refString = "";
if (this.exits != null) {
int i = 1;
exitsString = exitsString + " Exits: [";
for (TransportStopExit e : this.exits ) {
exitsString = exitsString + " Exits: [";
for (TransportStopExit e : this.exits) {
if (e.getRef() != null) {
refString = " [ref:" + e.getRef() + "] ";
}
@ -77,4 +85,23 @@ public class TransportStop extends MapObject {
}
return exitsString;
}
public boolean compareStop(TransportStop thatObj) {
if (this.compareObject(thatObj) &&
((this.referencesToRoutes == null && thatObj.referencesToRoutes == null) ||
(this.referencesToRoutes != null && thatObj.referencesToRoutes != null && this.referencesToRoutes.length == thatObj.referencesToRoutes.length)) &&
((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))) {
return false;
}
}
}
} else {
return false;
}
return true;
}
}

View file

@ -1,27 +1,36 @@
package net.osmand.data;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
public class TransportStopExit extends MapObject {
public int x31;
public int y31;
public String ref = null;
@Override
public void setLocation(double latitude, double longitude) {
super.setLocation(latitude, longitude);
}
public void setLocation(int zoom, int dx, int dy) {
x31 = dx << (31 - zoom);
y31 = dy << (31 - zoom);
setLocation(MapUtils.getLatitudeFromTile(zoom, dy), MapUtils.getLongitudeFromTile(zoom, dx));
}
public void setRef (String ref) {
public void setRef(String ref) {
this.ref = ref;
}
public String getRef() {
if (ref != null) {
return ref;
}
return "";
}
public boolean compareExit(TransportStopExit thatObj) {
return this.compareObject(thatObj) && Algorithms.objectEquals(this.ref, thatObj.ref);
}
}

View file

@ -328,4 +328,14 @@ public abstract class Entity implements Serializable {
return tags;
}
public boolean compareEntity(Entity thatObj) {
if (this == thatObj) {
return true;
} else {
return this.id == thatObj.id &&
Math.abs(latitude - thatObj.latitude) < 0.00001 &&
Math.abs(longitude - thatObj.longitude) < 0.00001 &&
Algorithms.objectEquals(this.tags, thatObj.tags);
}
}
}

View file

@ -1,6 +1,7 @@
package net.osmand.osm.edit;
import net.osmand.data.LatLon;
import net.osmand.util.Algorithms;
import java.io.Serializable;
import java.util.Map;
@ -38,4 +39,8 @@ public class Node extends Entity implements Serializable {
", tags=" + getTags() +
'}';
}
public boolean compareNode(Node thatObj) {
return this.compareEntity(thatObj);
}
}

View file

@ -1,14 +1,15 @@
package net.osmand.osm.edit;
import gnu.trove.list.array.TLongArrayList;
import net.osmand.data.LatLon;
import net.osmand.data.QuadRect;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import net.osmand.data.LatLon;
import net.osmand.data.QuadRect;
import gnu.trove.list.array.TLongArrayList;
public class Way extends Entity {
@ -196,4 +197,22 @@ public class Way extends Entity {
nodeIds.reverse();
}
}
public boolean compareWay(Way thatObj) {
if (this.compareEntity(thatObj) &&
Algorithms.objectEquals(this.nodeIds, thatObj.nodeIds) &&
((this.nodes == null && thatObj.nodes == null) || (this.nodes != null && thatObj.nodes != null && this.nodes.size() == thatObj.nodes.size()))) {
if (this.nodes != null) {
for (int i = 0; i < this.nodes.size(); i++) {
if (!this.nodes.get(i).compareNode(thatObj.nodes.get(i))) {
return false;
}
}
}
return true;
} else {
return false;
}
}
}

View file

@ -677,13 +677,24 @@ public class TransportRoutePlanner {
allPoints.clear();
allPointsLoad.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);
allPoints.addAll(s.getReferencesToRoutes());
if (!s.isDeleted()) {
allPoints.addAll(s.getReferencesToRoutes());
}
} else {
if (existingStops == null) {
existingStops = new ArrayList<>();
}
existingStops.add(s);
}
}
if (existingStops != null && existingStops.size() > 0) {
stops.removeAll(existingStops);
}
if(allPoints.size() > 0) {
allPoints.sort();
@ -713,6 +724,9 @@ public class TransportRoutePlanner {
private void loadTransportSegments(TIntObjectHashMap<TransportRoute> routes, BinaryMapIndexReader r,
List<TransportStop> stops, List<TransportRouteSegment> lst) throws IOException {
for(TransportStop s : stops) {
if (s.isDeleted()) {
continue;
}
for (int ref : s.getReferencesToRoutes()) {
TransportRoute route = routes.get(ref);
if (route != null) {
@ -736,7 +750,6 @@ public class TransportRoutePlanner {
} else {
System.err.println("Routing error: missing stop in route");
}
}
}
}

View file

@ -11,8 +11,8 @@
Thx - Hardy
-->
<string name="use_osm_live_public_transport_description">Enable public transport for OsmAnd Live changes.</string>
<string name="use_osm_live_public_transport">OsmAnd Live public transport</string>
<string name="time_of_day">Time of day</string>
<string name="by_transport_type">By %1$s</string>
<string name="step_by_step">Step by step</string>

View file

@ -2592,6 +2592,8 @@ public class OsmandSettings {
public final OsmandPreference<Boolean> USE_OSM_LIVE_FOR_ROUTING = new BooleanPreference("enable_osmc_routing", true).makeGlobal();
public final OsmandPreference<Boolean> USE_OSM_LIVE_FOR_PUBLIC_TRANSPORT = new BooleanPreference("enable_osmc_public_transport", true).makeGlobal();
public final OsmandPreference<Boolean> VOICE_MUTE = new BooleanPreference("voice_mute", false).makeGlobal();
// for background service

View file

@ -75,6 +75,10 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
R.string.use_osm_live_routing,
R.string.use_osm_live_routing_description));
navigation.addPreference(createCheckBoxPreference(settings.USE_OSM_LIVE_FOR_PUBLIC_TRANSPORT,
R.string.use_osm_live_public_transport,
R.string.use_osm_live_public_transport_description));
pref = new Preference(this);
final Preference simulate = pref;
final OsmAndLocationSimulation sim = getMyApplication().getLocationProvider().getLocationSimulation();

View file

@ -36,6 +36,9 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
import gnu.trove.list.array.TLongArrayList;
import gnu.trove.map.hash.TLongObjectHashMap;
public class AmenityMenuController extends MenuController {
private Amenity amenity;
@ -274,14 +277,20 @@ public class AmenityMenuController extends MenuController {
boolean useEnglishNames = app.getSettings().usingEnglishNames();
boolean isSubwayEntrance = amenity.getSubType().equals("subway_entrance");
TLongArrayList addedTransportStops = new TLongArrayList();
for (TransportIndexRepository t : reps) {
ArrayList<TransportStop> ls = new ArrayList<>();
QuadRect ll = MapUtils.calculateLatLonBbox(amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude(),
isSubwayEntrance ? 400 : 150);
t.searchTransportStops(ll.top, ll.left, ll.bottom, ll.right, -1, ls, null);
for (TransportStop tstop : ls) {
addRoutes(useEnglishNames, t, tstop,
(int) MapUtils.getDistance(tstop.getLocation(), amenity.getLocation()), isSubwayEntrance);
if (!addedTransportStops.contains(tstop.getId())) {
addedTransportStops.add(tstop.getId());
if (!tstop.isDeleted()) {
addRoutes(useEnglishNames, t, tstop,
(int) MapUtils.getDistance(tstop.getLocation(), amenity.getLocation()), isSubwayEntrance);
}
}
}
}
Collections.sort(routes, new Comparator<TransportStopRoute>() {

View file

@ -24,6 +24,8 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import gnu.trove.list.array.TLongArrayList;
public class TransportStopController extends MenuController {
public static final int SHOW_STOPS_RADIUS_METERS = 150;
@ -120,6 +122,7 @@ public class TransportStopController extends MenuController {
boolean useEnglishNames = mapActivity.getMyApplication().getSettings().usingEnglishNames();
TLongArrayList addedTransportStops = new TLongArrayList();
for (TransportIndexRepository t : reps) {
if (t.acceptTransportStop(transportStop)) {
boolean empty = transportStop.getReferencesToRoutes() == null || transportStop.getReferencesToRoutes().length == 0;
@ -130,9 +133,12 @@ public class TransportStopController extends MenuController {
QuadRect ll = MapUtils.calculateLatLonBbox(transportStop.getLocation().getLatitude(), transportStop.getLocation().getLongitude(), SHOW_STOPS_RADIUS_METERS);
t.searchTransportStops(ll.top, ll.left, ll.bottom, ll.right, -1, ls, null);
for (TransportStop tstop : ls) {
if (tstop.getId().longValue() != transportStop.getId().longValue() || empty) {
addRoutes(routes, useEnglishNames, t, tstop, transportStop,
(int) MapUtils.getDistance(tstop.getLocation(), transportStop.getLocation()));
if (!addedTransportStops.contains(tstop.getId())) {
addedTransportStops.add(tstop.getId());
if (!tstop.isDeleted() && (tstop.getId().longValue() != transportStop.getId().longValue() || empty)) {
addRoutes(routes, useEnglishNames, t, tstop, transportStop,
(int) MapUtils.getDistance(tstop.getLocation(), transportStop.getLocation()));
}
}
}
}

View file

@ -68,6 +68,8 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import gnu.trove.list.array.TLongArrayList;
import static net.osmand.plus.download.DownloadOsmandIndexesHelper.assetMapping;
/**
@ -117,6 +119,7 @@ public class ResourceManager {
private File filename;
private List<BinaryMapIndexReader> readers = new ArrayList<>(BinaryMapReaderResourceType.values().length);
private boolean useForRouting;
private boolean useForPublicTransport;
public BinaryMapReaderResource(File f, BinaryMapIndexReader initialReader) {
this.filename = f;
this.initialReader = initialReader;
@ -180,6 +183,14 @@ public class ResourceManager {
public boolean isUseForRouting() {
return useForRouting;
}
public boolean isUseForPublicTransport() {
return useForPublicTransport;
}
public void setUseForPublicTransport(boolean useForPublicTransport) {
this.useForPublicTransport = useForPublicTransport;
}
}
protected final Map<String, BinaryMapReaderResource> fileReaders = new ConcurrentHashMap<String, BinaryMapReaderResource>();
@ -709,6 +720,10 @@ public class ResourceManager {
context.getSettings().USE_OSM_LIVE_FOR_ROUTING.get())) {
resource.setUseForRouting(true);
}
if (mapReader.hasTransportData() && (!f.getParentFile().equals(liveDir) ||
context.getSettings().USE_OSM_LIVE_FOR_PUBLIC_TRANSPORT.get())) {
resource.setUseForPublicTransport(true);
}
if (mapReader.containsPoiData()) {
try {
RandomAccessFile raf = new RandomAccessFile(f, "r"); //$NON-NLS-1$
@ -922,7 +937,7 @@ public class ResourceManager {
public List<TransportIndexRepository> searchTransportRepositories(double latitude, double longitude) {
List<TransportIndexRepository> repos = new ArrayList<TransportIndexRepository>();
for (TransportIndexRepository index : transportRepositories.values()) {
if (index.checkContains(latitude,longitude)) {
if (index.checkContains(latitude,longitude) && index.isUseForPublicTransport()) {
repos.add(index);
}
}
@ -934,14 +949,24 @@ public class ResourceManager {
List<TransportIndexRepository> repos = new ArrayList<TransportIndexRepository>();
List<TransportStop> stops = new ArrayList<>();
for (TransportIndexRepository index : transportRepositories.values()) {
if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) {
if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude) && index.isUseForPublicTransport()) {
repos.add(index);
}
}
if(!repos.isEmpty()){
if (!repos.isEmpty()){
TLongArrayList addedTransportStops = new TLongArrayList();
for (TransportIndexRepository repository : repos) {
List<TransportStop> ls = new ArrayList<>();
repository.searchTransportStops(topLatitude, leftLongitude, bottomLatitude, rightLongitude,
-1, stops, matcher);
-1, ls, matcher);
for (TransportStop tstop : ls) {
if (!addedTransportStops.contains(tstop.getId())) {
addedTransportStops.add(tstop.getId());
if (!tstop.isDeleted()) {
stops.add(tstop);
}
}
}
}
}
return stops;
@ -1016,7 +1041,7 @@ public class ResourceManager {
public BinaryMapIndexReader[] getTransportRoutingMapFiles() {
List<BinaryMapIndexReader> readers = new ArrayList<>(fileReaders.size());
for(BinaryMapReaderResource r : fileReaders.values()) {
if(r.isUseForRouting()) {
if(r.isUseForPublicTransport()) {
BinaryMapIndexReader reader = r.getReader(BinaryMapReaderResourceType.TRANSPORT_ROUTING);
if (reader != null) {
readers.add(reader);

View file

@ -1,12 +1,11 @@
package net.osmand.plus.resources;
import java.util.Collection;
import java.util.List;
import net.osmand.ResultMatcher;
import net.osmand.data.TransportRoute;
import net.osmand.data.TransportStop;
import java.util.List;
public interface TransportIndexRepository {
public boolean checkContains(double latitude, double longitude);
@ -20,5 +19,5 @@ public interface TransportIndexRepository {
public List<TransportRoute> getRouteForStop(TransportStop stop);
public boolean isUseForPublicTransport();
}

View file

@ -89,5 +89,8 @@ public class TransportIndexRepositoryBinary implements TransportIndexRepository
return resource.getShallowReader().transportStopBelongsTo(stop);
}
@Override
public boolean isUseForPublicTransport() {
return resource.isUseForPublicTransport();
}
}

View file

@ -74,6 +74,7 @@ import java.util.Map.Entry;
import java.util.Set;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.list.array.TLongArrayList;
import static net.osmand.plus.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_CHANGE_MARKER_POSITION;
import static net.osmand.plus.mapcontextmenu.controllers.TransportStopController.SHOW_STOPS_RADIUS_METERS;
@ -906,11 +907,19 @@ public class ContextMenuLayer extends OsmandMapLayer {
List<TransportIndexRepository> reps =
activity.getMyApplication().getResourceManager().searchTransportRepositories(latitude, longitude);
TLongArrayList addedTransportStops = new TLongArrayList();
for (TransportIndexRepository t : reps) {
ArrayList<TransportStop> ls = new ArrayList<>();
QuadRect ll = MapUtils.calculateLatLonBbox(latitude, longitude, SHOW_STOPS_RADIUS_METERS);
t.searchTransportStops(ll.top, ll.left, ll.bottom, ll.right, -1, ls, null);
transportStops.addAll(ls);
for (TransportStop tstop : ls) {
if (!addedTransportStops.contains(tstop.getId())) {
addedTransportStops.add(tstop.getId());
if (!tstop.isDeleted()) {
transportStops.add(tstop);
}
}
}
}
return transportStops;
}