source: josm/trunk/src/org/openstreetmap/josm/data/imagery/AbstractWMSTileSource.java@ 10990

Last change on this file since 10990 was 10990, checked in by wiktorn, 8 years ago

Small refactor of WMS TileSource

  • Introduce AbstractWMSTileSource, which will be a base class for WMSEndpointTileSource
  • remove getHeaders() from WMSLayer, super method is already good enough
  • Property svn:eol-style set to native
File size: 6.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.imagery;
3
4import java.awt.Point;
5
6import org.openstreetmap.gui.jmapviewer.Tile;
7import org.openstreetmap.gui.jmapviewer.TileXY;
8import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
9import org.openstreetmap.gui.jmapviewer.tilesources.TMSTileSource;
10import org.openstreetmap.gui.jmapviewer.tilesources.TileSourceInfo;
11import org.openstreetmap.josm.Main;
12import org.openstreetmap.josm.data.Bounds;
13import org.openstreetmap.josm.data.ProjectionBounds;
14import org.openstreetmap.josm.data.coor.EastNorth;
15import org.openstreetmap.josm.data.coor.LatLon;
16import org.openstreetmap.josm.data.projection.Projection;
17
18/**
19 * Base class for different WMS tile sources those based on URL templates and those based on WMS endpoints
20 * @author Wiktor Niesiobędzki
21 * @since 10990
22 *
23 */
24public class AbstractWMSTileSource extends TMSTileSource {
25
26 private EastNorth anchorPosition;
27 private int[] tileXMin;
28 private int[] tileYMin;
29 private int[] tileXMax;
30 private int[] tileYMax;
31 private double[] degreesPerTile;
32 private static final float SCALE_DENOMINATOR_ZOOM_LEVEL_1 = 559082264.0287178f;
33
34 public AbstractWMSTileSource(TileSourceInfo info) {
35 super(info);
36 }
37
38 /**
39 * Initializes class with current projection in JOSM. This call is needed every time projection changes.
40 */
41 public void initProjection() {
42 initProjection(Main.getProjection());
43 }
44
45 private void initAnchorPosition(Projection proj) {
46 Bounds worldBounds = proj.getWorldBoundsLatLon();
47 EastNorth min = proj.latlon2eastNorth(worldBounds.getMin());
48 EastNorth max = proj.latlon2eastNorth(worldBounds.getMax());
49 this.anchorPosition = new EastNorth(min.east(), max.north());
50 }
51
52 /**
53 * Initializes class with projection in JOSM. This call is needed every time projection changes.
54 * @param proj new projection that shall be used for computations
55 */
56 public void initProjection(Projection proj) {
57 initAnchorPosition(proj);
58 ProjectionBounds worldBounds = proj.getWorldBoundsBoxEastNorth();
59
60 EastNorth topLeft = new EastNorth(worldBounds.getMin().east(), worldBounds.getMax().north());
61 EastNorth bottomRight = new EastNorth(worldBounds.getMax().east(), worldBounds.getMin().north());
62
63 // use 256 as "tile size" to keep the scale in line with default tiles in Mercator projection
64 double crsScale = 256 * 0.28e-03 / proj.getMetersPerUnit();
65 tileXMin = new int[getMaxZoom() + 1];
66 tileYMin = new int[getMaxZoom() + 1];
67 tileXMax = new int[getMaxZoom() + 1];
68 tileYMax = new int[getMaxZoom() + 1];
69 degreesPerTile = new double[getMaxZoom() + 1];
70
71 for (int zoom = 1; zoom <= getMaxZoom(); zoom++) {
72 // use well known scale set "GoogleCompatibile" from OGC WMTS spec to calculate number of tiles per zoom level
73 // this makes the zoom levels "glued" to standard TMS zoom levels
74 degreesPerTile[zoom] = (SCALE_DENOMINATOR_ZOOM_LEVEL_1 / Math.pow(2d, zoom - 1d)) * crsScale;
75 TileXY minTileIndex = eastNorthToTileXY(topLeft, zoom);
76 tileXMin[zoom] = minTileIndex.getXIndex();
77 tileYMin[zoom] = minTileIndex.getYIndex();
78 TileXY maxTileIndex = eastNorthToTileXY(bottomRight, zoom);
79 tileXMax[zoom] = maxTileIndex.getXIndex();
80 tileYMax[zoom] = maxTileIndex.getYIndex();
81 }
82 }
83
84 @Override
85 public ICoordinate tileXYToLatLon(Tile tile) {
86 return tileXYToLatLon(tile.getXtile(), tile.getYtile(), tile.getZoom());
87 }
88
89 @Override
90 public ICoordinate tileXYToLatLon(TileXY xy, int zoom) {
91 return tileXYToLatLon(xy.getXIndex(), xy.getYIndex(), zoom);
92 }
93
94 @Override
95 public ICoordinate tileXYToLatLon(int x, int y, int zoom) {
96 return Main.getProjection().eastNorth2latlon(getTileEastNorth(x, y, zoom)).toCoordinate();
97 }
98
99 @Override
100 public TileXY latLonToTileXY(double lat, double lon, int zoom) {
101 Projection proj = Main.getProjection();
102 EastNorth enPoint = proj.latlon2eastNorth(new LatLon(lat, lon));
103 return eastNorthToTileXY(enPoint, zoom);
104 }
105
106 private TileXY eastNorthToTileXY(EastNorth enPoint, int zoom) {
107 double scale = getDegreesPerTile(zoom);
108 return new TileXY(
109 (enPoint.east() - anchorPosition.east()) / scale,
110 (anchorPosition.north() - enPoint.north()) / scale
111 );
112 }
113
114 @Override
115 public TileXY latLonToTileXY(ICoordinate point, int zoom) {
116 return latLonToTileXY(point.getLat(), point.getLon(), zoom);
117 }
118
119 @Override
120 public int getTileXMax(int zoom) {
121 return tileXMax[zoom];
122 }
123
124 @Override
125 public int getTileXMin(int zoom) {
126 return tileXMin[zoom];
127 }
128
129 @Override
130 public int getTileYMax(int zoom) {
131 return tileYMax[zoom];
132 }
133
134 @Override
135 public int getTileYMin(int zoom) {
136 return tileYMin[zoom];
137 }
138
139 @Override
140 public Point latLonToXY(double lat, double lon, int zoom) {
141 double scale = getDegreesPerTile(zoom) / getTileSize();
142 EastNorth point = Main.getProjection().latlon2eastNorth(new LatLon(lat, lon));
143 return new Point(
144 (int) Math.round((point.east() - anchorPosition.east()) / scale),
145 (int) Math.round((anchorPosition.north() - point.north()) / scale)
146 );
147 }
148
149 @Override
150 public Point latLonToXY(ICoordinate point, int zoom) {
151 return latLonToXY(point.getLat(), point.getLon(), zoom);
152 }
153
154 @Override
155 public ICoordinate xyToLatLon(Point point, int zoom) {
156 return xyToLatLon(point.x, point.y, zoom);
157 }
158
159 @Override
160 public ICoordinate xyToLatLon(int x, int y, int zoom) {
161 double scale = getDegreesPerTile(zoom) / getTileSize();
162 Projection proj = Main.getProjection();
163 EastNorth ret = new EastNorth(
164 anchorPosition.east() + x * scale,
165 anchorPosition.north() - y * scale
166 );
167 return proj.eastNorth2latlon(ret).toCoordinate();
168 }
169
170 protected EastNorth getTileEastNorth(int x, int y, int z) {
171 double scale = getDegreesPerTile(z);
172 return new EastNorth(
173 anchorPosition.east() + x * scale,
174 anchorPosition.north() - y * scale
175 );
176 }
177
178 private double getDegreesPerTile(int zoom) {
179 return degreesPerTile[zoom];
180 }
181
182}
Note: See TracBrowser for help on using the repository browser.