source: josm/trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/TileZXY.java

Last change on this file was 19519, checked in by stoecker, 6 months ago

unify eol-style

  • Property svn:eol-style set to native
File size: 5.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm.visitor.paint;
3
4import java.util.stream.IntStream;
5import java.util.stream.Stream;
6
7import org.openstreetmap.josm.data.Bounds;
8import org.openstreetmap.josm.data.coor.ILatLon;
9
10/**
11 * A record used for storing tile information for painting.
12 * The origin is upper-left, not lower-left (so more like Google tile coordinates than TMS tile coordinates).
13 * @since 19176
14 */
15public final class TileZXY implements ILatLon {
16 private final int zoom;
17 private final int x;
18 private final int y;
19
20 /**
21 * Create a new {@link TileZXY} object
22 * @param zoom The zoom for which this tile was created
23 * @param x The x coordinate at the specified zoom level
24 * @param y The y coordinate at the specified zoom level
25 */
26 public TileZXY(int zoom, int x, int y) {
27 this.zoom = zoom;
28 this.x = x;
29 this.y = y;
30 }
31
32 /**
33 * Get the zoom level
34 * @return The zoom level for which this tile was created
35 */
36 public int zoom() {
37 return this.zoom;
38 }
39
40 /**
41 * Get the x coordinate
42 * @return The x coordinate for this tile
43 */
44 @SuppressWarnings("PMD.ShortMethodName")
45 public int x() {
46 return this.x;
47 }
48
49 /**
50 * Get the y coordinate
51 * @return The y coordinate for this tile
52 */
53 @SuppressWarnings("PMD.ShortMethodName")
54 public int y() {
55 return this.y;
56 }
57
58 /**
59 * Get the latitude for upper-left corner of this tile
60 * @return The latitude
61 */
62 @Override
63 public double lat() {
64 return yToLat(this.y(), this.zoom());
65 }
66
67 /**
68 * Get the longitude for the upper-left corner of this tile
69 * @return The longitude
70 */
71 @Override
72 public double lon() {
73 return xToLon(this.x(), this.zoom());
74 }
75
76 /**
77 * Convert a bounds to a series of tiles that entirely cover the bounds
78 * @param minLat The minimum latitude
79 * @param minLon The minimum longitude
80 * @param maxLat The maximum latitude
81 * @param maxLon The maximum longitude
82 * @param zoom The zoom level to generate the tiles for
83 * @return The stream of tiles
84 */
85 public static Stream<TileZXY> boundsToTiles(double minLat, double minLon, double maxLat, double maxLon, int zoom) {
86 return boundsToTiles(minLat, minLon, maxLat, maxLon, zoom, 0);
87 }
88
89 /**
90 * Convert a bounds to a series of tiles that entirely cover the bounds
91 * @param minLat The minimum latitude
92 * @param minLon The minimum longitude
93 * @param maxLat The maximum latitude
94 * @param maxLon The maximum longitude
95 * @param zoom The zoom level to generate the tiles for
96 * @param expansion The number of tiles to expand on the x/y axis (1 row north, 1 row south, 1 column left, 1 column right)
97 * @return The stream of tiles
98 */
99 public static Stream<TileZXY> boundsToTiles(double minLat, double minLon, double maxLat, double maxLon, int zoom, int expansion) {
100 final TileZXY upperRight = latLonToTile(maxLat, maxLon, zoom);
101 final TileZXY lowerLeft = latLonToTile(minLat, minLon, zoom);
102 return IntStream.rangeClosed(lowerLeft.x() - expansion, upperRight.x() + expansion)
103 .mapToObj(x -> IntStream.rangeClosed(upperRight.y() - expansion, lowerLeft.y() + expansion)
104 .mapToObj(y -> new TileZXY(zoom, x, y)))
105 .flatMap(stream -> stream);
106 }
107
108 /**
109 * Convert a tile to the bounds for that tile
110 * @param tile The tile to get the bounds for
111 * @return The bounds
112 */
113 public static Bounds tileToBounds(TileZXY tile) {
114 return new Bounds(yToLat(tile.y() + 1, tile.zoom()), xToLon(tile.x(), tile.zoom()),
115 yToLat(tile.y(), tile.zoom()), xToLon(tile.x() + 1, tile.zoom()));
116 }
117
118 /**
119 * Convert a x tile coordinate to a latitude
120 * @param x The x coordinate
121 * @param zoom The zoom level to use for the calculation
122 * @return The latitude for the x coordinate (upper-left of the tile)
123 */
124 public static double xToLon(int x, int zoom) {
125 return (x / Math.pow(2, zoom)) * 360 - 180;
126 }
127
128 /**
129 * Convert a y tile coordinate to a latitude
130 * @param y The y coordinate
131 * @param zoom The zoom level to use for the calculation
132 * @return The latitude for the y coordinate (upper-left of the tile)
133 */
134 public static double yToLat(int y, int zoom) {
135 double t = Math.PI - (2 * Math.PI * y) / Math.pow(2, zoom);
136 return 180 / Math.PI * Math.atan((Math.exp(t) - Math.exp(-t)) / 2);
137 }
138
139 /**
140 * Convert a lat, lon, and zoom to a tile coordiante
141 * @param lat The latitude
142 * @param lon The longitude
143 * @param zoom The zoom level
144 * @return The specified tile coordinates at the specified zoom
145 */
146 public static TileZXY latLonToTile(double lat, double lon, int zoom) {
147 final double zoom2 = Math.pow(2, zoom);
148 final double latLog = Math.log(Math.tan(Math.toRadians(lat)) + 1 / Math.cos(Math.toRadians(lat)));
149 final int xCoord = (int) Math.floor(zoom2 * (180 + lon) / 360);
150 final int yCoord = (int) Math.floor(zoom2 * (1 - latLog / Math.PI) / 2);
151 return new TileZXY(zoom, xCoord, yCoord);
152 }
153
154 @Override
155 public String toString() {
156 return "TileZXY{" + zoom + "/" + x + "/" + y + "}";
157 }
158
159 @Override
160 public int hashCode() {
161 // We only care about comparing zoom, x, and y
162 return Integer.hashCode(this.zoom) + 31 * (Integer.hashCode(this.x) + 31 * Integer.hashCode(this.y));
163 }
164
165 @Override
166 public boolean equals(Object obj) {
167 if (obj instanceof TileZXY) {
168 TileZXY o = (TileZXY) obj;
169 return this.zoom == o.zoom && this.x == o.x && this.y == o.y;
170 }
171 return false;
172 }
173}
Note: See TracBrowser for help on using the repository browser.