/* Copyright 2013 The jeo project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.jeo.tile;
import io.jeo.data.Cursor;
import java.io.IOException;
/**
* A rectangular two dimensional coverage of tile objects.
*
* @author Justin Deoliveira, OpenGeo
*/
public class TileCover {
TileGrid grid;
int x0,x1,y0,y1;
Tile[][] tiles;
/**
* Creates a new tile cover.
*
* @param grid The tile grid specifying the zoom level at which the cover exists.
* @param x0 The horizontal index of the leftmost tile in the coverage.
* @param y0 The vertical index of the bottommost tile in the coverage.
* @param x1 The horizontal index of the rightmost tile in the coverage.
* @param y1 The vertical index of the rightmost tile in the coverage.
*/
public TileCover(TileGrid grid, int x0, int y0, int x1, int y1) {
this.grid = grid;
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
tiles = new Tile[width()][height()];
}
/**
* The grid / zoom level at which the coverage occurs.
*/
public TileGrid grid() {
return grid;
}
/**
* Horizontal index of the leftmost tile in the coverage.
*/
public int x0() {
return x0;
}
/**
* Horizontal index of the rightmost tile in the coverage.
*/
public int x1() {
return x1;
}
/**
* Vertical index of the bottommost tile in the coverage.
*/
public int y0() {
return y0;
}
/**
* Vertical index of the rightmost tile in the coverage.
*/
public int y1() {
return y1;
}
/**
* The number of tiles horizontally in the coverage.
*/
public int width() {
return x1 - x0 + 1;
}
/**
* The number of tiles vertically in the coverage.
*/
public int height() {
return y1 - y0 + 1;
}
/**
* Obtains the cursor for this cover from a tile set.
*
* @param tileset The tile source.
*/
public Cursor<Tile> cursor(TileDataset tileset) throws IOException {
return tileset.read(grid.z(), grid.z(), x0, x1, y0, y1);
}
/**
* Pulls all the tiles for the cover from the specified tile source.
*
* @param tileset The tile source.
*/
public void fill(TileDataset tileset) throws IOException {
try (Cursor<Tile> cursor = cursor(tileset)) {
while (cursor.hasNext()) {
Tile t = cursor.next();
tiles[t.x()-x0][t.y()-y0] = t;
}
}
}
/**
* Returns a tile at the specified offsets into the coverage.
* <p>
* The {@link #fill(TileDataset)} method must be called before this method is called. The <tt>x</tt>
* and <tt>y</tt> values are specified relative to the lower left corner of the tile cover.
* Meaning x = 0, y = 0 is the most lower left tile in ths cover.
* </p>
*/
public Tile tile(int x, int y) {
Tile t = tiles[x][y];
if (t == null) {
// "blank" tile
t = new Tile(grid.z(), x0 + x, y0 + y, null, null);
}
return t;
}
@Override
public String toString() {
return new StringBuilder().append(grid.z()).append(": ")
.append(x0).append(",").append(y0).append(" - ").append(x1).append(",").append(y1)
.toString();
}
}