1 package tim.prune.gui.map;
4 * Class to hold the current position of the map
6 public class MapPosition
8 /** Width and height of each tile of map */
9 private static final int MAP_TILE_SIZE = 256;
11 /** x position (scale depends on zoom) */
12 private int _xPosition = 0;
13 /** y position (scale depends on zoom) */
14 private int _yPosition = 0;
16 /** Zoom level, from 2 to max */
17 private int _zoom = 12;
18 /** Factor to zoom by, 2 to the power of zoom */
19 private int _zoomFactor = 1 << _zoom;
20 /** Flag to mark if this position has ever been set */
21 private boolean _empty = true;
22 /** Maximum zoom level */
23 private static final int MAX_ZOOM = 21;
27 * Zoom and pan to show the selected area
28 * @param inMinX minimum transformed X
29 * @param inMaxX maximum transformed X
30 * @param inMinY minimum transformed Y
31 * @param inMaxY maximum transformed Y
32 * @param inWidth width of display
33 * @param inHeight height of display
35 public void zoomToXY(double inMinX, double inMaxX, double inMinY, double inMaxY, int inWidth, int inHeight)
37 // System.out.println("Zooming to " + inMinX + ", " + inMaxX + ", " + inMinY + ", " + inMaxY + "; width=" + inWidth + ", height=" + inHeight);
38 double diffX = Math.abs(inMaxX - inMinX);
39 double diffY = Math.abs(inMaxY - inMinY);
40 // Find out what zoom level to go to
41 int requiredZoom = -1;
42 for (int currZoom = MAX_ZOOM; currZoom >= 2; currZoom--)
44 if (transformToPixels(diffX, currZoom) < inWidth
45 && transformToPixels(diffY, currZoom) < inHeight)
47 requiredZoom = currZoom;
51 if (requiredZoom < 2) requiredZoom = 2;
52 else if (requiredZoom > 18) requiredZoom = 18;
54 setZoom(requiredZoom);
55 _xPosition = transformToPixels((inMinX + inMaxX) / 2.0);
56 _yPosition = transformToPixels((inMinY + inMaxY) / 2.0);
61 * Ensure that zoom and zoomFactor remain in sync
62 * @param inZoom zoom level to set
64 private void setZoom(int inZoom)
67 _zoomFactor = 1 << _zoom;
72 * Zoom and pan to show the selected area
73 * @param inMinX minimum pixels X
74 * @param inMaxX maximum pixels X
75 * @param inMinY minimum pixels Y
76 * @param inMaxY maximum pixels Y
77 * @param inWidth width of display
78 * @param inHeight height of display
80 public void zoomToPixels(int inMinX, int inMaxX, int inMinY, int inMaxY, int inWidth, int inHeight)
82 // System.out.println("Current position is " + _xPosition + ", " + _yPosition);
83 int diffX = Math.abs(inMaxX - inMinX);
84 int diffY = Math.abs(inMaxY - inMinY);
85 // Find out what zoom level to go to
86 int requiredZoom = -1;
88 for (int currZoom = MAX_ZOOM; currZoom >= _zoom; currZoom--)
90 multFactor = 1 << (currZoom - _zoom);
91 if ((diffX * multFactor) < inWidth && (diffY * multFactor) < inHeight)
93 requiredZoom = currZoom;
97 setZoom(requiredZoom);
99 _xPosition = (_xPosition - inWidth/2 + (inMinX + inMaxX) / 2) * multFactor;
100 _yPosition = (_yPosition - inHeight/2 + (inMinY + inMaxY) / 2) * multFactor;
105 * Transform a given coordinate into pixels using the current zoom value
106 * @param inValue value to transform
109 private int transformToPixels(double inValue)
111 return transformToPixels(inValue, _zoom);
115 * Transform a given coordinate into pixels using the specified zoom value
116 * @param inValue value to transform
117 * @param inZoom zoom value to use
120 private static int transformToPixels(double inValue, int inZoom)
122 return (int) (inValue * MAP_TILE_SIZE * (1 << inZoom));
126 * Convert pixels back into x coordinates
127 * @param inPixelX x coordinate on screen
128 * @param inWidth current width of window
129 * @return x coordinate
131 public double getXFromPixels(int inPixelX, int inWidth)
133 return ((inPixelX - inWidth/2) + _xPosition) * 1.0 / MAP_TILE_SIZE / _zoomFactor;
137 * Convert pixels back into y coordinates
138 * @param inPixelY y coordinate on screen
139 * @param inHeight current height of window
140 * @return y coordinate
142 public double getYFromPixels(int inPixelY, int inHeight)
144 return ((inPixelY - inHeight/2) + _yPosition) * 1.0 / MAP_TILE_SIZE / _zoomFactor;
148 * Get the horizontal offset from the centre
149 * @param inValue value to transform
150 * @return number of pixels right (+ve) or left (-ve) from the centre
152 public int getXFromCentre(double inValue)
154 return transformToPixels(inValue) - _xPosition;
158 * Get the vertical offset from the centre
159 * @param inValue value to transform
160 * @return number of pixels up (+ve) or down (-ve) from the centre
162 public int getYFromCentre(double inValue)
164 return transformToPixels(inValue) - _yPosition;
168 * Convert a pixel value into a bounds value for sensitivity
169 * @param inPixels number of pixels
170 * @return bounds value to use for x,y checking
172 public double getBoundsFromPixels(int inPixels) {
173 return (inPixels * 1.0 / MAP_TILE_SIZE / _zoomFactor);
177 * Get the leftmost, rightmost, upper and lower index boundaries for the tiles to display
178 * @param inWidth width of window
179 * @param inHeight height of window
180 * @return tile indices as array left, right, up, down
182 public int[] getTileIndices(int inWidth, int inHeight)
184 int[] result = new int[4];
185 result[0] = getTileIndex(_xPosition - inWidth/2);
186 result[1] = getTileIndex(_xPosition + inWidth/2);
187 result[2] = getTileIndex(_yPosition - inHeight/2);
188 result[3] = getTileIndex(_yPosition + inHeight/2);
193 * Get the pixel offsets for the display
194 * @param inWidth width of window
195 * @param inHeight height of window
196 * @return offsets as x, y
198 public int[] getDisplayOffsets(int inWidth, int inHeight)
200 int[] result = new int[2];
201 result[0] = getDisplayOffset(_xPosition - inWidth/2);
202 result[1] = getDisplayOffset(_yPosition - inHeight/2);
207 * @return x index of the centre tile
209 public int getCentreTileX()
211 return getTileIndex(_xPosition);
215 * @return y index of the centre tile
217 public int getCentreTileY()
219 return getTileIndex(_yPosition);
223 * @param inPosition position of point
224 * @return tile index for that point
226 private int getTileIndex(int inPosition)
228 return inPosition / MAP_TILE_SIZE;
232 * @param inPosition position of point
233 * @return pixel offset for that point
235 private int getDisplayOffset(int inPosition)
237 return inPosition % MAP_TILE_SIZE;
238 // I thought that &255 would be slightly faster, but it gives the wrong result
246 if (_zoom < MAX_ZOOM)
257 public void zoomOut()
268 * @return current zoom level
276 * Pan map by the specified amount
277 * @param inDeltaX amount to pan right
278 * @param inDeltaY amount to pan down
280 public void pan(int inDeltaX, int inDeltaY)
282 // TODO: Check bounds?
283 _xPosition += inDeltaX;
284 _yPosition += inDeltaY;
288 * @return true if this position has never been set
290 public boolean isEmpty()