diff --git a/data/maps.xsd b/data/maps.xsd
index 2643b2d..308edd4 100644
a
|
b
|
|
670 | 670 | </xs:all> |
671 | 671 | </xs:complexType> |
672 | 672 | </xs:element> |
| 673 | <!-- list of HTTP headers, that indicate "no tile at this zoom level" situation --> |
673 | 674 | <xs:element name="no-tile-header" minOccurs="0" maxOccurs="unbounded"> |
674 | 675 | <xs:complexType> |
675 | 676 | <xs:attribute name="name" type="xs:string" /> |
676 | 677 | <xs:attribute name="value" type="xs:string" /> |
677 | 678 | </xs:complexType> |
678 | 679 | </xs:element> |
| 680 | <!-- tile size provided by imagery source. Default - 256 --> |
| 681 | <xs:element name="tile-size" minOccurs="0" maxOccurs="1" type="xs:positiveInteger" /> |
679 | 682 | </xs:choice> |
680 | 683 | </xs:sequence> |
681 | 684 | <xs:attribute name="last-check" type="xs:date" use="optional" /> |
diff --git a/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java b/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java
index 903ee25..ab08dd2 100644
a
|
b
|
package org.openstreetmap.gui.jmapviewer;
|
10 | 10 | */ |
11 | 11 | public class OsmMercator { |
12 | 12 | |
13 | | public static int TILE_SIZE = 256; |
| 13 | /** |
| 14 | * default tile size |
| 15 | */ |
| 16 | public static int DEFAUL_TILE_SIZE = 256; |
14 | 17 | public static final double MAX_LAT = 85.05112877980659; |
15 | 18 | public static final double MIN_LAT = -85.05112877980659; |
16 | 19 | private static double EARTH_RADIUS = 6378137; // equatorial earth radius for EPSG:3857 (Mercator) |
17 | 20 | |
18 | | public static double radius(int aZoomlevel) { |
19 | | return (TILE_SIZE * (1 << aZoomlevel)) / (2.0 * Math.PI); |
| 21 | /** |
| 22 | * instance with tile size of 256 for easy conversions |
| 23 | */ |
| 24 | public static final OsmMercator MERCATOR_256 = new OsmMercator(); |
| 25 | |
| 26 | private int tileSize = DEFAUL_TILE_SIZE; |
| 27 | |
| 28 | /** |
| 29 | * Creates instance with default tile size of 256 |
| 30 | */ |
| 31 | public OsmMercator() { |
| 32 | } |
| 33 | |
| 34 | /** |
| 35 | * Creates instance with provided tile size. |
| 36 | * @param tileSize |
| 37 | */ |
| 38 | public OsmMercator(int tileSize) { |
| 39 | this.tileSize = tileSize; |
| 40 | } |
| 41 | |
| 42 | public double radius(int aZoomlevel) { |
| 43 | return (tileSize * (1 << aZoomlevel)) / (2.0 * Math.PI); |
20 | 44 | } |
21 | 45 | |
22 | 46 | /** |
23 | 47 | * Returns the absolut number of pixels in y or x, defined as: 2^Zoomlevel * |
24 | | * TILE_WIDTH where TILE_WIDTH is the width of a tile in pixels |
| 48 | * tileSize where tileSize is the width of a tile in pixels |
25 | 49 | * |
26 | 50 | * @param aZoomlevel zoom level to request pixel data |
27 | 51 | * @return number of pixels |
28 | 52 | */ |
29 | | public static int getMaxPixels(int aZoomlevel) { |
30 | | return TILE_SIZE * (1 << aZoomlevel); |
| 53 | public int getMaxPixels(int aZoomlevel) { |
| 54 | return tileSize * (1 << aZoomlevel); |
31 | 55 | } |
32 | 56 | |
33 | | public static int falseEasting(int aZoomlevel) { |
| 57 | public int falseEasting(int aZoomlevel) { |
34 | 58 | return getMaxPixels(aZoomlevel) / 2; |
35 | 59 | } |
36 | 60 | |
37 | | public static int falseNorthing(int aZoomlevel) { |
| 61 | public int falseNorthing(int aZoomlevel) { |
38 | 62 | return (-1 * getMaxPixels(aZoomlevel) / 2); |
39 | 63 | } |
40 | 64 | |
… |
… |
public class OsmMercator {
|
50 | 74 | * @return the distance |
51 | 75 | * @author Jason Huntley |
52 | 76 | */ |
53 | | public static double getDistance(int x1, int y1, int x2, int y2, int zoomLevel) { |
| 77 | public double getDistance(int x1, int y1, int x2, int y2, int zoomLevel) { |
54 | 78 | double la1 = YToLat(y1, zoomLevel); |
55 | 79 | double lo1 = XToLon(x1, zoomLevel); |
56 | 80 | double la2 = YToLat(y2, zoomLevel); |
… |
… |
public class OsmMercator {
|
69 | 93 | * @return the distance |
70 | 94 | * @author Jason Huntley |
71 | 95 | */ |
72 | | public static double getDistance(double la1, double lo1, double la2, double lo2) { |
| 96 | public double getDistance(double la1, double lo1, double la2, double lo2) { |
73 | 97 | double aStartLat = Math.toRadians(la1); |
74 | 98 | double aStartLong = Math.toRadians(lo1); |
75 | 99 | double aEndLat =Math.toRadians(la2); |
… |
… |
public class OsmMercator {
|
100 | 124 | * @return [0..2^Zoomlevel*TILE_SIZE[ |
101 | 125 | * @author Jan Peter Stotz |
102 | 126 | */ |
103 | | public static double LonToX(double aLongitude, int aZoomlevel) { |
| 127 | public double LonToX(double aLongitude, int aZoomlevel) { |
104 | 128 | int mp = getMaxPixels(aZoomlevel); |
105 | 129 | double x = (mp * (aLongitude + 180l)) / 360l; |
106 | 130 | return Math.min(x, mp - 1); |
… |
… |
public class OsmMercator {
|
124 | 148 | * @return [0..2^Zoomlevel*TILE_SIZE[ |
125 | 149 | * @author Jan Peter Stotz |
126 | 150 | */ |
127 | | public static double LatToY(double aLat, int aZoomlevel) { |
| 151 | public double LatToY(double aLat, int aZoomlevel) { |
128 | 152 | if (aLat < MIN_LAT) |
129 | 153 | aLat = MIN_LAT; |
130 | 154 | else if (aLat > MAX_LAT) |
… |
… |
public class OsmMercator {
|
154 | 178 | * @return ]-180..180[ |
155 | 179 | * @author Jan Peter Stotz |
156 | 180 | */ |
157 | | public static double XToLon(int aX, int aZoomlevel) { |
| 181 | public double XToLon(int aX, int aZoomlevel) { |
158 | 182 | return ((360d * aX) / getMaxPixels(aZoomlevel)) - 180.0; |
159 | 183 | } |
160 | 184 | |
… |
… |
public class OsmMercator {
|
165 | 189 | * [0..2^Zoomlevel*TILE_WIDTH[ |
166 | 190 | * @return [MIN_LAT..MAX_LAT] is about [-85..85] |
167 | 191 | */ |
168 | | public static double YToLat(int aY, int aZoomlevel) { |
| 192 | public double YToLat(int aY, int aZoomlevel) { |
169 | 193 | aY += falseNorthing(aZoomlevel); |
170 | 194 | double latitude = (Math.PI / 2) - (2 * Math.atan(Math.exp(-1.0 * aY / radius(aZoomlevel)))); |
171 | 195 | return -1 * Math.toDegrees(latitude); |
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTMSTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTMSTileSource.java
index 9e44ea0..4842ae4 100644
a
|
b
|
public abstract class AbstractTMSTileSource extends AbstractTileSource {
|
14 | 14 | protected String baseUrl; |
15 | 15 | protected String id; |
16 | 16 | private Map<String, String> noTileHeaders; |
| 17 | protected int tileSize; |
| 18 | protected OsmMercator osmMercator; |
17 | 19 | |
18 | 20 | public AbstractTMSTileSource(TileSourceInfo info) { |
19 | 21 | this.name = info.getName(); |
… |
… |
public abstract class AbstractTMSTileSource extends AbstractTileSource {
|
23 | 25 | } |
24 | 26 | this.id = info.getUrl(); |
25 | 27 | this.noTileHeaders = info.getNoTileHeaders(); |
| 28 | this.tileSize = info.getTileSize(); |
| 29 | osmMercator = new OsmMercator(this.tileSize); |
26 | 30 | } |
27 | 31 | |
28 | 32 | @Override |
… |
… |
public abstract class AbstractTMSTileSource extends AbstractTileSource {
|
80 | 84 | */ |
81 | 85 | @Override |
82 | 86 | public int getTileSize() { |
83 | | return OsmMercator.TILE_SIZE; |
| 87 | return tileSize; |
84 | 88 | } |
85 | 89 | |
86 | 90 | @Override |
87 | 91 | public double getDistance(double lat1, double lon1, double lat2, double lon2) { |
88 | | return OsmMercator.getDistance(lat1, lon1, lat2, lon2); |
| 92 | return osmMercator.getDistance(lat1, lon1, lat2, lon2); |
89 | 93 | } |
90 | 94 | |
91 | 95 | @Override |
92 | 96 | public int LonToX(double lon, int zoom) { |
93 | | return (int )OsmMercator.LonToX(lon, zoom); |
| 97 | return (int )osmMercator.LonToX(lon, zoom); |
94 | 98 | } |
95 | 99 | |
96 | 100 | @Override |
97 | 101 | public int LatToY(double lat, int zoom) { |
98 | | return (int )OsmMercator.LatToY(lat, zoom); |
| 102 | return (int )osmMercator.LatToY(lat, zoom); |
99 | 103 | } |
100 | 104 | |
101 | 105 | @Override |
102 | 106 | public double XToLon(int x, int zoom) { |
103 | | return OsmMercator.XToLon(x, zoom); |
| 107 | return osmMercator.XToLon(x, zoom); |
104 | 108 | } |
105 | 109 | |
106 | 110 | @Override |
107 | 111 | public double YToLat(int y, int zoom) { |
108 | | return OsmMercator.YToLat(y, zoom); |
| 112 | return osmMercator.YToLat(y, zoom); |
109 | 113 | } |
110 | 114 | |
111 | 115 | @Override |
112 | 116 | public double latToTileY(double lat, int zoom) { |
113 | | return OsmMercator.LatToY(lat, zoom) / OsmMercator.TILE_SIZE; |
| 117 | return osmMercator.LatToY(lat, zoom) / tileSize; |
114 | 118 | } |
115 | 119 | |
116 | 120 | @Override |
117 | 121 | public double lonToTileX(double lon, int zoom) { |
118 | | return OsmMercator.LonToX(lon, zoom) / OsmMercator.TILE_SIZE; |
| 122 | return osmMercator.LonToX(lon, zoom) / tileSize; |
119 | 123 | } |
120 | 124 | |
121 | 125 | @Override |
122 | 126 | public double tileYToLat(int y, int zoom) { |
123 | | return OsmMercator.YToLat(y * OsmMercator.TILE_SIZE, zoom); |
| 127 | return osmMercator.YToLat(y * tileSize, zoom); |
124 | 128 | } |
125 | 129 | |
126 | 130 | @Override |
127 | 131 | public double tileXToLon(int x, int zoom) { |
128 | | return OsmMercator.XToLon(x * OsmMercator.TILE_SIZE, zoom); |
| 132 | return osmMercator.XToLon(x * tileSize, zoom); |
129 | 133 | } |
130 | 134 | |
131 | 135 | @Override |
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java
index 6acd716..9f67568 100644
a
|
b
|
public class ScanexTileSource extends TMSTileSource {
|
93 | 93 | |
94 | 94 | @Override |
95 | 95 | public int LatToY(double lat, int zoom) { |
96 | | return (int )(latToTileY(lat, zoom) * OsmMercator.TILE_SIZE); |
| 96 | return (int )(latToTileY(lat, zoom) * tileSize); |
97 | 97 | } |
98 | 98 | |
99 | 99 | @Override |
100 | 100 | public double YToLat(int y, int zoom) { |
101 | | return tileYToLat((double )y / OsmMercator.TILE_SIZE, zoom); |
| 101 | return tileYToLat((double )y / tileSize, zoom); |
102 | 102 | } |
103 | 103 | |
104 | 104 | @Override |
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/TileSourceInfo.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/TileSourceInfo.java
index f5b342c..c45eb8b 100644
a
|
b
|
package org.openstreetmap.gui.jmapviewer.tilesources;
|
3 | 3 | |
4 | 4 | import java.util.Map; |
5 | 5 | |
| 6 | import org.openstreetmap.gui.jmapviewer.OsmMercator; |
| 7 | |
6 | 8 | /** |
7 | 9 | * Data class that keeps basic information about a tile source. |
8 | 10 | */ |
… |
… |
public class TileSourceInfo {
|
27 | 29 | /** cookies that needs to be sent to tile source */ |
28 | 30 | protected String cookies; |
29 | 31 | |
| 32 | private int tileSize = OsmMercator.DEFAUL_TILE_SIZE; |
30 | 33 | |
31 | 34 | /** |
32 | 35 | * Create a TileSourceInfo class |
… |
… |
public class TileSourceInfo {
|
104 | 107 | return cookies; |
105 | 108 | } |
106 | 109 | |
| 110 | /** |
| 111 | * |
| 112 | * @return tile size provided by this tile source |
| 113 | */ |
| 114 | public int getTileSize() { |
| 115 | return tileSize; |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | * sets the tile size provided by this tile source |
| 120 | * @param tileSize |
| 121 | */ |
| 122 | public void setTileSize(int tileSize) { |
| 123 | if (tileSize <= 0) { |
| 124 | throw new AssertionError("Invalid tile size: " + tileSize); |
| 125 | } |
| 126 | this.tileSize = tileSize; |
| 127 | } |
| 128 | |
| 129 | |
107 | 130 | } |
diff --git a/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java b/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java
index 608ebed..bc54b8b 100644
a
|
b
|
import java.util.regex.Pattern;
|
18 | 18 | import javax.swing.ImageIcon; |
19 | 19 | |
20 | 20 | import org.openstreetmap.gui.jmapviewer.Coordinate; |
| 21 | import org.openstreetmap.gui.jmapviewer.OsmMercator; |
21 | 22 | import org.openstreetmap.gui.jmapviewer.interfaces.Attributed; |
22 | 23 | import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTileSource; |
23 | 24 | import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource.Mapnik; |
… |
… |
public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInf
|
224 | 225 | @pref String icon; |
225 | 226 | @pref String description; |
226 | 227 | @pref Map<String, String> noTileHeaders; |
| 228 | @pref int tileSize = OsmMercator.DEFAUL_TILE_SIZE; |
227 | 229 | |
228 | 230 | /** |
229 | 231 | * Constructs a new empty WMS {@code ImageryPreferenceEntry}. |
… |
… |
public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInf
|
280 | 282 | if (i.noTileHeaders != null && !i.noTileHeaders.isEmpty()) { |
281 | 283 | noTileHeaders = i.noTileHeaders; |
282 | 284 | } |
| 285 | |
| 286 | tileSize = i.getTileSize(); |
283 | 287 | } |
284 | 288 | |
285 | 289 | @Override |
… |
… |
public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInf
|
401 | 405 | if (e.noTileHeaders != null) { |
402 | 406 | noTileHeaders = e.noTileHeaders; |
403 | 407 | } |
| 408 | setTileSize(e.tileSize); |
404 | 409 | } |
405 | 410 | |
406 | 411 | /** |
diff --git a/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java b/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java
index e6231a2..f835dfb 100644
a
|
b
|
public class ImageryLayerInfo {
|
149 | 149 | Collection<String> newKnownDefaults = new TreeSet<>(knownDefaults); |
150 | 150 | for (ImageryInfo def : defaultLayers) { |
151 | 151 | // temporary migration code, so all user preferences will get updated with new settings from JOSM site (can be removed ~Dez. 2015) |
152 | | if (def.getNoTileHeaders() != null) { |
| 152 | if (def.getNoTileHeaders() != null || def.getTileSize() > 0) { |
153 | 153 | for (ImageryInfo i: layers) { |
154 | 154 | if (isSimilar(def, i)) { |
155 | | i.setNoTileHeaders(def.getNoTileHeaders()); |
| 155 | if (def.getNoTileHeaders() != null) { |
| 156 | i.setNoTileHeaders(def.getNoTileHeaders()); |
| 157 | } |
| 158 | if (def.getTileSize() > 0) { |
| 159 | i.setTileSize(def.getTileSize()); |
| 160 | } |
156 | 161 | changed = true; |
157 | 162 | } |
158 | 163 | } |
diff --git a/src/org/openstreetmap/josm/gui/bbox/SlippyMapBBoxChooser.java b/src/org/openstreetmap/josm/gui/bbox/SlippyMapBBoxChooser.java
index 7b41c59..c98d890 100644
a
|
b
|
public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser {
|
124 | 124 | private transient Bounds bbox; |
125 | 125 | |
126 | 126 | // upper left and lower right corners of the selection rectangle (x/y on ZOOM_MAX) |
127 | | private Point iSelectionRectStart; |
128 | | private Point iSelectionRectEnd; |
| 127 | private Coordinate iSelectionRectStart; |
| 128 | private Coordinate iSelectionRectEnd; |
129 | 129 | |
130 | 130 | /** |
131 | 131 | * Constructs a new {@code SlippyMapBBoxChooser}. |
… |
… |
public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser {
|
209 | 209 | |
210 | 210 | // draw selection rectangle |
211 | 211 | if (iSelectionRectStart != null && iSelectionRectEnd != null) { |
| 212 | Rectangle box = new Rectangle(getMapPosition(iSelectionRectStart, false)); |
| 213 | box.add(getMapPosition(iSelectionRectEnd, false)); |
212 | 214 | |
213 | | int zoomDiff = MAX_ZOOM - zoom; |
214 | | Point tlc = getTopLeftCoordinates(); |
215 | | int x_min = (iSelectionRectStart.x >> zoomDiff) - tlc.x; |
216 | | int y_min = (iSelectionRectStart.y >> zoomDiff) - tlc.y; |
217 | | int x_max = (iSelectionRectEnd.x >> zoomDiff) - tlc.x; |
218 | | int y_max = (iSelectionRectEnd.y >> zoomDiff) - tlc.y; |
219 | | |
220 | | int w = x_max - x_min; |
221 | | int h = y_max - y_min; |
222 | 215 | g.setColor(new Color(0.9f, 0.7f, 0.7f, 0.6f)); |
223 | | g.fillRect(x_min, y_min, w, h); |
| 216 | g.fillRect(box.x, box.y, box.width, box.height); |
224 | 217 | |
225 | 218 | g.setColor(Color.BLACK); |
226 | | g.drawRect(x_min, y_min, w, h); |
| 219 | g.drawRect(box.x, box.y, box.width, box.height); |
227 | 220 | } |
228 | 221 | } catch (Exception e) { |
229 | 222 | Main.error(e); |
… |
… |
public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser {
|
256 | 249 | Point p_max = new Point(Math.max(aEnd.x, aStart.x), Math.max(aEnd.y, aStart.y)); |
257 | 250 | Point p_min = new Point(Math.min(aEnd.x, aStart.x), Math.min(aEnd.y, aStart.y)); |
258 | 251 | |
259 | | Point tlc = getTopLeftCoordinates(); |
260 | | int zoomDiff = MAX_ZOOM - zoom; |
261 | | Point pEnd = new Point(p_max.x + tlc.x, p_max.y + tlc.y); |
262 | | Point pStart = new Point(p_min.x + tlc.x, p_min.y + tlc.y); |
263 | | |
264 | | pEnd.x <<= zoomDiff; |
265 | | pEnd.y <<= zoomDiff; |
266 | | pStart.x <<= zoomDiff; |
267 | | pStart.y <<= zoomDiff; |
| 252 | iSelectionRectStart = getPosition(p_min); |
| 253 | iSelectionRectEnd = getPosition(p_max); |
268 | 254 | |
269 | | iSelectionRectStart = pStart; |
270 | | iSelectionRectEnd = pEnd; |
271 | | |
272 | | Coordinate l1 = getPosition(p_max); // lon may be outside [-180,180] |
273 | | Coordinate l2 = getPosition(p_min); // lon may be outside [-180,180] |
274 | 255 | Bounds b = new Bounds( |
275 | 256 | new LatLon( |
276 | | Math.min(l2.getLat(), l1.getLat()), |
277 | | LatLon.toIntervalLon(Math.min(l1.getLon(), l2.getLon())) |
| 257 | Math.min(iSelectionRectStart.getLat(), iSelectionRectEnd.getLat()), |
| 258 | LatLon.toIntervalLon(Math.min(iSelectionRectStart.getLon(), iSelectionRectEnd.getLon())) |
278 | 259 | ), |
279 | 260 | new LatLon( |
280 | | Math.max(l2.getLat(), l1.getLat()), |
281 | | LatLon.toIntervalLon(Math.max(l1.getLon(), l2.getLon()))) |
| 261 | Math.max(iSelectionRectStart.getLat(), iSelectionRectEnd.getLat()), |
| 262 | LatLon.toIntervalLon(Math.max(iSelectionRectStart.getLon(), iSelectionRectEnd.getLon()))) |
282 | 263 | ); |
283 | 264 | Bounds oldValue = this.bbox; |
284 | 265 | this.bbox = b; |
… |
… |
public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser {
|
331 | 312 | minLon -= 360.0; |
332 | 313 | } |
333 | 314 | |
334 | | int y1 = tileSource.LatToY(bbox.getMinLat(), MAX_ZOOM); |
335 | | int y2 = tileSource.LatToY(bbox.getMaxLat(), MAX_ZOOM); |
336 | | int x1 = tileSource.LonToX(minLon, MAX_ZOOM); |
337 | | int x2 = tileSource.LonToX(maxLon, MAX_ZOOM); |
338 | | |
339 | | iSelectionRectStart = new Point(Math.min(x1, x2), Math.min(y1, y2)); |
340 | | iSelectionRectEnd = new Point(Math.max(x1, x2), Math.max(y1, y2)); |
| 315 | iSelectionRectStart = new Coordinate(bbox.getMinLat(), bbox.getMinLon()); |
| 316 | iSelectionRectEnd = new Coordinate(bbox.getMaxLat(), bbox.getMaxLon()); |
341 | 317 | |
342 | 318 | // calc the screen coordinates for the new selection rectangle |
343 | 319 | MapMarkerDot xmin_ymin = new MapMarkerDot(bbox.getMinLat(), bbox.getMinLon()); |
diff --git a/src/org/openstreetmap/josm/gui/layer/TMSLayer.java b/src/org/openstreetmap/josm/gui/layer/TMSLayer.java
index f4a29dd..63b716e 100644
a
|
b
|
import org.openstreetmap.josm.data.preferences.BooleanProperty;
|
65 | 65 | import org.openstreetmap.josm.data.preferences.IntegerProperty; |
66 | 66 | import org.openstreetmap.josm.data.preferences.StringProperty; |
67 | 67 | import org.openstreetmap.josm.data.projection.Projection; |
| 68 | import org.openstreetmap.josm.gui.ExtendedDialog; |
68 | 69 | import org.openstreetmap.josm.gui.MapFrame; |
69 | 70 | import org.openstreetmap.josm.gui.MapView; |
70 | 71 | import org.openstreetmap.josm.gui.MapView.LayerChangeListener; |
… |
… |
public class TMSLayer extends ImageryLayer implements ImageObserver, TileLoaderL
|
422 | 423 | } |
423 | 424 | |
424 | 425 | private final int getBestZoom() { |
425 | | double factor = getScaleFactor(1); |
| 426 | double factor = getScaleFactor(1); // check the ratio between area of tilesize at zoom 1 to current view |
426 | 427 | double result = Math.log(factor)/Math.log(2)/2+1; |
427 | | // In general, smaller zoom levels are more readable. We prefer big, |
428 | | // block, pixelated (but readable) map text to small, smeared, |
429 | | // unreadable underzoomed text. So, use .floor() instead of rounding |
430 | | // to skew things a bit toward the lower zooms. |
| 428 | /* |
| 429 | * Math.log(factor)/Math.log(2) - gives log base 2 of factor |
| 430 | * We divide result by 2, as factor contains ratio between areas. We could do Math.sqrt before log, or just divide log by 2 |
| 431 | * In general, smaller zoom levels are more readable. We prefer big, |
| 432 | * block, pixelated (but readable) map text to small, smeared, |
| 433 | * unreadable underzoomed text. So, use .floor() instead of rounding |
| 434 | * to skew things a bit toward the lower zooms. |
| 435 | * Remember, that result here, should correspond to TMSLayer.paint(...) |
| 436 | * getScaleFactor(...) is supposed to be between 0.75 and 3 |
| 437 | */ |
431 | 438 | int intResult = (int)Math.floor(result); |
432 | 439 | if (intResult > getMaxZoomLvl()) |
433 | 440 | return getMaxZoomLvl(); |
… |
… |
public class TMSLayer extends ImageryLayer implements ImageObserver, TileLoaderL
|
513 | 520 | @Override |
514 | 521 | public void actionPerformed(ActionEvent ae) { |
515 | 522 | if (clickedTile != null) { |
516 | | showMetadataTile = clickedTile; |
517 | | redraw(); |
| 523 | ExtendedDialog ed = new ExtendedDialog(Main.parent, tr("Tile Info"), new String[]{tr("OK")}); |
| 524 | ed.setIcon(JOptionPane.INFORMATION_MESSAGE); |
| 525 | StringBuilder content = new StringBuilder(); |
| 526 | content.append("Tile name: ").append(clickedTile.getKey()).append("\n"); |
| 527 | try { |
| 528 | content.append("Tile url: ").append(clickedTile.getUrl()).append("\n"); |
| 529 | } catch (IOException e) { |
| 530 | } |
| 531 | content.append("Tile size: ").append(clickedTile.getTileSource().getTileSize()).append("x").append(clickedTile.getTileSource().getTileSize()).append("\n"); |
| 532 | Rectangle displaySize = tileToRect(clickedTile); |
| 533 | content.append("Tile display size: ").append(displaySize.width).append("x").append(displaySize.height).append("\n"); |
| 534 | ed.setContent(content.toString()); |
| 535 | ed.showDialog(); |
518 | 536 | } |
519 | 537 | } |
520 | 538 | })); |
… |
… |
public class TMSLayer extends ImageryLayer implements ImageObserver, TileLoaderL
|
1383 | 1401 | myDrawString(g, tr("Current zoom: {0}", currentZoomLevel), 50, 140); |
1384 | 1402 | myDrawString(g, tr("Display zoom: {0}", displayZoomLevel), 50, 155); |
1385 | 1403 | myDrawString(g, tr("Pixel scale: {0}", getScaleFactor(currentZoomLevel)), 50, 170); |
1386 | | myDrawString(g, tr("Best zoom: {0}", Math.log(getScaleFactor(1))/Math.log(2)/2+1), 50, 185); |
| 1404 | myDrawString(g, tr("Best zoom: {0}", getBestZoom()), 50, 185); |
1387 | 1405 | if(tileLoader instanceof TMSCachedTileLoader) { |
1388 | 1406 | TMSCachedTileLoader cachedTileLoader = (TMSCachedTileLoader)tileLoader; |
1389 | 1407 | int offset = 185; |
diff --git a/src/org/openstreetmap/josm/io/imagery/ImageryReader.java b/src/org/openstreetmap/josm/io/imagery/ImageryReader.java
index c50e66f..04dc890 100644
a
|
b
|
public class ImageryReader {
|
137 | 137 | "terms-of-use-url", |
138 | 138 | "country-code", |
139 | 139 | "icon", |
| 140 | "tile-size", |
140 | 141 | }).contains(qName)) { |
141 | 142 | newState = State.ENTRY_ATTRIBUTE; |
142 | 143 | lang = atts.getValue("lang"); |
… |
… |
public class ImageryReader {
|
299 | 300 | case "icon": |
300 | 301 | entry.setIcon(accumulator.toString()); |
301 | 302 | break; |
| 303 | case "tile-size": |
| 304 | Integer tileSize = null; |
| 305 | try { |
| 306 | tileSize = Integer.parseInt(accumulator.toString()); |
| 307 | } catch(NumberFormatException e) { |
| 308 | tileSize = null; |
| 309 | } |
| 310 | if (tileSize == null) { |
| 311 | skipEntry = true; |
| 312 | } else { |
| 313 | entry.setTileSize(tileSize.intValue()); |
| 314 | } |
| 315 | break; |
302 | 316 | } |
303 | 317 | break; |
304 | 318 | case BOUNDS: |