Tiles
The Tile interface is the central representational structure for raster information.
Among the most common implementations of Tile is the ArrayTile, so named because it is backed by a normal JVM array. The examples in this document use an ArrayTile but should be illustrative of the Tile API more generally. In addition to the array of raw data, an ArrayTile must know how many columns and rows there are so that it can properly interpret (x, y) indices as positions within its one-dimensional, backing array.
Creating a Tile
A 10x10 Tile backed by an array of Ints, is created to be used in the examples below:
import geotrellis.raster._
val rawData = 1 to 100 toArray
val cols = 10
val rows = 10
val tile100 = ArrayTile(rawData, cols, rows)
Tile Proportions
As mentioned above, each Tile must track its own shape. This information is available on the tile instance:
tile100.cols
// res0: Int = 10
tile100.rows
// res1: Int = 10
tile100.dimensions
// res2: Dimensions[Int] = Dimensions(10, 10)
Data Types
The data type of tiles is represented by a CellType. Each CellType defines
- Bit Width - how much memory per cell of data?
- Floating Point? (predicate) - is each cell floating point or integral?
- NoData Value - the sentinel value or lack thereof which signifies a lack of data and which should not be used most calculations
Accessing a tile's CellType relatively simple:
tile100.cellType
// res3: IntConstantNoDataCellType.type = int32
If a Tile's CellType is incorrect, there are a couple of options for resolving the matter.
// Here's an integer celltype with a 'NoData' value of 55
val ct = IntUserDefinedNoDataCellType(55)
// If the underlying data is correct but the celltype is mislabelled:
val interpreted = tile100.interpretAs(ct)
// If the underlying data should be converted to a new celltype
val converted = tile100.convert(ct)
interpreted.cellType
// res4: CellType = IntUserDefinedNoDataCellType(55)
converted.cellType
// res5: CellType = IntUserDefinedNoDataCellType(55)
Accessing Tile values
Retrieval of values from within a tile is relatively simple though performance considerations on the JVM introduce some complexity. To avoid potential slowdowns in code that iterates through a Tile - potentially retrieving thousands or tens of thousands of values - GeoTrellis had to keep the methods for returning Int (integral values) and Double (floating point values) separate. The naming convention used throughout GeoTrellis is <func> for the Int case and <func>Double for Doubles
Individual Values
Accessing a single value with get
tile100.get(5, 5)
// res6: Int = 56
tile100.getDouble(5, 5)
// res7: Double = 56.0
Iterating Through Cell Values
Applying a side-effecting function to each cell's value:
val feInt = { i: Int => println(i) }
val feDbl = { i: Double => println(i) }
tile100.foreach(feInt)
tile100.foreachDouble(feDbl)
Transform a tile with any Int => Int or Double => Double function:
val mapInt = { i: Int => i + 1 }
val mapDbl = { i: Double => i + 1 }
tile100.map(mapInt)
tile100.mapDouble(mapDbl)