All Downloads are FREE. Search and download functionalities are using the official Maven repository.

geotrellis.CroppedRaster.scala Maven / Gradle / Ivy

The newest version!
package geotrellis

import geotrellis.raster._
import spire.syntax.cfor._
import scala.collection.mutable

object CroppedRaster {
  def apply(sourceRaster:Raster,gridBounds:GridBounds):CroppedRaster = 
    CroppedRaster(sourceRaster,gridBounds,sourceRaster.rasterExtent.extentFor(gridBounds))
  def apply(sourceRaster:Raster,extent:Extent):CroppedRaster =
    CroppedRaster(sourceRaster,sourceRaster.rasterExtent.gridBoundsFor(extent),extent)
}

case class CroppedRaster(sourceRaster:Raster,
                         gridBounds:GridBounds,
                         extent:Extent) 
  extends Raster {
  val rasterExtent = RasterExtent(extent,
                                  sourceRaster.rasterExtent.cellwidth,
                                  sourceRaster.rasterExtent.cellheight,
                                  gridBounds.width,
                                  gridBounds.height)
  def force = toArrayRaster
  val rasterType = sourceRaster.rasterType

  private val colMin = gridBounds.colMin
  private val rowMin = gridBounds.rowMin
  private val sourceCols = sourceRaster.rasterExtent.cols
  private val sourceRows = sourceRaster.rasterExtent.rows

  def warp(target:RasterExtent) = toArrayRaster.warp(target)

  def get(col: Int,row: Int): Int = {
    val c = col+gridBounds.colMin
    val r = row+gridBounds.rowMin
    if(c < 0 || r < 0 || c >= sourceCols || r >= sourceRows) {
      NODATA
    } else {
      sourceRaster.get(c,r)
    }
  }
  def getDouble(col: Int,row: Int): Double = {
    val c = col+gridBounds.colMin
    val r = row+gridBounds.rowMin

    if(c < 0 || r < 0 || c >= sourceCols || r >= sourceRows) {
      Double.NaN
    } else {
      sourceRaster.getDouble(col+gridBounds.colMin,row+gridBounds.rowMin)
    }
  }

  def toArrayRaster:ArrayRaster = {
    val data = RasterData.allocByType(rasterType,cols,rows)
    if(!isFloat) {
      cfor(0)(_ < rows, _ + 1) { row =>
        cfor(0)(_ < cols, _ + 1) { col =>
          data.set(col, row, get(col,row))
        }
      }
    } else {
      cfor(0)(_ < rows, _ + 1) { row =>
        cfor(0)(_ < cols, _ + 1) { col =>
          data.setDouble(col, row, getDouble(col,row))
        }
      }
    }
    ArrayRaster(data,rasterExtent)
  }

  def toArray: Array[Int] = {
    val arr = Array.ofDim[Int](rasterExtent.cols*rasterExtent.rows)
    var i = 0
    cfor(0)(_ < rows, _ + 1) { row =>
      cfor(0)(_ < cols, _ + 1) { col =>
        arr(i) = get(col,row)
        i += 1
      }
    }
    arr
  }

  def toArrayDouble: Array[Double] = {
    val arr = Array.ofDim[Double](rasterExtent.cols*rasterExtent.rows)
    var i = 0
    cfor(0)(_ < rows, _ + 1) { row =>
      cfor(0)(_ < cols, _ + 1) { col =>
        arr(i) = getDouble(col,row)
        i += 1
      }
    }
    arr
  }

  def toArrayByte(): Array[Byte] = toArrayRaster.toArrayByte

  def copy() = 
    if(isFloat) {
      Raster(toArray,rasterExtent) 
    } else {
      Raster(toArrayDouble,rasterExtent)
    }

  def convert(typ: RasterType):Raster = 
    sourceRaster.convert(typ)

  def map(f: Int => Int): Raster = {
    val data = RasterData.allocByType(rasterType,cols,rows)
    cfor(0)(_ < rows, _ + 1) { row =>
      cfor(0)(_ < cols, _ + 1) { col =>
        data.set(col,row, get(col,row))
      }
    }
    ArrayRaster(data,rasterExtent)
  }

  def combine(r2:Raster)(f:(Int, Int) => Int):Raster = {
    if(this.rasterExtent != r2.rasterExtent) {
      throw new GeoAttrsError("Cannot combine rasters with different raster extents." +
                             s"$rasterExtent does not match ${r2.rasterExtent}")
    }
    val data = RasterData.allocByType(rasterType,cols,rows)
    cfor(0)(_ < rows, _ + 1) { row =>
      cfor(0)(_ < cols, _ + 1) { col =>
        data.set(col,row, f(get(col,row),r2.get(col,row)))
      }
    }
    Raster(data,rasterExtent)
  }

  def mapDouble(f:Double =>Double):Raster = {
    val data = RasterData.allocByType(rasterType,cols,rows)
    cfor(0)(_ < rows, _ + 1) { row =>
      cfor(0)(_ < cols, _ + 1) { col =>
        data.setDouble(col,row, getDouble(col,row))
      }
    }
    ArrayRaster(data,rasterExtent)
  }

  def combineDouble(r2:Raster)(f:(Double, Double) => Double):Raster = {
    if(this.rasterExtent != r2.rasterExtent) {
      throw new GeoAttrsError("Cannot combine rasters with different raster extents." +
                             s"$rasterExtent does not match ${r2.rasterExtent}")
    }
    val data = RasterData.allocByType(rasterType,cols,rows)
    cfor(0)(_ < rows, _ + 1) { row =>
      cfor(0)(_ < cols, _ + 1) { col =>
        data.setDouble(col,row, f(getDouble(col,row),r2.getDouble(col,row)))
      }
    }
    Raster(data,rasterExtent)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy