Skip to content

Commit 0b5496f

Browse files
committed
Add tiles around point to tile module
1 parent 39a94e4 commit 0b5496f

File tree

9 files changed

+140
-1
lines changed

9 files changed

+140
-1
lines changed

examples/tile_map_at_point.groovy

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import geoscript.geom.Geometry
2+
import geoscript.geom.Point
3+
import geoscript.layer.OSM
4+
import geoscript.layer.Raster
5+
import geoscript.proj.Projection
6+
import javax.imageio.ImageIO
7+
8+
OSM osm = new OSM()
9+
10+
[
11+
"POINT (-100.777587890625 46.800059446787316)",
12+
"POINT (-122.38494873046875 47.570966845786124)",
13+
"POINT (12.5244140625 42.032974332441405)",
14+
"POINT (23.752441406249996 38.004819966413194)"
15+
].eachWithIndex { String wkt, int i ->
16+
[1,4,8,16].each {int z ->
17+
Raster raster = osm.getRaster(Projection.transform(Geometry.fromWKT(wkt), "EPSG:4326", "EPSG:3857") as Point, z, 400, 400)
18+
ImageIO.write(raster.image, "png", new File("map_at_point_${i}_${z}.png"))
19+
}
20+
}

src/main/groovy/geoscript/layer/ImageTileLayer.groovy

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package geoscript.layer
22

33
import geoscript.geom.Bounds
4+
import geoscript.geom.Point
45
import geoscript.style.RasterSymbolizer
56
import org.geotools.map.GridCoverageLayer
67

@@ -71,6 +72,18 @@ abstract class ImageTileLayer extends TileLayer<ImageTile> implements Renderable
7172
}
7273
}
7374

