// Created by plusminus on 19:24:16 - 12.11.2008
package org.androad.osm.views.tiles.util;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.MapTileProviderBase;
import org.osmdroid.tileprovider.MapTileProviderBasic;
import org.osmdroid.tileprovider.MapTileRequestState;
import org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.util.GeoPoint;
import org.androad.osm.util.ValuePair;
import org.androad.osm.util.Util.PixelSetter;
import org.androad.osm.views.util.Util;
import org.androad.sys.ors.adt.rs.Route;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
public class OSMMapTilePreloader extends MapTileProviderBasic implements Runnable {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
HashSet<MapTile> mLoaded = new HashSet<MapTile>();
ArrayList<MapTile> mTiles;
// ===========================================================
// Constructors
// ===========================================================
public OSMMapTilePreloader(Context pContext, ITileSource pTileSource, final ArrayList<MapTile> pTiles) {
super(pContext, pTileSource);
this.setTileSource(pTileSource);
mTiles = pTiles;
}
// ===========================================================
// Getter & Setter
// ===========================================================
public void setHandler(Handler pHandler) {
this.setTileRequestCompleteHandler(pHandler);
}
public int getProgress() {
return mLoaded.size();
}
public int getTotal() {
return mTiles.size();
}
// ===========================================================
// Methods from SuperClass/Interfaces
// ===========================================================
@Override
public void mapTileRequestCompleted(MapTileRequestState aState, Drawable aDrawable) {
super.mapTileRequestCompleted(aState, aDrawable);
mLoaded.add(aState.getMapTile());
}
// ===========================================================
// Methods
// ===========================================================
/**
* Loads a series of MapTiles to the various caches at a specific zoomlevel.
*/
public void run() {
for(int i = 0; i < mTiles.size(); i++) {
while(i - getProgress() >= OpenStreetMapTileProviderConstants.TILE_DOWNLOAD_MAXIMUM_QUEUE_SIZE) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
this.getMapTile(mTiles.get(i));
}
}
/**
*
* @param aRoute
* @param aZoomLevel
* @param aProviderInfo
* @param pSmoothed Smoothed by a Bresenham-Algorithm
* @return
* @throws IllegalArgumentException
*/
public static ArrayList<MapTile> getNeededMaptiles(final Route aRoute, final int aZoomLevel, final MapTileProviderBase aProviderInfo, final boolean pSmoothed) throws IllegalArgumentException {
return getNeededMaptiles(aRoute.getPolyLine(), aZoomLevel, aProviderInfo, pSmoothed);
}
/**
*
* @param aPath
* @param aZoomLevel
* @param aProviderInfo
* @param pSmoothed Smoothed by a Bresenham-Algorithm
* @return
* @throws IllegalArgumentException
*/
public static ArrayList<MapTile> getNeededMaptiles(final List<GeoPoint> aPath, final int aZoomLevel, final MapTileProviderBase aProviderInfo, final boolean pSmoothed) throws IllegalArgumentException {
if(aZoomLevel > aProviderInfo.getMaximumZoomLevel()) {
throw new IllegalArgumentException("Zoomlevel higher than Renderer supplies!");
}
/* We need only unique MapTile-indices, so we use a Set. */
final Set<ValuePair> needed = new TreeSet<ValuePair>(new Comparator<ValuePair>(){
@Override
public int compare(final ValuePair a, final ValuePair b) {
return a.compareTo(b);
}
});
/* Contains the values of a single line. */
final Set<ValuePair> rasterLine = new TreeSet<ValuePair>(new Comparator<ValuePair>(){
@Override
public int compare(final ValuePair a, final ValuePair b) {
return a.compareTo(b);
}
});
final PixelSetter rasterLinePixelSetter = new PixelSetter(){
@Override
public void setPixel(final int x, final int y) {
rasterLine.add(new ValuePair(x,y));
}
};
MapTile cur = null;
GeoPoint previous = null;
/* Get the mapTile-coords of every point in the polyline and add to the set. */
for (final GeoPoint gp : aPath) {
cur = Util.getMapTileFromCoordinates(gp, aZoomLevel);
needed.add(new ValuePair(cur.getX(), cur.getY()));
if(previous != null){
final int prevX = cur.getX();
final int prevY = cur.getY();
cur = Util.getMapTileFromCoordinates(GeoPoint.fromCenterBetween(gp, previous), aZoomLevel);
final int curX = cur.getX();
final int curY = cur.getY();
rasterLine.clear();
org.androad.osm.util.Util.rasterLine(prevX, prevY, curX, curY, rasterLinePixelSetter);
/* If wanted smooth that line. */
if(pSmoothed){
org.androad.osm.util.Util.smoothLine(rasterLine);
}
needed.addAll(rasterLine);
}
previous = gp;
}
/* Put the unique MapTile-indices into an array. */
final int countNeeded = needed.size();
final ArrayList<MapTile> out = new ArrayList<MapTile>(countNeeded);
int i = 0;
for (final ValuePair valuePair : needed) {
out.add(new MapTile(aZoomLevel, valuePair.getValueA(), valuePair.getValueB()));
}
return out;
}
}