package org.osmdroid.gpkg;
import android.content.Context;
import android.os.Build;
import org.osmdroid.api.IGeoPoint;
import org.osmdroid.tileprovider.IMapTileProviderCallback;
import org.osmdroid.tileprovider.IRegisterReceiver;
import org.osmdroid.tileprovider.MapTileProviderArray;
import org.osmdroid.tileprovider.modules.IFilesystemCache;
import org.osmdroid.tileprovider.modules.INetworkAvailablityCheck;
import org.osmdroid.tileprovider.modules.MapTileDownloader;
import org.osmdroid.tileprovider.modules.MapTileFilesystemProvider;
import org.osmdroid.tileprovider.modules.MapTileSqlCacheProvider;
import org.osmdroid.tileprovider.modules.NetworkAvailabliltyCheck;
import org.osmdroid.tileprovider.modules.SqlTileWriter;
import org.osmdroid.tileprovider.modules.TileWriter;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.tileprovider.tilesource.XYTileSource;
import org.osmdroid.tileprovider.util.SimpleRegisterReceiver;
import org.osmdroid.util.BoundingBox;
import java.io.File;
import java.util.Iterator;
import mil.nga.geopackage.GeoPackage;
import mil.nga.geopackage.features.user.FeatureDao;
import mil.nga.geopackage.projection.Projection;
import mil.nga.geopackage.projection.ProjectionFactory;
import mil.nga.geopackage.projection.ProjectionTransform;
import mil.nga.geopackage.tiles.user.TileDao;
/**
* GeoPackage +
* created on 1/5/2017.
*
* @author Alex O'Ree
*/
public class GeoPackageProvider extends MapTileProviderArray implements IMapTileProviderCallback {
protected GeoPackageMapTileModuleProvider geopackage;
protected IFilesystemCache tileWriter;
public GeoPackageProvider(File[] db, Context context) {
this(new SimpleRegisterReceiver(context), new NetworkAvailabliltyCheck(context),
TileSourceFactory.DEFAULT_TILE_SOURCE, context, null, db);
}
public GeoPackageProvider(final IRegisterReceiver pRegisterReceiver,
final INetworkAvailablityCheck aNetworkAvailablityCheck, final ITileSource pTileSource,
final Context pContext, final IFilesystemCache cacheWriter, File[] databases) {
super(pTileSource, pRegisterReceiver);
if (cacheWriter != null) {
tileWriter = cacheWriter;
} else {
if (Build.VERSION.SDK_INT < 10) {
tileWriter = new TileWriter();
} else {
tileWriter = new SqlTileWriter();
}
}
if (Build.VERSION.SDK_INT < 10) {
final MapTileFilesystemProvider fileSystemProvider = new MapTileFilesystemProvider(
pRegisterReceiver, pTileSource);
mTileProviderList.add(fileSystemProvider);
} else {
final MapTileSqlCacheProvider cachedProvider = new MapTileSqlCacheProvider(pRegisterReceiver, pTileSource);
mTileProviderList.add(cachedProvider);
}
geopackage = new GeoPackageMapTileModuleProvider(databases, pContext, tileWriter);
mTileProviderList.add(geopackage);
final MapTileDownloader downloaderProvider = new MapTileDownloader(pTileSource, tileWriter,
aNetworkAvailablityCheck);
mTileProviderList.add(downloaderProvider);
}
public GeoPackageMapTileModuleProvider geoPackageMapTileModuleProvider(){
return geopackage;
}
@Override
public IFilesystemCache getTileWriter() {
return tileWriter;
}
@Override
public void detach() {
//https://github.com/osmdroid/osmdroid/issues/213
//close the writer
if (tileWriter != null)
tileWriter.onDetach();
tileWriter = null;
geopackage.detach();
super.detach();
}
public ITileSource getTileSource(String database, String table) {
Iterator<GeoPackage> iterator = geopackage.tileSources.iterator();
while (iterator.hasNext()){
GeoPackage next = iterator.next();
if (next.getName().equalsIgnoreCase(database)) {
//found the database
if (next.getTileTables().contains(table)) {
//find the tile table
TileSourceBounds t = new TileSourceBounds();
TileDao tileDao = next.getTileDao(table);
mil.nga.geopackage.BoundingBox boundingBox = tileDao.getBoundingBox();
Projection webmercator = ProjectionFactory.getProjection(0);
ProjectionTransform transformation = tileDao.getProjection().getTransformation(webmercator);
boundingBox=transformation.transform(boundingBox);
t.bounds=new BoundingBox(boundingBox.getMaxLatitude(),boundingBox.getMaxLongitude(),boundingBox.getMinLatitude(),boundingBox.getMinLongitude());
t.maxzoom=(int)tileDao.getMaxZoom();
t.minzoom=(int)tileDao.getMinZoom();
return new XYTileSource(table, t.minzoom, t.maxzoom, 256, "", new String[]{database});
}
}
}
return null;
}
/**
* returns null if the database or tile table cannot be found
* @return
*/
public TileSourceBounds getTileSourceBounds() {
Iterator<GeoPackage> iterator = geopackage.tileSources.iterator();
while (iterator.hasNext()){
GeoPackage next = iterator.next();
if (next.getName().equals(((OnlineTileSourceBase)getTileSource()).getBaseUrl())) {
//found the database
if (next.getTileTables().contains(getTileSource().name())) {
//find the tile table
TileSourceBounds t = new TileSourceBounds();
TileDao tileDao = next.getTileDao(getTileSource().name());
mil.nga.geopackage.BoundingBox boundingBox = tileDao.getBoundingBox();
Projection webmercator = ProjectionFactory.getProjection(0);
ProjectionTransform transformation = tileDao.getProjection().getTransformation(webmercator);
boundingBox=transformation.transform(boundingBox);
t.bounds=new BoundingBox(boundingBox.getMaxLatitude(),boundingBox.getMaxLongitude(),boundingBox.getMinLatitude(),boundingBox.getMinLongitude());
t.maxzoom=(int)tileDao.getMaxZoom();
t.minzoom=(int)tileDao.getMinZoom();
return t;
}
}
}
return null;
}
public static class TileSourceBounds{
public BoundingBox bounds;
public int minzoom;
public int maxzoom;
}
}