75+
/**
76+
* Get a Raster around a Point at a given zoom level
77+
* @param p The Point (in the TileLayer's projection)
78+
* @param z The zoom level
79+
* @param w The image width
80+
* @param h The image height
81+
* @return A Raster
82+
*/
83+
Raster getRaster(Point p, long z, int w, int h) {
84+
getRaster(this.pyramid.bounds(p, z, w, h), w, h)
85+
}
86+
7487
@Override
7588
List<org.geotools.map.Layer> getMapLayers(Bounds bounds, List size) {
7689
def raster = this.getRaster(bounds.reproject(this.proj), size[0], size[1])

src/main/groovy/geoscript/layer/Pyramid.groovy

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package geoscript.layer
22

33
import geoscript.geom.Bounds
4+
import geoscript.geom.Point
45
import geoscript.layer.io.PyramidReader
56
import geoscript.layer.io.PyramidReaders
67
import geoscript.proj.Projection
@@ -115,6 +116,21 @@ class Pyramid {
115116
grids.min { Grid g -> g.z }
116117
}
117118

119+
/**
120+
* Find the Bounds around a Point at a given zoom level for a canvas of a given width and height
121+
* @param p The Point (in the Pyramid's projection)
122+
* @param z The zoom level
123+
* @param width The canvas width
124+
* @param height The canvas height
125+
* @return a Bounds
126+
*/
127+
Bounds bounds(Point p, long z, int width, int height) {
128+
Grid g = grid(z)
129+
double boundsWidth = g.xResolution * width
130+
double boundsHeight = g.yResolution * height
131+
new Bounds(p.x - boundsWidth / 2, p.y - boundsHeight / 2, p.x + boundsWidth / 2, p.y + boundsHeight / 2, this.proj)
132+
}
133+
118134
/**
119135
* Calculate the Bounds for the given Tile
120136
* @param t The Tile

src/main/groovy/geoscript/layer/TileCursor.groovy

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package geoscript.layer
22

33
import geoscript.geom.Bounds
4+
import geoscript.geom.Point
45
import org.geotools.util.logging.Logging
56
import java.util.logging.Logger
67

@@ -221,6 +222,20 @@ class TileCursor<T extends Tile> implements Iterator {
221222
}
222223
}
223224

225+
/**
226+
* Create a TileCursor for all Tiles centered on a Point for a given zoom level that fill an image of
227+
* a certain width and height
228+
* @param layer The TileLayer
229+
* @param p The Point (in the TileLayer's Projection)
230+
* @param z The zoom level
231+
* @param w The image width
232+
* @param h The image height
233+
* @return A TileCursor
234+
*/
235+
TileCursor(TileLayer layer, Point p, long z, int w, int h) {
236+
this(layer, layer.pyramid.bounds(p, z, w, h), z)
237+
}
238+
224239
/**
225240
* Validate number parameters passed into the TileCursor constructor
226241
* @param num The number value

src/main/groovy/geoscript/layer/TileLayer.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package geoscript.layer
22

33
import geoscript.feature.Field
44
import geoscript.geom.Bounds
5+
import geoscript.geom.Point
56
import geoscript.proj.Projection
67
import geoscript.workspace.Memory
78
import geoscript.workspace.Workspace
@@ -113,6 +114,19 @@ abstract class TileLayer<T extends Tile> implements Closeable {
113114
new TileCursor(this, b, w, h)
114115
}
115116

117+
/**
118+
* Get a TileCursor for all Tiles centered on a Point for a given zoom level that fill an image of
119+
* a certain width and height
120+
* @param p The Point (in the TileLayer's Projection)
121+
* @param z The zoom level
122+
* @param w The image width
123+
* @param h The image height
124+
* @return A TileCursor
125+
*/
126+
TileCursor<T> tiles(Point p, long z, int w, int h) {
127+
new TileCursor(this, p, z, w, h)
128+
}
129+
116130
/**
117131
* Delete all of the Tiles in the TileCursor
118132
* @param tiles The TileCursor

src/test/groovy/geoscript/layer/PyramidTestCase.groovy

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package geoscript.layer
22

33
import geoscript.geom.Bounds
4+
import geoscript.geom.Point
45
import geoscript.proj.Projection
56
import org.junit.Rule
67
import org.junit.Test
@@ -98,6 +99,14 @@ class PyramidTestCase {
9899
assertEquals(b1, b2)
99100
}
100101

102+
@Test
103+
void osmBoundsAroundPoint() {
104+
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()
105+
pyramid.origin = Pyramid.Origin.TOP_LEFT
106+
Bounds bounds = pyramid.bounds(Projection.transform(new Point(-100.81,46.81),"EPSG:4326","EPSG:3857"), 8, 400, 300)
107+
assertEquals(new Bounds(-1.1344314741869908E7,5819468.535791107,-1.1099920991869908E7,6002763.848291107, "EPSG:3857"), bounds)
108+
}
109+
101110
@Test
102111
void getTileCoordinates() {
103112
Pyramid pyramid = Pyramid.createGlobalMercatorPyramid()

src/test/groovy/geoscript/layer/TileCursorTestCase.groovy

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package geoscript.layer
22

33
import geoscript.geom.Bounds
4+
import geoscript.geom.Point
5+
import geoscript.proj.Projection
46
import org.junit.Test
5-
67
import static org.junit.Assert.*
78

89
/**
@@ -135,6 +136,22 @@ class TileCursorTestCase {
135136
assertNotNull cursorBounds.proj
136137
}
137138

139+
@Test
140+
void boundsAroundPoint() {
141+
File file = new File(getClass().getClassLoader().getResource("states.mbtiles").toURI())
142+
MBTiles layer = new MBTiles(file)
143+
TileCursor cursor = new TileCursor(layer, Projection.transform(new Point(-100.81,46.81),"EPSG:4326","EPSG:3857"), 8, 400, 300)
144+
assertEquals(8, cursor.z)
145+
assertEquals(55, cursor.minX)
146+
assertEquals(165, cursor.minY)
147+
assertEquals(57, cursor.maxX)
148+
assertEquals(166, cursor.maxY)
149+
assertEquals(3, cursor.width)
150+
assertEquals(2, cursor.height)
151+
assertEquals(6, cursor.size)
152+
layer.close()
153+
}
154+
138155
@Test
139156
void resetAfterHasNextFalse() {
140157
File file = new File(getClass().getClassLoader().getResource("states.mbtiles").toURI())

src/test/groovy/geoscript/layer/TileLayerTestCase.groovy

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ package geoscript.layer
22

33
import geoscript.feature.Feature
44
import geoscript.geom.Bounds
5+
import geoscript.geom.Point
56
import geoscript.proj.Projection
67
import org.geotools.image.test.ImageAssert
78
import org.junit.Rule
89
import org.junit.Test
910
import org.junit.rules.TemporaryFolder
1011

12+
import javax.imageio.ImageIO
13+
1114
import static junit.framework.Assert.*
1215

1316
/**
@@ -224,6 +227,22 @@ class TileLayerTestCase {
224227
layer.close()
225228
}
226229

230+
@Test
231+
void boundsAroundPoint() {
232+
File file = new File(getClass().getClassLoader().getResource("states.mbtiles").toURI())
233+
MBTiles layer = new MBTiles(file)
234+
TileCursor cursor = layer.tiles(Projection.transform(new Point(-100.81,46.81),"EPSG:4326","EPSG:3857"), 8, 400, 300)
235+
assertEquals(8, cursor.z)
236+
assertEquals(55, cursor.minX)
237+
assertEquals(165, cursor.minY)
238+
assertEquals(57, cursor.maxX)
239+
assertEquals(166, cursor.maxY)
240+
assertEquals(3, cursor.width)
241+
assertEquals(2, cursor.height)
242+
assertEquals(6, cursor.size)
243+
layer.close()
244+
}
245+
227246
@Test
228247
void getRaster() {
229248
File file = new File(getClass().getClassLoader().getResource("states.mbtiles").toURI())
@@ -256,6 +275,22 @@ class TileLayerTestCase {
256275
layer.close()
257276
}
258277

278+
@Test
279+
void getRasterAroundPoint() {
280+
File file = new File(getClass().getClassLoader().getResource("states.mbtiles").toURI())
281+
MBTiles layer = new MBTiles(file)
282+
Point point = Projection.transform(new Point(-100.81,46.81),"EPSG:4326","EPSG:3857")
283+
Raster raster = layer.getRaster(point, 4, 300, 200)
284+
assertNotNull raster
285+
ImageAssert.assertEquals(new File(getClass().getClassLoader().getResource("geoscript/layer/tilelayer_raster_point.png").toURI()), raster.image, 100)
286+
File out = folder.newFile("raster.png")
287+
WorldImage format = new WorldImage(out)
288+
format.write(raster)
289+
assertTrue out.exists()
290+
assertTrue out.length() > 0
291+
layer.close()
292+
}
293+
259294
@Test
260295
void getLayer() {
261296
File file = new File(getClass().getClassLoader().getResource("states.mbtiles").toURI())
5.66 KB
Loading

0 commit comments

Comments
 (0)