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

geotrellis.raster.op.focal.MedianModeCalculation.scala Maven / Gradle / Ivy

The newest version!
package geotrellis.raster.op.focal

import geotrellis._

trait MedianModeCalculation {
  val modeValue = 0
  var currArrMax = 0

  var arr:Array[Int] = null
  var d2:Int = 0

  def initArray(extent:Int) = {
    val d = extent*2 + 1
    d2 = d*d
    arr = Array.ofDim[Int](d2)
    for(i <- 0 until arr.length) { arr(i) = NODATA }
  }

  def reset() = { 
    var i = 0
    while(i < d2) { arr(i) = NODATA ; i += 1 }
    currArrMax = 0
  }

  /** Adds a value to the internal array,
   * ordering the values. If you call addValue
   * after calling this you'll probably break the
   * ordering, so use one or the other. This one
   * is slower, according to timing data.
   */
 def addValueOrdered(v:Int) = {
    var i = 0
    var arrV = 0
    var break = false
    while(!break)
    {
      arrV = arr(i)
      if(isNoData(arrV)) {
        arr(i) = v
        currArrMax += 1
        break = true
      } else if(arrV > v) {
        var j = currArrMax
        while(j > i) {
          arr(j) = arr(j-1)
          j -= 1
        }
        arr(i) = v
        currArrMax += 1
        break = true
      }
      i += 1
    }
  }

  /** Adds a value to the internal array,
   * grouping values together but not ordering
   * them. If you call this after calling
   * addValueOrdered, you'll probably break the
   * ordering, so use one or the other. This one
   * is faster, according to timing data.
   */
  def addValue(v:Int) = {
    var i = 0
    var break = false
    while(!break)
    {
      if(isNoData(arr(i))) {
        arr(i) = v
        currArrMax += 1
        break = true
      }
      else if(arr(i) == v) {
        var j = currArrMax
        while(j > i) {
          arr(j) = arr(j-1)
          j -= 1
        }
        currArrMax += 1
        break = true
      }
      i += 1
    }
  }

  def removeValue(v:Int) = {
    var i = 0
    var break = false
    while(arr(i) != v && i < d2-1) i += 1
    if(i == d2-1) { 
      arr(i) = NODATA 
      currArrMax -= 1
    } else {
      while(!break) {
        arr(i) = arr(i+1)
        if(i == d2-2) {           
          arr(d2-1) = NODATA
          currArrMax -= 1
          break = true
        }
        i += 1
      }
    }
  }

  /** Calculates the median. If you use this,
   *  make sure you've been only calling addValueOrdered
   */
  def median = {
    if(currArrMax == 0) NODATA else {
      if(currArrMax % 2 == 0) {
       (arr(currArrMax/2) + arr(currArrMax/2-1)) / 2
      } else {
        arr(currArrMax/2)
      }
    }
  }

  /** Calculates the mode. 
   * Works with addValue or addValueOrdered
   */
  def mode = {
    var i = 1
    var m = arr(0)
    var modeCount = 1
    var curValue = m
    var curCount = 1

    var break = false
    while(!break) {
      val v = arr(i)
      if(isNoData(v)) {
        if(curCount > modeCount) {
          m = curValue
          modeCount = curCount
        }
        
        break = true
      }
        else {
          if(v == curValue) {
            curCount += 1
          } else {
            if(curCount > modeCount) {
              m = curValue
              modeCount = curCount
            }
            curValue = v
            curCount = 1
          }
          i += 1
          if(i == d2) break = true
        }
    }

    m
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy