Update transport stops

This commit is contained in:
Victor Shcherb 2016-07-28 23:08:38 +02:00
parent 6076426d48
commit cd237d1184
7 changed files with 97 additions and 268 deletions

View file

@ -560,12 +560,6 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
mapLayers.getMapControlsLayer().startNavigation();
}
}
View progress = mapLayers.getMapInfoLayer().getProgressBar();
if (progress != null) {
app.getResourceManager().setBusyIndicator(new BusyIndicator(this, progress));
}
mapView.refreshMap(true);
if (atlasMapRendererView != null) {
atlasMapRendererView.handleOnResume();
@ -938,7 +932,6 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
settings.MAP_ACTIVITY_ENABLED.set(false);
getMyApplication().getAppCustomization().pauseActivity(MapActivity.class);
app.getResourceManager().interruptRendering();
app.getResourceManager().setBusyIndicator(null);
OsmandPlugin.onMapActivityPause(this);
}

View file

@ -5,26 +5,18 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import net.osmand.PlatformUtil;
import net.osmand.ResultMatcher;
import net.osmand.data.RotatedTileBox;
import net.osmand.data.TransportStop;
import net.osmand.map.ITileSource;
import net.osmand.map.MapTileDownloader.DownloadRequest;
import net.osmand.map.MapTileDownloader.IMapDownloaderCallback;
import net.osmand.plus.BusyIndicator;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import android.os.Handler;
import android.os.HandlerThread;
/**
* Thread to load map objects (POI, transport stops )async
*/
@ -34,75 +26,25 @@ public class AsyncLoadingThread extends Thread {
private static final Log log = PlatformUtil.getLog(AsyncLoadingThread.class);
private Handler asyncLoadingTransport;
Stack<Object> requests = new Stack<Object>();
TransportLoadRequest transportLoadRequest = null;
private final ResourceManager resourceManger;
public AsyncLoadingThread(ResourceManager resourceManger) {
super("Loader map objects (synchronizer)"); //$NON-NLS-1$
this.resourceManger = resourceManger;
}
private void startTransportLoadingThread() {
HandlerThread h = new HandlerThread("Loading transport");
h.start();
asyncLoadingTransport = new Handler(h.getLooper());
}
private int calculateProgressStatus() {
int progress = 0;
if (resourceManger.getMapTileDownloader() != null && resourceManger.getMapTileDownloader().isSomethingBeingDownloaded()) {
progress = BusyIndicator.STATUS_GREEN;
} else if (resourceManger.getContext().getRoutingHelper().isRouteBeingCalculated()) {
progress = BusyIndicator.STATUS_ORANGE;
} else if (resourceManger.isSearchAmenitiesInProgress()) {
progress = BusyIndicator.STATUS_BLACK;
} else if (!requests.isEmpty()) {
progress = BusyIndicator.STATUS_BLACK;
} else if (transportLoadRequest != null && transportLoadRequest.isRunning()) {
progress = BusyIndicator.STATUS_BLACK;
}
return progress;
}
@Override
public void run() {
while (true) {
try {
boolean tileLoaded = false;
boolean amenityLoaded = false;
boolean transportLoaded = false;
boolean mapLoaded = false;
int progress = calculateProgressStatus();
synchronized (resourceManger) {
if (resourceManger.getBusyIndicator() != null) {
resourceManger.getBusyIndicator().updateStatus(progress);
}
}
while (!requests.isEmpty()) {
Object req = requests.pop();
if (req instanceof TileLoadDownloadRequest) {
TileLoadDownloadRequest r = (TileLoadDownloadRequest) req;
tileLoaded |= resourceManger.getRequestedImageTile(r) != null;
} else if (req instanceof TransportLoadRequest) {
if (!transportLoaded) {
if (transportLoadRequest == null || asyncLoadingTransport == null) {
startTransportLoadingThread();
transportLoadRequest = (TransportLoadRequest) req;
asyncLoadingTransport.post(transportLoadRequest.prepareToRun());
} else if (transportLoadRequest.recalculateRequest((TransportLoadRequest) req)) {
transportLoadRequest = (TransportLoadRequest) req;
asyncLoadingTransport.post(transportLoadRequest.prepareToRun());
}
transportLoaded = true;
}
} else if (req instanceof MapLoadRequest) {
if (!mapLoaded) {
MapLoadRequest r = (MapLoadRequest) req;
@ -111,18 +53,10 @@ public class AsyncLoadingThread extends Thread {
}
}
}
if (tileLoaded || amenityLoaded || transportLoaded || mapLoaded) {
if (tileLoaded || mapLoaded) {
// use downloader callback
resourceManger.getMapTileDownloader().fireLoadCallback(null);
}
int newProgress = calculateProgressStatus();
if (progress != newProgress) {
synchronized (resourceManger) {
if (resourceManger.getBusyIndicator() != null) {
resourceManger.getBusyIndicator().updateStatus(newProgress);
}
}
}
sleep(750);
} catch (InterruptedException e) {
log.error(e, e);
@ -140,9 +74,6 @@ public class AsyncLoadingThread extends Thread {
requests.push(req);
}
public void requestToLoadTransport(TransportLoadRequest req) {
requests.push(req);
}
public boolean isFilePendingToDownload(File fileToSave) {
return resourceManger.getMapTileDownloader().isFilePendingToDownload(fileToSave);
@ -251,48 +182,6 @@ public class AsyncLoadingThread extends Thread {
}
protected class TransportLoadRequest extends MapObjectLoadRequest<TransportStop> {
private final List<TransportIndexRepository> repos;
private int zoom;
public TransportLoadRequest(List<TransportIndexRepository> repos, int zoom) {
super();
this.repos = repos;
this.zoom = zoom;
}
public Runnable prepareToRun() {
final double ntopLatitude = topLatitude + (topLatitude - bottomLatitude) / 2;
final double nbottomLatitude = bottomLatitude - (topLatitude - bottomLatitude) / 2;
final double nleftLongitude = leftLongitude - (rightLongitude - leftLongitude) / 2;
final double nrightLongitude = rightLongitude + (rightLongitude - leftLongitude) / 2;
setBoundaries(ntopLatitude, nleftLongitude, nbottomLatitude, nrightLongitude);
return new Runnable() {
@Override
public void run() {
start();
try {
for (TransportIndexRepository repository : repos) {
repository.evaluateCachedTransportStops(ntopLatitude, nleftLongitude, nbottomLatitude, nrightLongitude, zoom,
LIMIT_TRANSPORT, TransportLoadRequest.this);
}
} finally {
finish();
}
}
};
}
public boolean recalculateRequest(TransportLoadRequest req) {
if (this.zoom != req.zoom) {
return true;
}
return !isContains(req.topLatitude, req.leftLongitude, req.bottomLatitude, req.rightLongitude);
}
}
protected static class MapLoadRequest {
public final RotatedTileBox tileBox;

View file

@ -1,15 +1,20 @@
package net.osmand.plus.resources;
import android.content.Context;
import android.content.res.AssetManager;
import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.HandlerThread;
import android.text.format.DateFormat;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.osmand.AndroidUtils;
import net.osmand.GeoidAltitudeCorrection;
@ -32,7 +37,6 @@ import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiCategory;
import net.osmand.plus.AppInitializer;
import net.osmand.plus.AppInitializer.InitEvents;
import net.osmand.plus.BusyIndicator;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
@ -42,7 +46,6 @@ import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.plus.resources.AsyncLoadingThread.MapLoadRequest;
import net.osmand.plus.resources.AsyncLoadingThread.TileLoadDownloadRequest;
import net.osmand.plus.resources.AsyncLoadingThread.TransportLoadRequest;
import net.osmand.plus.srtmplugin.SRTMPlugin;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.util.Algorithms;
@ -53,20 +56,15 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import android.content.Context;
import android.content.res.AssetManager;
import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.HandlerThread;
import android.text.format.DateFormat;
import android.util.DisplayMetrics;
import android.view.WindowManager;
/**
* Resource manager is responsible to work with all resources
@ -98,8 +96,6 @@ public class ResourceManager {
private final OsmandApplication context;
private BusyIndicator busyIndicator;
public interface ResourceWatcher {
@ -916,20 +912,21 @@ public class ResourceManager {
}
public void searchTransportAsync(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, List<TransportStop> toFill){
public List<TransportStop> searchTransportSync(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, ResultMatcher<TransportStop> matcher){
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.checkCachedObjects(topLatitude, leftLongitude, bottomLatitude, rightLongitude, zoom, toFill, true)) {
repos.add(index);
}
repos.add(index);
}
}
if(!repos.isEmpty()){
TransportLoadRequest req = asyncLoadingThread.new TransportLoadRequest(repos, zoom);
req.setBoundaries(topLatitude, leftLongitude, bottomLatitude, rightLongitude);
asyncLoadingThread.requestToLoadTransport(req);
for (TransportIndexRepository repository : repos) {
repository.searchTransportStops(topLatitude, leftLongitude, bottomLatitude, rightLongitude,
-1, stops, matcher);
}
}
return stops;
}
////////////////////////////////////////////// Working with map ////////////////////////////////////////////////
@ -1002,13 +999,9 @@ public class ResourceManager {
transportRepositories.clear();
}
public BusyIndicator getBusyIndicator() {
return busyIndicator;
}
public synchronized void setBusyIndicator(BusyIndicator busyIndicator) {
this.busyIndicator = busyIndicator;
}
public synchronized void close(){
imagesOnFS.clear();

View file

@ -13,25 +13,13 @@ public interface TransportIndexRepository {
public boolean checkContains(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude);
public boolean checkCachedObjects(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, List<TransportStop> toFill);
public boolean checkCachedObjects(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, List<TransportStop> toFill, boolean fillFound);
public boolean acceptTransportStop(TransportStop stop);
/**
*
* @param stop
* @param format {0} - ref, {1} - type, {2} - name, {3} - name_en
* @return
*/
public void searchTransportStops(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude,
int limit, List<TransportStop> stops, ResultMatcher<TransportStop> matcher);
public List<String> getRouteDescriptionsForStop(TransportStop stop, String format);
public void evaluateCachedTransportStops(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, int limit,
ResultMatcher<TransportStop> matcher);
public List<RouteInfoLocation> searchTransportRouteStops(double latitude, double longitude, LatLon locationToGo, int zoom);
public void close();

View file

@ -24,12 +24,6 @@ public class TransportIndexRepositoryBinary implements TransportIndexRepository
private static final Log log = PlatformUtil.getLog(TransportIndexRepositoryBinary.class);
private final BinaryMapIndexReader file;
protected List<TransportStop> cachedObjects = new ArrayList<TransportStop>();
protected double cTopLatitude;
protected double cBottomLatitude;
protected double cLeftLongitude;
protected double cRightLongitude;
private int cZoom;
public TransportIndexRepositoryBinary(BinaryMapIndexReader file) {
this.file = file;
@ -45,28 +39,7 @@ public class TransportIndexRepositoryBinary implements TransportIndexRepository
}
@Override
public boolean checkCachedObjects(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, List<TransportStop> toFill){
return checkCachedObjects(topLatitude, leftLongitude, bottomLatitude, rightLongitude, zoom, toFill, false);
}
@Override
public synchronized boolean checkCachedObjects(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, List<TransportStop> toFill, boolean fillFound){
boolean inside = cTopLatitude >= topLatitude && cLeftLongitude <= leftLongitude && cRightLongitude >= rightLongitude
&& cBottomLatitude <= bottomLatitude && cZoom == zoom;
boolean noNeedToSearch = inside;
if((inside || fillFound) && toFill != null){
for(TransportStop a : cachedObjects){
LatLon location = a.getLocation();
if (location.getLatitude() <= topLatitude && location.getLongitude() >= leftLongitude && location.getLongitude() <= rightLongitude
&& location.getLatitude() >= bottomLatitude) {
toFill.add(a);
}
}
}
return noNeedToSearch;
}
public List<TransportStop> searchTransportStops(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude,
public void searchTransportStops(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude,
int limit, List<TransportStop> stops, ResultMatcher<TransportStop> matcher) {
long now = System.currentTimeMillis();
try {
@ -80,7 +53,6 @@ public class TransportIndexRepositoryBinary implements TransportIndexRepository
} catch (IOException e) {
log.error("Disk error ", e); //$NON-NLS-1$
}
return stops;
}
@ -115,23 +87,6 @@ public class TransportIndexRepositoryBinary implements TransportIndexRepository
return res;
}
@Override
public void evaluateCachedTransportStops(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude,
int zoom, int limit, ResultMatcher<TransportStop> matcher) {
cTopLatitude = topLatitude ;
cBottomLatitude = bottomLatitude ;
cLeftLongitude = leftLongitude ;
cRightLongitude = rightLongitude ;
cZoom = zoom;
// first of all put all entities in temp list in order to not freeze other read threads
ArrayList<TransportStop> tempList = new ArrayList<TransportStop>();
searchTransportStops(cTopLatitude, cLeftLongitude, cBottomLatitude, cRightLongitude, limit, tempList, matcher);
synchronized (this) {
cachedObjects.clear();
cachedObjects.addAll(tempList);
}
}
@Override

View file

@ -329,10 +329,6 @@ public class MapInfoLayer extends OsmandMapLayer {
return true;
}
public View getProgressBar() {
// currently no progress on info layer
return null;
}
public static String getStringPropertyName(Context ctx, String propertyName, String defValue) {
try {

View file

@ -8,6 +8,8 @@ import android.graphics.Paint;
import android.graphics.PointF;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import net.osmand.ResultMatcher;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.QuadRect;
@ -15,26 +17,26 @@ import net.osmand.data.QuadTree;
import net.osmand.data.RotatedTileBox;
import net.osmand.data.TransportStop;
import net.osmand.plus.R;
import net.osmand.plus.resources.TransportIndexRepository;
import net.osmand.plus.poi.PoiUIFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class TransportStopsLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider {
private static final int startZoom = 12;
private OsmandMapTileView view;
private List<TransportStop> objects = new ArrayList<>();
private Paint paintIcon;
private Bitmap stopBus;
private Bitmap stopTram;
private Bitmap stopSmall;
private MapLayerData<List<TransportStop>> data;
@SuppressWarnings("deprecation")
@Override
public void initLayer(OsmandMapTileView view) {
public void initLayer(final OsmandMapTileView view) {
this.view = view;
DisplayMetrics dm = new DisplayMetrics();
WindowManager wmgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
@ -42,12 +44,59 @@ public class TransportStopsLayer extends OsmandMapLayer implements ContextMenuLa
paintIcon = new Paint();
stopBus = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_transport_stop_bus);
stopTram = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_transport_stop_tram);
stopSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_transport_stop_small);
data = new OsmandMapLayer.MapLayerData<List<TransportStop>>() {
{
ZOOM_THRESHOLD = 0;
}
@Override
public boolean isInterrupted() {
return super.isInterrupted();
}
@Override
public void layerOnPostExecute() {
view.refreshMap();
}
@Override
protected List<TransportStop> calculateResult(RotatedTileBox tileBox) {
QuadRect latLonBounds = tileBox.getLatLonBounds();
if (latLonBounds == null) {
return new ArrayList<>();
}
int z = (int) Math.floor(tileBox.getZoom() + Math.log(view.getSettings().MAP_DENSITY.get()) / Math.log(2));
List<TransportStop> res = view.getApplication().getResourceManager().searchTransportSync(latLonBounds.top, latLonBounds.left,
latLonBounds.bottom, latLonBounds.right, new ResultMatcher<TransportStop>() {
@Override
public boolean publish(TransportStop object) {
return true;
}
@Override
public boolean isCancelled() {
return isInterrupted();
}
});
Collections.sort(res, new Comparator<TransportStop>() {
@Override
public int compare(TransportStop lhs, TransportStop rhs) {
return lhs.getId() < rhs.getId() ? -1 : (lhs.getId().longValue() == rhs.getId().longValue() ? 0 : 1);
}
});
return res;
}
};
}
public void getFromPoint(RotatedTileBox tb,PointF point, List<? super TransportStop> res) {
if (objects != null) {
if (data.getResults() != null) {
List<TransportStop> objects = data.getResults();
int ex = (int) point.x;
int ey = (int) point.y;
final int rp = getRadiusPoi(tb);
@ -72,35 +121,6 @@ public class TransportStopsLayer extends OsmandMapLayer implements ContextMenuLa
}
private String getStopDescription(TransportStop n, boolean useName) {
StringBuilder text = new StringBuilder(250);
text.append(view.getContext().getString(R.string.transport_Stop))
.append(" : ").append(n.getName(view.getSettings().MAP_PREFERRED_LOCALE.get())); //$NON-NLS-1$
text.append("\n").append(view.getContext().getString(R.string.transport_Routes)).append(" : "); //$NON-NLS-1$ //$NON-NLS-2$
List<TransportIndexRepository> reps = view.getApplication().getResourceManager().searchTransportRepositories(
n.getLocation().getLatitude(), n.getLocation().getLongitude());
for (TransportIndexRepository t : reps) {
if (t.acceptTransportStop(n)) {
List<String> l;
if (!useName) {
l = t.getRouteDescriptionsForStop(n, "{1} {0}"); //$NON-NLS-1$
} else if (view.getSettings().usingEnglishNames()) {
l = t.getRouteDescriptionsForStop(n, "{1} {0} - {3}"); //$NON-NLS-1$
} else {
l = t.getRouteDescriptionsForStop(n, "{1} {0} - {2}"); //$NON-NLS-1$
}
if (l != null) {
for (String s : l) {
text.append("\n").append(s); //$NON-NLS-1$
}
}
}
}
return text.toString();
}
public int getRadiusPoi(RotatedTileBox tb){
final double zoom = tb.getZoom();
@ -124,16 +144,11 @@ public class TransportStopsLayer extends OsmandMapLayer implements ContextMenuLa
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox,
DrawSettings settings) {
if (tileBox.getZoom() >= startZoom) {
objects.clear();
data.queryNewData(tileBox);;
float iconSize = stopBus.getWidth() * 3 / 2.5f;
QuadTree<QuadRect> boundIntersections = initBoundIntersections(tileBox);
final QuadRect latLonBounds = tileBox.getLatLonBounds();
view.getApplication().getResourceManager().searchTransportAsync(latLonBounds.top, latLonBounds.left,
latLonBounds.bottom, latLonBounds.right, tileBox.getZoom(), objects);
List<TransportStop> fullObjects = new ArrayList<>();
for (TransportStop o : objects) {
for (TransportStop o : data.getResults()) {
float x = tileBox.getPixXFromLatLon(o.getLocation().getLatitude(), o.getLocation().getLongitude());
float y = tileBox.getPixYFromLatLon(o.getLocation().getLatitude(), o.getLocation().getLongitude());