1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
package tim.prune.gui.map;
import java.awt.Image;
/**
* Class to act as a memory-based map tile cache
* For caching of tiles on disk, see the DiskTileCacher class.
*/
public class MemTileCacher
{
/** Array of images to hold tiles */
private Image[] _tiles = new Image[GRID_SIZE * GRID_SIZE];
/** Current zoom level */
private int _zoom = -1;
/** X coordinate of central tile */
private int _tileX = -1;
/** Y coordinate of central tile */
private int _tileY = -1;
/** X coord of grid centre */
private int _gridCentreX = 0;
/** Y coord of grid centre */
private int _gridCentreY = 0;
/** Grid size */
private static final int GRID_SIZE = 15;
/**
* Recentre the map and clear the cache
* @param inZoom zoom level
* @param inTileX x coord of central tile
* @param inTileY y coord of central tile
*/
public void centreMap(int inZoom, int inTileX, int inTileY)
{
int shift = Math.max(Math.abs(inTileX-_tileX), Math.abs(inTileY - _tileY));
if (shift == 0) {return;}
// Clear cache if either zoom has changed or map has jumped too far
if (inZoom != _zoom || shift > GRID_SIZE/2)
{
_zoom = inZoom;
clearAll();
}
_gridCentreX = getCacheCoordinate(_gridCentreX + inTileX - _tileX);
_gridCentreY = getCacheCoordinate(_gridCentreY + inTileY - _tileY);
_tileX = inTileX;
_tileY = inTileY;
// Mark boundaries as invalid
for (int i=0; i<GRID_SIZE; i++)
{
_tiles[getArrayIndexNoWrap(_tileX + GRID_SIZE/2 + 1, _tileY + i - GRID_SIZE/2)] = null;
_tiles[getArrayIndexNoWrap(_tileX + i - GRID_SIZE/2, _tileY + GRID_SIZE/2 + 1)] = null;
}
}
/**
* Transform a coordinate from map tiles to array coordinates
* @param inTile coordinate of tile
* @return coordinate in array (wrapping around cache grid)
*/
private static int getCacheCoordinate(int inTile)
{
int tile = inTile;
while (tile >= GRID_SIZE) {tile -= GRID_SIZE;}
while (tile < 0) {tile += GRID_SIZE;}
return tile;
}
/**
* Get the array index for the given coordinates, including regular lon wrapping
* @param inX x coord of tile
* @param inY y coord of tile
* @return array index
*/
private int getArrayIndex(int inX, int inY)
{
final int tileSpan = 1 << _zoom;
int deltaX = (inX - _tileX);
while (deltaX > (tileSpan/2)) {deltaX -= tileSpan;}
while (deltaX < (-tileSpan/2)) {deltaX += tileSpan;}
int x = getCacheCoordinate(deltaX + _gridCentreX);
int y = getCacheCoordinate(inY - _tileY + _gridCentreY);
return (x + y * GRID_SIZE);
}
/**
* Get the array index for the given coordinates, without wrapping x coords
* (used for deletion to avoid deleting the wrong tile)
* @param inX x coord of tile
* @param inY y coord of tile
* @return array index
*/
private int getArrayIndexNoWrap(int inX, int inY)
{
int x = getCacheCoordinate(inX - _tileX + _gridCentreX);
int y = getCacheCoordinate(inY - _tileY + _gridCentreY);
return (x + y * GRID_SIZE);
}
/**
* Clear all the cached images
*/
public void clearAll()
{
for (int i=0; i<_tiles.length; i++) {
_tiles[i] = null;
}
}
/**
* @param inX x index of tile
* @param inY y index of tile
* @return selected tile if already loaded, or null otherwise
*/
public Image getTile(int inX, int inY)
{
return _tiles[getArrayIndex(inX, inY)];
}
/**
* Save the specified tile at the given coordinates
* @param inTile image to save
* @param inX x coordinate of tile
* @param inY y coordinate of tile
* @param inZoom zoom level
*/
public void setTile(Image inTile, int inX, int inY, int inZoom)
{
// Ignore images received for a different zoom level
if (inZoom == _zoom) {
_tiles[getArrayIndex(inX, inY)] = inTile;
}
}
}
|