add transport indexes

git-svn-id: https://osmand.googlecode.com/svn/trunk@272 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-07-01 21:52:20 +00:00
parent b9e7499f63
commit 0fc3d6b70a
13 changed files with 566 additions and 113 deletions

View file

@ -23,8 +23,9 @@ public class DownloaderIndexFromGoogleCode {
*/ */
public static void main(String[] args) throws URISyntaxException, IOException { public static void main(String[] args) throws URISyntaxException, IOException {
Map<String, String> indexFiles = DownloaderIndexFromGoogleCode.getIndexFiles(new String[] { IndexConstants.ADDRESS_INDEX_EXT, Map<String, String> indexFiles = DownloaderIndexFromGoogleCode.getIndexFiles(new String[] { IndexConstants.ADDRESS_INDEX_EXT,
IndexConstants.POI_INDEX_EXT }, new String[] { IndexConstants.POI_INDEX_EXT, IndexConstants.TRANSPORT_INDEX_EXT }, new String[] {
IndexConstants.ADDRESS_TABLE_VERSION + "", IndexConstants.POI_TABLE_VERSION + "" }); //$NON-NLS-1$//$NON-NLS-2$ IndexConstants.ADDRESS_TABLE_VERSION + "", IndexConstants.POI_TABLE_VERSION + "", //$NON-NLS-1$//$NON-NLS-2$
IndexConstants.TRANSPORT_TABLE_VERSION + "" }); //$NON-NLS-1$
System.out.println(indexFiles); System.out.println(indexFiles);
} }

View file

@ -290,7 +290,7 @@ public class IndexConstants {
// Transport Index // Transport Index
public enum IndexTransportStop implements IndexColumn { public enum IndexTransportStop implements IndexColumn {
ID("long"), LATITUDE("double", true), LONGITUDE("double", true), NAME, NAME_EN; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ ID("long"), LATITUDE("double", true), LONGITUDE("double", true), NAME, NAME_EN; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
boolean index = false; boolean index = false;
String type = null; String type = null;
@ -327,7 +327,7 @@ public class IndexConstants {
public enum IndexTransportRouteStop implements IndexColumn { public enum IndexTransportRouteStop implements IndexColumn {
STOP("long"), ROUTE("long", true), DIRECTION("boolean"); //$NON-NLS-1$ //$NON-NLS-2$ STOP("long"), ROUTE("long", true), DIRECTION("boolean"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
boolean index = false; boolean index = false;
String type = null; String type = null;

View file

@ -29,6 +29,8 @@ indexing_address = Indexing address
indexing_poi = Indexing POI indexing_poi = Indexing POI
indexing_transport = Indexing transport
km = km km = km
km_h = km/h km_h = km/h

View file

@ -29,6 +29,8 @@ indexing_address = \u0418\u043D\u0434\u0435\u043A\u0441\u0438\u0440\u0443\u0435\
indexing_poi = \u0418\u043D\u0434\u0435\u043A\u0441\u0438\u0440\u0443\u044E\u0442\u0441\u044F POI indexing_poi = \u0418\u043D\u0434\u0435\u043A\u0441\u0438\u0440\u0443\u044E\u0442\u0441\u044F POI
indexing_transport = \u0418\u043D\u0434\u0435\u043A\u0441\u0438\u0440\u0443\u0435\u0442\u0441\u044F \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442
km = \u043A\u043C km = \u043A\u043C
km_h = \u043A\u043C/\u0447 km_h = \u043A\u043C/\u0447

View file

@ -11,7 +11,6 @@ import org.apache.commons.logging.Log;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement; import android.database.sqlite.SQLiteStatement;
import com.osmand.data.Amenity; import com.osmand.data.Amenity;
@ -24,30 +23,15 @@ import com.osmand.osm.Node;
import com.osmand.osm.io.IOsmStorageFilter; import com.osmand.osm.io.IOsmStorageFilter;
import com.osmand.osm.io.OsmBaseStorage; import com.osmand.osm.io.OsmBaseStorage;
public class AmenityIndexRepository { public class AmenityIndexRepository extends BaseLocationIndexRepository<Amenity> {
private static final Log log = LogUtil.getLog(AmenityIndexRepository.class); private static final Log log = LogUtil.getLog(AmenityIndexRepository.class);
public final static int LIMIT_AMENITIES = 500; public final static int LIMIT_AMENITIES = 500;
private SQLiteDatabase db;
private double dataTopLatitude;
private double dataBottomLatitude;
private double dataLeftLongitude;
private double dataRightLongitude;
private String name;
// cache amenities // cache amenities
private List<Amenity> cachedAmenities = new ArrayList<Amenity>();
private double cTopLatitude;
private double cBottomLatitude;
private double cLeftLongitude;
private double cRightLongitude;
private int cZoom;
private String cFilterId; private String cFilterId;
private final String[] columns = IndexConstants.generateColumnNames(IndexPoiTable.values()); private final String[] columns = IndexConstants.generateColumnNames(IndexPoiTable.values());
public List<Amenity> searchAmenities(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int limit, PoiFilter filter, List<Amenity> amenities){ public List<Amenity> searchAmenities(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int limit, PoiFilter filter, List<Amenity> amenities){
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@ -122,13 +106,8 @@ public class AmenityIndexRepository {
public synchronized void clearCache(){ public synchronized void clearCache(){
cachedAmenities.clear(); super.clearCache();
cTopLatitude = 0;
cBottomLatitude = 0;
cRightLongitude = 0;
cLeftLongitude = 0;
cFilterId = null; cFilterId = null;
cZoom = 0;
} }
public void evaluateCachedAmenities(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, int limit, PoiFilter filter, List<Amenity> toFill){ public void evaluateCachedAmenities(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, int limit, PoiFilter filter, List<Amenity> toFill){
@ -142,8 +121,8 @@ public class AmenityIndexRepository {
ArrayList<Amenity> tempList = new ArrayList<Amenity>(); ArrayList<Amenity> tempList = new ArrayList<Amenity>();
searchAmenities(cTopLatitude, cLeftLongitude, cBottomLatitude, cRightLongitude, limit, filter, tempList); searchAmenities(cTopLatitude, cLeftLongitude, cBottomLatitude, cRightLongitude, limit, filter, tempList);
synchronized (this) { synchronized (this) {
cachedAmenities.clear(); cachedObjects.clear();
cachedAmenities.addAll(tempList); cachedObjects.addAll(tempList);
} }
checkCachedAmenities(topLatitude, leftLongitude, bottomLatitude, rightLongitude, cZoom, filter.getFilterId(), toFill); checkCachedAmenities(topLatitude, leftLongitude, bottomLatitude, rightLongitude, cZoom, filter.getFilterId(), toFill);
@ -157,7 +136,7 @@ public class AmenityIndexRepository {
&& cBottomLatitude <= bottomLatitude && zoom == cZoom; && cBottomLatitude <= bottomLatitude && zoom == cZoom;
boolean noNeedToSearch = inside && Algoritms.objectEquals(filterId, cFilterId); boolean noNeedToSearch = inside && Algoritms.objectEquals(filterId, cFilterId);
if((inside || fillFound) && toFill != null && Algoritms.objectEquals(filterId, cFilterId)){ if((inside || fillFound) && toFill != null && Algoritms.objectEquals(filterId, cFilterId)){
for(Amenity a : cachedAmenities){ for(Amenity a : cachedObjects){
LatLon location = a.getLocation(); LatLon location = a.getLocation();
if (location.getLatitude() <= topLatitude && location.getLongitude() >= leftLongitude && location.getLongitude() <= rightLongitude if (location.getLatitude() <= topLatitude && location.getLongitude() >= leftLongitude && location.getLongitude() <= rightLongitude
&& location.getLatitude() >= bottomLatitude) { && location.getLatitude() >= bottomLatitude) {
@ -172,53 +151,10 @@ public class AmenityIndexRepository {
} }
public boolean initialize(final IProgress progress, File file) { public boolean initialize(final IProgress progress, File file) {
long start = System.currentTimeMillis(); return super.initialize(progress, file, IndexConstants.POI_TABLE_VERSION, IndexPoiTable.getTable());
if(db != null){
// close previous db
db.close();
}
db = SQLiteDatabase.openOrCreateDatabase(file, null);
name = file.getName().substring(0, file.getName().indexOf('.'));
if(db.getVersion() != IndexConstants.POI_TABLE_VERSION){
db.close();
db = null;
return false;
} }
Cursor query = db.query(IndexPoiTable.getTable(), new String[]{"MAX(latitude)", "MAX(longitude)", "MIN(latitude)", "MIN(longitude)"}, null, null,null, null, null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
if(query.moveToFirst()){
dataTopLatitude = query.getDouble(0);
dataRightLongitude = query.getDouble(1);
dataBottomLatitude = query.getDouble(2);
dataLeftLongitude = query.getDouble(3);
}
query.close();
if (log.isDebugEnabled()) {
log.debug("Initializing db " + file.getAbsolutePath() + " " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return true;
}
public synchronized void close(){
if(db != null){
db.close();
dataRightLongitude = dataLeftLongitude = dataBottomLatitude= dataTopLatitude = 0;
cachedAmenities.clear();
cTopLatitude = cBottomLatitude = cLeftLongitude = cRightLongitude = 0;
}
}
public String getName() {
return name;
}
private void bindString(SQLiteStatement s, int i, String v){
if(v == null){
s.bindNull(i);
} else {
s.bindString(i, v);
}
}
public boolean updateAmenities(List<Amenity> amenities, double leftLon, double topLat, double rightLon, double bottomLat){ public boolean updateAmenities(List<Amenity> amenities, double leftLon, double topLat, double rightLon, double bottomLat){
String latCol = IndexPoiTable.LATITUDE.name(); String latCol = IndexPoiTable.LATITUDE.name();
@ -243,24 +179,6 @@ public class AmenityIndexRepository {
return true; return true;
} }
public boolean checkContains(double latitude, double longitude){
if(latitude < dataTopLatitude && latitude > dataBottomLatitude && longitude > dataLeftLongitude && longitude < dataRightLongitude){
return true;
}
return false;
}
public boolean checkContains(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude){
if(rightLongitude < dataLeftLongitude || leftLongitude > dataRightLongitude){
return false;
}
if(topLatitude < dataBottomLatitude || bottomLatitude > dataTopLatitude){
return false;
}
return true;
}
private final static String SITE_API = "http://api.openstreetmap.org/"; //$NON-NLS-1$ private final static String SITE_API = "http://api.openstreetmap.org/"; //$NON-NLS-1$
public static boolean loadingPOIs(List<Amenity> amenities, double leftLon, double topLat, double righLon, double bottomLat) { public static boolean loadingPOIs(List<Amenity> amenities, double leftLon, double topLat, double righLon, double bottomLat) {

View file

@ -0,0 +1,133 @@
package com.osmand;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import com.osmand.data.MapObject;
import com.osmand.osm.LatLon;
public class BaseLocationIndexRepository<T extends MapObject> {
private static final Log log = LogUtil.getLog(BaseLocationIndexRepository.class);
protected SQLiteDatabase db;
protected double dataTopLatitude;
protected double dataBottomLatitude;
protected double dataLeftLongitude;
protected double dataRightLongitude;
protected String name;
protected List<T> cachedObjects = new ArrayList<T>();
protected double cTopLatitude;
protected double cBottomLatitude;
protected double cLeftLongitude;
protected double cRightLongitude;
protected int cZoom;
public synchronized void clearCache(){
cachedObjects.clear();
cTopLatitude = 0;
cBottomLatitude = 0;
cRightLongitude = 0;
cLeftLongitude = 0;
cZoom = 0;
}
public boolean initialize(final IProgress progress, File file, int version, String tableLocation) {
long start = System.currentTimeMillis();
if(db != null){
// close previous db
db.close();
}
db = SQLiteDatabase.openOrCreateDatabase(file, null);
name = file.getName().substring(0, file.getName().indexOf('.'));
if(db.getVersion() != version){
db.close();
db = null;
return false;
}
Cursor query = db.query(tableLocation, new String[]{"MAX(latitude)", "MAX(longitude)", "MIN(latitude)", "MIN(longitude)"}, null, null,null, null, null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
if(query.moveToFirst()){
dataTopLatitude = query.getDouble(0);
dataRightLongitude = query.getDouble(1);
dataBottomLatitude = query.getDouble(2);
dataLeftLongitude = query.getDouble(3);
}
query.close();
if (log.isDebugEnabled()) {
log.debug("Initializing db " + file.getAbsolutePath() + " " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return true;
}
public synchronized void close() {
if (db != null) {
db.close();
dataRightLongitude = dataLeftLongitude = dataBottomLatitude = dataTopLatitude = 0;
clearCache();
db = null;
}
}
public String getName() {
return name;
}
protected void bindString(SQLiteStatement s, int i, String v){
if(v == null){
s.bindNull(i);
} else {
s.bindString(i, v);
}
}
public boolean checkCachedObjects(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, List<T> toFill){
return checkCachedObjects(topLatitude, leftLongitude, bottomLatitude, rightLongitude, zoom, toFill, false);
}
public synchronized boolean checkCachedObjects(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, List<T> toFill, boolean fillFound){
if (db == null) {
return true;
}
boolean inside = cTopLatitude >= topLatitude && cLeftLongitude <= leftLongitude && cRightLongitude >= rightLongitude
&& cBottomLatitude <= bottomLatitude && cZoom == zoom;
boolean noNeedToSearch = inside;
if((inside || fillFound) && toFill != null){
for(T 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 boolean checkContains(double latitude, double longitude){
if(latitude < dataTopLatitude && latitude > dataBottomLatitude && longitude > dataLeftLongitude && longitude < dataRightLongitude){
return true;
}
return false;
}
public boolean checkContains(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude){
if(rightLongitude < dataLeftLongitude || leftLongitude > dataRightLongitude){
return false;
}
if(topLatitude < dataBottomLatitude || bottomLatitude > dataTopLatitude){
return false;
}
return true;
}
}

View file

@ -18,6 +18,7 @@ import android.graphics.BitmapFactory;
import android.os.Environment; import android.os.Environment;
import com.osmand.data.Amenity; import com.osmand.data.Amenity;
import com.osmand.data.TransportStop;
import com.osmand.data.index.IndexConstants; import com.osmand.data.index.IndexConstants;
import com.osmand.data.preparation.MapTileDownloader; import com.osmand.data.preparation.MapTileDownloader;
import com.osmand.data.preparation.MapTileDownloader.DownloadRequest; import com.osmand.data.preparation.MapTileDownloader.DownloadRequest;
@ -36,9 +37,13 @@ import com.osmand.views.POIMapLayer;
*/ */
public class ResourceManager { public class ResourceManager {
public static final String POI_PATH = "osmand/" + IndexConstants.POI_INDEX_DIR; //$NON-NLS-1$ public static final String APP_DIR = "osmand/"; //$NON-NLS-1$
public static final String ADDRESS_PATH = "osmand/" + IndexConstants.ADDRESS_INDEX_DIR; //$NON-NLS-1$ public static final String POI_PATH = APP_DIR + IndexConstants.POI_INDEX_DIR;
public static final String TILES_PATH = "osmand/tiles/"; //$NON-NLS-1$ public static final String ADDRESS_PATH = APP_DIR + IndexConstants.ADDRESS_INDEX_DIR;
public static final String TRANSPORT_PATH = APP_DIR + IndexConstants.TRANSPORT_INDEX_DIR;
public static final String TILES_PATH = APP_DIR+"tiles/"; //$NON-NLS-1$
public static final int LIMIT_TRANSPORT = 200;
private static final Log log = LogUtil.getLog(ResourceManager.class); private static final Log log = LogUtil.getLog(ResourceManager.class);
@ -66,6 +71,8 @@ public class ResourceManager {
protected Map<String, AmenityIndexRepository> amenityRepositories = new LinkedHashMap<String, AmenityIndexRepository>(); protected Map<String, AmenityIndexRepository> amenityRepositories = new LinkedHashMap<String, AmenityIndexRepository>();
protected Map<String, TransportIndexRepository> transportRepositories = new LinkedHashMap<String, TransportIndexRepository>();
public AsyncLoadingThread asyncLoadingTiles = new AsyncLoadingThread(); public AsyncLoadingThread asyncLoadingTiles = new AsyncLoadingThread();
@ -230,6 +237,7 @@ public class ResourceManager {
List<String> warnings = new ArrayList<String>(); List<String> warnings = new ArrayList<String>();
warnings.addAll(indexingPoi(progress)); warnings.addAll(indexingPoi(progress));
warnings.addAll(indexingAddresses(progress)); warnings.addAll(indexingAddresses(progress));
warnings.addAll(indexingTransport(progress));
return warnings; return warnings;
} }
@ -286,8 +294,34 @@ public class ResourceManager {
} }
} }
// //////////////////////////////////////////// Working with amenities ////////////////////////////////////////////////
public List<AmenityIndexRepository> searchRepositories(double latitude, double longitude) { public List<String> indexingTransport(final IProgress progress){
File file = new File(Environment.getExternalStorageDirectory(), TRANSPORT_PATH);
List<String> warnings = new ArrayList<String>();
closeTransport();
if (file.exists() && file.canRead()) {
for (File f : file.listFiles()) {
indexingTransport(progress, warnings, f);
}
}
return warnings;
}
public void indexingTransport(final IProgress progress, List<String> warnings, File f) {
if (f.getName().endsWith(IndexConstants.TRANSPORT_INDEX_EXT)) {
TransportIndexRepository repository = new TransportIndexRepository();
progress.startTask(Messages.getMessage("indexing_transport") + f.getName(), -1); //$NON-NLS-1$
boolean initialized = repository.initialize(progress, f);
if (initialized) {
transportRepositories.put(repository.getName(), repository);
} else {
warnings.add(MessageFormat.format(Messages.getMessage("version_index_is_not_supported"), f.getName())); //$NON-NLS-1$
}
}
}
////////////////////////////////////////////// Working with amenities ////////////////////////////////////////////////
public List<AmenityIndexRepository> searchAmenityRepositories(double latitude, double longitude) {
List<AmenityIndexRepository> repos = new ArrayList<AmenityIndexRepository>(); List<AmenityIndexRepository> repos = new ArrayList<AmenityIndexRepository>();
for (AmenityIndexRepository index : amenityRepositories.values()) { for (AmenityIndexRepository index : amenityRepositories.values()) {
if (index.checkContains(latitude,longitude)) { if (index.checkContains(latitude,longitude)) {
@ -338,6 +372,47 @@ public class ResourceManager {
return addressMap.values(); return addressMap.values();
} }
////////////////////////////////////////////// Working with transport ////////////////////////////////////////////////
public List<TransportIndexRepository> searchTransportRepositories(double latitude, double longitude) {
List<TransportIndexRepository> repos = new ArrayList<TransportIndexRepository>();
for (TransportIndexRepository index : transportRepositories.values()) {
if (index.checkContains(latitude,longitude)) {
repos.add(index);
}
}
return repos;
}
public List<TransportStop> searchTransportStops(double latitude, double longitude, int zoom, int limit) {
double tileNumberX = MapUtils.getTileNumberX(zoom, longitude);
double tileNumberY = MapUtils.getTileNumberY(zoom, latitude);
double topLatitude = MapUtils.getLatitudeFromTile(zoom, tileNumberY - 0.5);
double bottomLatitude = MapUtils.getLatitudeFromTile(zoom, tileNumberY + 0.5);
double leftLongitude = MapUtils.getLongitudeFromTile(zoom, tileNumberX - 0.5);
double rightLongitude = MapUtils.getLongitudeFromTile(zoom, tileNumberX + 0.5);
List<TransportStop> stops = new ArrayList<TransportStop>();
for (TransportIndexRepository index : transportRepositories.values()) {
if (index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)) {
if (!index.checkCachedObjects(topLatitude, leftLongitude, bottomLatitude, rightLongitude, zoom, stops)) {
index.searchTransportStops(topLatitude, leftLongitude, bottomLatitude, rightLongitude, limit, stops);
}
}
}
return stops;
}
public void searchTransportAsync(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, List<TransportStop> toFill){
for(TransportIndexRepository index : transportRepositories.values()){
if(index.checkContains(topLatitude, leftLongitude, bottomLatitude, rightLongitude)){
if(!index.checkCachedObjects(topLatitude, leftLongitude, bottomLatitude, rightLongitude, zoom, toFill, true)){
asyncLoadingTiles.requestToLoadTransport(
new TransportLoadRequest(index, topLatitude, leftLongitude, bottomLatitude, rightLongitude, zoom));
}
}
}
}
////////////////////////////////////////////// Closing methods //////////////////////////////////////////////// ////////////////////////////////////////////// Closing methods ////////////////////////////////////////////////
public void closeAmenities(){ public void closeAmenities(){
@ -354,10 +429,18 @@ public class ResourceManager {
addressMap.clear(); addressMap.clear();
} }
public void closeTransport(){
for(TransportIndexRepository r : transportRepositories.values()){
r.close();
}
transportRepositories.clear();
}
public synchronized void close(){ public synchronized void close(){
imagesOnFS.clear(); imagesOnFS.clear();
closeAmenities(); closeAmenities();
closeAddresses(); closeAddresses();
closeTransport();
} }
/// On low memory method /// /// On low memory method ///
@ -423,11 +506,27 @@ public class ResourceManager {
this.zoom = zoom; this.zoom = zoom;
this.filter = filter; this.filter = filter;
} }
} }
private static class TransportLoadRequest {
public final TransportIndexRepository repository;
public final double topLatitude;
public final double bottomLatitude;
public final double leftLongitude;
public final double rightLongitude;
public final int zoom;
public TransportLoadRequest(TransportIndexRepository repository, double topLatitude, double leftLongitude,
double bottomLatitude, double rightLongitude, int zoom) {
super();
this.bottomLatitude = bottomLatitude;
this.leftLongitude = leftLongitude;
this.repository = repository;
this.rightLongitude = rightLongitude;
this.topLatitude = topLatitude;
this.zoom = zoom;
}
}
public class AsyncLoadingThread extends Thread { public class AsyncLoadingThread extends Thread {
Stack<Object> requests = new Stack<Object>(); Stack<Object> requests = new Stack<Object>();
@ -442,6 +541,7 @@ public class ResourceManager {
try { try {
boolean update = false; boolean update = false;
boolean amenityLoaded = false; boolean amenityLoaded = false;
boolean transportLoaded = false;
while(!requests.isEmpty()){ while(!requests.isEmpty()){
Object req = requests.pop(); Object req = requests.pop();
if (req instanceof TileLoadDownloadRequest) { if (req instanceof TileLoadDownloadRequest) {
@ -456,9 +556,16 @@ public class ResourceManager {
r.bottomLatitude, r.rightLongitude, r.zoom, POIMapLayer.LIMIT_POI, r.filter, null); r.bottomLatitude, r.rightLongitude, r.zoom, POIMapLayer.LIMIT_POI, r.filter, null);
amenityLoaded = true; amenityLoaded = true;
} }
} else if(req instanceof TransportLoadRequest){
if(!transportLoaded){
TransportLoadRequest r = (TransportLoadRequest) req;
r.repository.evaluateCachedTransportStops(r.topLatitude, r.leftLongitude,
r.bottomLatitude, r.rightLongitude, r.zoom, LIMIT_TRANSPORT, null);
transportLoaded = true;
} }
} }
if(update || amenityLoaded){ }
if(update || amenityLoaded || transportLoaded){
// use downloader callback // use downloader callback
for(IMapDownloaderCallback c : downloader.getDownloaderCallbacks()){ for(IMapDownloaderCallback c : downloader.getDownloaderCallbacks()){
c.tileDownloaded(null); c.tileDownloaded(null);
@ -479,5 +586,9 @@ public class ResourceManager {
public void requestToLoadAmenities(AmenityLoadRequest req){ public void requestToLoadAmenities(AmenityLoadRequest req){
requests.push(req); requests.push(req);
} }
public void requestToLoadTransport(TransportLoadRequest req){
requests.push(req);
}
}; };
} }

View file

@ -0,0 +1,117 @@
package com.osmand;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import android.database.Cursor;
import com.osmand.data.TransportStop;
import com.osmand.data.index.IndexConstants;
import com.osmand.data.index.IndexConstants.IndexTransportRoute;
import com.osmand.data.index.IndexConstants.IndexTransportRouteStop;
import com.osmand.data.index.IndexConstants.IndexTransportStop;
public class TransportIndexRepository extends BaseLocationIndexRepository<TransportStop> {
private static final Log log = LogUtil.getLog(TransportIndexRepository.class);
public boolean initialize(final IProgress progress, File file) {
return super.initialize(progress, file, IndexConstants.TRANSPORT_TABLE_VERSION, IndexTransportStop.getTable());
}
private final String[] columns = IndexConstants.generateColumnNames(IndexTransportStop.values());
public List<TransportStop> searchTransportStops(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int limit, List<TransportStop> stops){
long now = System.currentTimeMillis();
String squery = "? < latitude AND latitude < ? AND ? < longitude AND longitude < ?"; //$NON-NLS-1$
if(limit != -1){
squery += " ORDER BY RANDOM() LIMIT " +limit; //$NON-NLS-1$
}
Cursor query = db.query(IndexTransportStop.getTable(), columns, squery,
new String[]{Double.toString(bottomLatitude),
Double.toString(topLatitude), Double.toString(leftLongitude), Double.toString(rightLongitude)}, null, null, null);
if(query.moveToFirst()){
do {
TransportStop st = new TransportStop();
st.setId(query.getLong(IndexTransportStop.ID.ordinal()));
st.setLocation(query.getDouble(IndexTransportStop.LATITUDE.ordinal()),
query.getDouble(IndexTransportStop.LONGITUDE.ordinal()));
st.setName(query.getString(IndexTransportStop.NAME.ordinal() ));
st.setEnName(query.getString(IndexTransportStop.NAME_EN.ordinal()));
stops.add(st);
if(limit != -1 && stops.size() >= limit){
break;
}
} while(query.moveToNext());
}
query.close();
if (log.isDebugEnabled()) {
log.debug(String.format("Search for %s done in %s ms found %s.", //$NON-NLS-1$
topLatitude + " " + leftLongitude, System.currentTimeMillis() - now, stops.size())); //$NON-NLS-1$
}
return stops;
}
private static String cacheSQLRouteDescriptions = null;
/**
*
* @param stop
* @param format {0} - ref, {1} - type, {2} - name, {3} - name_en
* @return
*/
public List<String> getRouteDescriptionsForStop(TransportStop stop, String format) {
long now = System.currentTimeMillis();
List<String> res = new ArrayList<String>();
MessageFormat f = new MessageFormat(format);
if (cacheSQLRouteDescriptions == null) {
StringBuilder sql = new StringBuilder(200);
sql.append("SELECT ").append(IndexTransportRoute.REF).append(",").append(IndexTransportRoute.TYPE) //$NON-NLS-1$//$NON-NLS-2$
.append(",").append(IndexTransportRoute.NAME).append(",").append(IndexTransportRoute.NAME_EN); //$NON-NLS-1$ //$NON-NLS-2$
sql.append(" FROM ").append(IndexTransportRoute.getTable()).append(" JOIN ").append(IndexTransportRouteStop.getTable()); //$NON-NLS-1$ //$NON-NLS-2$
sql.append(" ON ").append(IndexTransportRoute.getTable()).append(".").append(IndexTransportRoute.ID).append(" = "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
sql.append(IndexTransportRouteStop.getTable()).append(".").append(IndexTransportRouteStop.ROUTE); //$NON-NLS-1$
sql.append(" WHERE ").append(IndexTransportRouteStop.STOP).append(" = ?"); //$NON-NLS-1$ //$NON-NLS-2$
cacheSQLRouteDescriptions = sql.toString();
}
Cursor query = db.rawQuery(cacheSQLRouteDescriptions, new String[] { stop.getId() + "" }); //$NON-NLS-1$
if (query.moveToFirst()) {
do {
res.add(f.format(new String[] { query.getString(0), query.getString(1), query.getString(2), query.getString(3) }));
} while (query.moveToNext());
}
query.close();
if (log.isDebugEnabled()) {
log.debug(String.format("Search for stop %s done in %s ms found %s.", //$NON-NLS-1$
stop.getId() + "", System.currentTimeMillis() - now, res.size())); //$NON-NLS-1$
}
return res;
}
public void evaluateCachedTransportStops(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, int limit, List<TransportStop> toFill){
cTopLatitude = topLatitude + (topLatitude -bottomLatitude);
cBottomLatitude = bottomLatitude - (topLatitude -bottomLatitude);
cLeftLongitude = leftLongitude - (rightLongitude - leftLongitude);
cRightLongitude = rightLongitude + (rightLongitude - leftLongitude);
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);
synchronized (this) {
cachedObjects.clear();
cachedObjects.addAll(tempList);
}
checkCachedObjects(topLatitude, leftLongitude, bottomLatitude, rightLongitude, cZoom, toFill);
}
}

View file

@ -73,8 +73,9 @@ public class DownloadIndexActivity extends ListActivity {
try { try {
log.debug("Start loading list of index files"); //$NON-NLS-1$ log.debug("Start loading list of index files"); //$NON-NLS-1$
Map<String, String> indexFiles = DownloaderIndexFromGoogleCode.getIndexFiles(new String[] { IndexConstants.ADDRESS_INDEX_EXT, Map<String, String> indexFiles = DownloaderIndexFromGoogleCode.getIndexFiles(new String[] { IndexConstants.ADDRESS_INDEX_EXT,
IndexConstants.POI_INDEX_EXT }, new String[] { IndexConstants.POI_INDEX_EXT, IndexConstants.TRANSPORT_INDEX_EXT, }, new String[] {
IndexConstants.ADDRESS_TABLE_VERSION + "", IndexConstants.POI_TABLE_VERSION + "" }); //$NON-NLS-1$//$NON-NLS-2$ IndexConstants.ADDRESS_TABLE_VERSION + "", IndexConstants.POI_TABLE_VERSION + "",//$NON-NLS-1$//$NON-NLS-2$
IndexConstants.TRANSPORT_TABLE_VERSION + "",}); //$NON-NLS-1$
if (indexFiles != null && !indexFiles.isEmpty()) { if (indexFiles != null && !indexFiles.isEmpty()) {
return indexFiles; return indexFiles;
} else { } else {
@ -116,6 +117,9 @@ public class DownloadIndexActivity extends ListActivity {
} else if(key.endsWith(IndexConstants.POI_INDEX_EXT)){ } else if(key.endsWith(IndexConstants.POI_INDEX_EXT)){
parent = new File(Environment.getExternalStorageDirectory(), ResourceManager.POI_PATH); parent = new File(Environment.getExternalStorageDirectory(), ResourceManager.POI_PATH);
regionName += IndexConstants.POI_INDEX_EXT; regionName += IndexConstants.POI_INDEX_EXT;
} else if(key.endsWith(IndexConstants.TRANSPORT_INDEX_EXT)){
parent = new File(Environment.getExternalStorageDirectory(), ResourceManager.TRANSPORT_PATH);
regionName += IndexConstants.TRANSPORT_INDEX_EXT;
} }
if(parent != null){ if(parent != null){
parent.mkdirs(); parent.mkdirs();
@ -150,6 +154,8 @@ public class DownloadIndexActivity extends ListActivity {
ResourceManager.getResourceManager().indexingAddress(impl, warnings, file); ResourceManager.getResourceManager().indexingAddress(impl, warnings, file);
} else if(file.getName().endsWith(IndexConstants.POI_INDEX_EXT)){ } else if(file.getName().endsWith(IndexConstants.POI_INDEX_EXT)){
ResourceManager.getResourceManager().indexingPoi(impl, warnings, file); ResourceManager.getResourceManager().indexingPoi(impl, warnings, file);
} else if(file.getName().endsWith(IndexConstants.TRANSPORT_INDEX_EXT)){
ResourceManager.getResourceManager().indexingTransport(impl, warnings, file);
} }
if(warnings.isEmpty()){ if(warnings.isEmpty()){
showWarning(getString(R.string.download_index_success)); showWarning(getString(R.string.download_index_success));
@ -200,7 +206,15 @@ public class DownloadIndexActivity extends ListActivity {
TextView description = (TextView) row.findViewById(R.id.download_descr); TextView description = (TextView) row.findViewById(R.id.download_descr);
Entry<String, String> e = getItem(position); Entry<String, String> e = getItem(position);
int l = e.getKey().lastIndexOf('_'); int l = e.getKey().lastIndexOf('_');
String s = e.getKey().endsWith(IndexConstants.POI_INDEX_EXT) ? getString(R.string.poi) : getString(R.string.address); String s = ""; //$NON-NLS-1$
if(e.getKey().endsWith(IndexConstants.POI_INDEX_EXT)){
s = getString(R.string.poi);
} else if(e.getKey().endsWith(IndexConstants.ADDRESS_INDEX_EXT)){
s = getString(R.string.address);
} else if(e.getKey().endsWith(IndexConstants.TRANSPORT_INDEX_EXT)){
s = "Transport";
}
item.setText(s + "\n " + e.getKey().substring(0, l)); //$NON-NLS-1$ item.setText(s + "\n " + e.getKey().substring(0, l)); //$NON-NLS-1$
description.setText(e.getValue().replace(':', '\n')); description.setText(e.getValue().replace(':', '\n'));
return row; return row;

View file

@ -448,7 +448,7 @@ public class EditingPOIActivity {
} }
private void updateNodeInIndexes(String action, Node n){ private void updateNodeInIndexes(String action, Node n){
List<AmenityIndexRepository> repos = ResourceManager.getResourceManager().searchRepositories(n.getLatitude(), n.getLongitude()); List<AmenityIndexRepository> repos = ResourceManager.getResourceManager().searchAmenityRepositories(n.getLatitude(), n.getLongitude());
if(DELETE_ACTION.equals(action)){ if(DELETE_ACTION.equals(action)){
for(AmenityIndexRepository r: repos){ for(AmenityIndexRepository r: repos){
r.deleteAmenity(n.getId()); r.deleteAmenity(n.getId());

View file

@ -72,6 +72,7 @@ import com.osmand.views.POIMapLayer;
import com.osmand.views.PointLocationLayer; import com.osmand.views.PointLocationLayer;
import com.osmand.views.PointNavigationLayer; import com.osmand.views.PointNavigationLayer;
import com.osmand.views.RouteLayer; import com.osmand.views.RouteLayer;
import com.osmand.views.TransportStopsLayer;
public class MapActivity extends Activity implements LocationListener, IMapLocationListener, SensorEventListener { public class MapActivity extends Activity implements LocationListener, IMapLocationListener, SensorEventListener {
@ -95,6 +96,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
private RouteLayer routeLayer; private RouteLayer routeLayer;
private OsmBugsLayer osmBugsLayer; private OsmBugsLayer osmBugsLayer;
private POIMapLayer poiMapLayer; private POIMapLayer poiMapLayer;
private TransportStopsLayer transportStopsLayer;
private PointLocationLayer locationLayer; private PointLocationLayer locationLayer;
private PointNavigationLayer navigationLayer; private PointNavigationLayer navigationLayer;
private MapInfoLayer mapInfoLayer; private MapInfoLayer mapInfoLayer;
@ -172,13 +174,16 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
osmBugsLayer = new OsmBugsLayer(this); osmBugsLayer = new OsmBugsLayer(this);
// 3. poi layer // 3. poi layer
poiMapLayer = new POIMapLayer(); poiMapLayer = new POIMapLayer();
// 4. point navigation layer // 4. poi layer
transportStopsLayer = new TransportStopsLayer();
mapView.addLayer(transportStopsLayer);
// 5. point navigation layer
navigationLayer = new PointNavigationLayer(); navigationLayer = new PointNavigationLayer();
mapView.addLayer(navigationLayer); mapView.addLayer(navigationLayer);
// 5. point location layer // 6. point location layer
locationLayer = new PointLocationLayer(); locationLayer = new PointLocationLayer();
mapView.addLayer(locationLayer); mapView.addLayer(locationLayer);
// 6. map info layer // 7. map info layer
mapInfoLayer = new MapInfoLayer(this, routeLayer); mapInfoLayer = new MapInfoLayer(this, routeLayer);
mapView.addLayer(mapInfoLayer); mapView.addLayer(mapInfoLayer);
@ -778,7 +783,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
Toast.makeText(this, getString(R.string.update_poi_is_not_available_for_zoom), Toast.LENGTH_SHORT).show(); Toast.makeText(this, getString(R.string.update_poi_is_not_available_for_zoom), Toast.LENGTH_SHORT).show();
return; return;
} }
final List<AmenityIndexRepository> repos = ResourceManager.getResourceManager().searchRepositories(latitude, longitude); final List<AmenityIndexRepository> repos = ResourceManager.getResourceManager().searchAmenityRepositories(latitude, longitude);
if(repos.isEmpty()){ if(repos.isEmpty()){
Toast.makeText(this, getString(R.string.update_poi_no_offline_poi_index), Toast.LENGTH_SHORT).show(); Toast.makeText(this, getString(R.string.update_poi_no_offline_poi_index), Toast.LENGTH_SHORT).show();
return; return;
@ -918,5 +923,4 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
} }
} }

View file

@ -237,7 +237,7 @@ public class OsmBugsLayer implements OsmandMapLayer {
int y = view.getRotatedMapYForPoint(n.getLatitude(), n.getLongitude()); int y = view.getRotatedMapYForPoint(n.getLatitude(), n.getLongitude());
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) { if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
String format = "Bug : " + n.getName(); //$NON-NLS-1$ String format = "Bug : " + n.getName(); //$NON-NLS-1$
Toast.makeText(view.getContext(), format, Toast.LENGTH_SHORT).show(); Toast.makeText(view.getContext(), format, Toast.LENGTH_LONG).show();
return true; return true;
} }
} }

View file

@ -0,0 +1,151 @@
package com.osmand.views;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.widget.Toast;
import com.osmand.OsmandSettings;
import com.osmand.ResourceManager;
import com.osmand.TransportIndexRepository;
import com.osmand.data.TransportStop;
import com.osmand.osm.MapUtils;
public class TransportStopsLayer implements OsmandMapLayer {
private static final int startZoom = 12;
private Paint pointAltUI;
private OsmandMapTileView view;
private List<TransportStop> objects = new ArrayList<TransportStop>();
private ResourceManager resourceManager;
@Override
public void initLayer(OsmandMapTileView view) {
this.view = view;
pointAltUI = new Paint();
pointAltUI.setColor(Color.rgb(0, 0, 255));
pointAltUI.setAlpha(200);
pointAltUI.setAntiAlias(true);
resourceManager = ResourceManager.getResourceManager();
pixRect.set(0, 0, view.getWidth(), view.getHeight());
}
public TransportStop getFromPoint(PointF point){
if (objects != null) {
int ex = (int) point.x;
int ey = (int) point.y;
int radius = getRadiusPoi(view.getZoom()) * 3 / 2;
try {
for (int i = 0; i < objects.size(); i++) {
TransportStop n = objects.get(i);
int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
return n;
}
}
} catch (IndexOutOfBoundsException e) {
// that's really rare case, but is much efficient than introduce synchronized block
}
}
return null;
}
public int getTileSize(){
return view.getTileSize();
}
@Override
public boolean onTouchEvent(PointF point) {
TransportStop n = getFromPoint(point);
if(n != null){
StringBuilder text = new StringBuilder(250);
text.append("Stop").append(" : ").append(n.getName(OsmandSettings.usingEnglishNames(view.getContext()))); //$NON-NLS-2$
text.append("\n").append("Routes").append(" : "); //$NON-NLS-1$//$NON-NLS-3$
List<TransportIndexRepository> reps = ResourceManager.getResourceManager().searchTransportRepositories(n.getLocation().getLatitude(), n.getLocation().getLongitude());
if(!reps.isEmpty()){
List<String> l;
if(OsmandSettings.usingEnglishNames(view.getContext())){
l = reps.get(0).getRouteDescriptionsForStop(n, "{1} {0} - {3}"); //$NON-NLS-1$
} else {
l = reps.get(0).getRouteDescriptionsForStop(n, "{1} {0} - {2}"); //$NON-NLS-1$
}
for(String s : l){
text.append("\n").append(s); //$NON-NLS-1$
}
}
Toast.makeText(view.getContext(), text.toString(), Toast.LENGTH_LONG).show();
return true;
}
return false;
}
public int getRadiusPoi(int zoom){
if(zoom < startZoom){
return 0;
} else if(zoom <= 15){
return 7;
} else if(zoom == 16){
return 10;
} else if(zoom == 17){
return 14;
} else {
return 18;
}
}
Rect pixRect = new Rect();
RectF tileRect = new RectF();
@Override
public void onDraw(Canvas canvas) {
if (view.getZoom() >= startZoom) {
pixRect.set(0, 0, view.getWidth(), view.getHeight());
view.calculateTileRectangle(pixRect, view.getCenterPointX(),
view.getCenterPointY(), view.getXTile(), view.getYTile(), tileRect);
double topLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.top);
double leftLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.left);
double bottomLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.bottom);
double rightLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.right);
objects.clear();
resourceManager.searchTransportAsync(topLatitude, leftLongitude, bottomLatitude, rightLongitude, view.getZoom(), objects);
for (TransportStop o : objects) {
int x = view.getMapXForPoint(o.getLocation().getLongitude());
int y = view.getMapYForPoint(o.getLocation().getLatitude());
canvas.drawCircle(x, y, getRadiusPoi(view.getZoom()), pointAltUI);
}
}
}
@Override
public void destroyLayer() {
}
@Override
public boolean drawInScreenPixels() {
return false;
}
@Override
public boolean onLongPressEvent(PointF point) {
// TODO open search transport
return false;
}
}