X-Git-Url: https://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Fgui%2Fmap%2FMemTileCacher.java;fp=src%2Ftim%2Fprune%2Fgui%2Fmap%2FMemTileCacher.java;h=20d7a213a1a0c1b76001272f862739cec19f5051;hp=0000000000000000000000000000000000000000;hb=ce6f2161b8596f7018d6a76bff79bc9e571f35fd;hpb=2d8cb72e84d5cc1089ce77baf1e34ea3ea2f8465 diff --git a/src/tim/prune/gui/map/MemTileCacher.java b/src/tim/prune/gui/map/MemTileCacher.java new file mode 100644 index 0000000..20d7a21 --- /dev/null +++ b/src/tim/prune/gui/map/MemTileCacher.java @@ -0,0 +1,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) {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; + } + } +}