Skip to content

Commit

Permalink
Make GeoTiffSegmentConstruct typeclass more generic
Browse files Browse the repository at this point in the history
  • Loading branch information
pomadchin committed Dec 21, 2017
1 parent f7ae421 commit 4bd54b7
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 18 deletions.
17 changes: 9 additions & 8 deletions spark/src/main/scala/geotrellis/spark/cog/COGLayer.scala
Expand Up @@ -22,6 +22,10 @@ import java.net.URI
import scala.reflect.ClassTag

object COGLayer {
/**
* Make it more generic? GeoTiffs are Iterables of (K, V)s // K - is a segment key, V - is a segment itself
* Segments are in a row major order => profit?
*/
def pyramidUp[
K: SpatialComponent: Ordering: ClassTag,
V <: CellGrid: ClassTag: ? => TileMergeMethods[V]: ? => TilePrototypeMethods[V]: ? => TileCropMethods[V]
Expand All @@ -31,7 +35,7 @@ object COGLayer {
layoutScheme: LayoutScheme,
md: TileLayerMetadata[K],
options: GeoTiffOptions
)(implicit tc: Iterable[(SpatialKey, V)] => GeoTiffSegmentConstructMethods[V]): List[GeoTiff[V]] = {
)(implicit tc: Iterable[(K, V)] => GeoTiffSegmentConstructMethods[K, V]): List[GeoTiff[V]] = {
val nextLayoutLevel @ LayoutLevel(nextZoom, nextLayout) = layoutScheme.zoomOut(layoutLevel)
if(nextZoom >= endZoom) {
val list: List[(K, V)] =
Expand All @@ -55,9 +59,7 @@ object COGLayer {
}.toList

val ifdLayer: GeoTiff[V] =
list
.map { case (key, tile) => key.getComponent[SpatialKey] -> tile }
.toGeoTiff(nextLayout, md, options.copy(subfileType = Some(ReducedImage)))
list.toGeoTiff(nextLayout, md, options.copy(subfileType = Some(ReducedImage)))

ifdLayer :: pyramidUp(list, endZoom, nextLayoutLevel, layoutScheme, md, options)
} else List()
Expand All @@ -67,7 +69,7 @@ object COGLayer {
K: SpatialComponent: Ordering: ClassTag,
V <: CellGrid: ClassTag: ? => TileMergeMethods[V]: ? => TilePrototypeMethods[V]: ? => TileCropMethods[V]
](rdd: RDD[(K, V)] with Metadata[TileLayerMetadata[K]])(startZoom: Int, endZoom: Int, layoutScheme: LayoutScheme)
(implicit tc: Iterable[(SpatialKey, V)] => GeoTiffSegmentConstructMethods[V]): RDD[(K, GeoTiff[V])] = {
(implicit tc: Iterable[(K, V)] => GeoTiffSegmentConstructMethods[K, V]): RDD[(K, GeoTiff[V])] = {
val md = rdd.metadata
val sourceLayout = md.layout
val options: GeoTiffOptions = GeoTiffOptions(storageMethod = Tiled(sourceLayout.tileCols, sourceLayout.tileRows))
Expand All @@ -88,6 +90,7 @@ object COGLayer {
groupedByEndZoom
.repartition(groupedPartitions)
.mapPartitions { partition: Iterator[(K, (Iterable[(K, V)]))] =>
// TODO: refactor, so ugly
val list = partition.toList
val flatList = list.flatMap(_._2)

Expand All @@ -98,9 +101,7 @@ object COGLayer {
pyramidUp[K, V](flatList, endZoom, LayoutLevel(startZoom, sourceLayout), layoutScheme, md, options.copy(subfileType = Some(ReducedImage)))

val stitchedTile: GeoTiff[V] =
flatList
.map { case (key, tile) => key.getComponent[SpatialKey] -> tile }
.toGeoTiff(sourceLayout, md, options, overviews)
flatList.toGeoTiff(sourceLayout, md, options, overviews)

Iterator(sfc -> stitchedTile)
} else Iterator()
Expand Down
Expand Up @@ -4,12 +4,13 @@ import geotrellis.raster.io.geotiff._
import geotrellis.raster._
import geotrellis.spark._
import geotrellis.spark.tiling._
import geotrellis.util.MethodExtensions
import geotrellis.util._

trait GeoTiffSegmentConstructMethods[T <: CellGrid] extends MethodExtensions[Iterable[(SpatialKey, T)]] {
lazy val gb: GridBounds = GridBounds.envelope(self.map(_._1))
trait GeoTiffSegmentConstructMethods[K, T <: CellGrid] extends MethodExtensions[Iterable[(K, T)]] {
implicit val spatialComponent: SpatialComponent[K]
lazy val gb: GridBounds = GridBounds.envelope(self.map(_._1.getComponent[SpatialKey]))

def toGeoTiff[K](
def toGeoTiff(
nextLayout: LayoutDefinition,
md: TileLayerMetadata[K],
options: GeoTiffOptions,
Expand Down
20 changes: 14 additions & 6 deletions spark/src/main/scala/geotrellis/spark/cog/Implicits.scala
Expand Up @@ -5,11 +5,13 @@ import geotrellis.raster.crop._
import geotrellis.raster.io.geotiff._
import geotrellis.spark._
import geotrellis.spark.tiling._
import geotrellis.util._

import spire.syntax.cfor._

object Implicits extends Implicits

// TODO: remove asInstanceOf casts
trait Implicits {
implicit class withSinglebandGeoTiffConstructMethods(val self: Tile) extends GeoTiffConstructMethods[Tile] {
def toGeoTiff[K](
Expand Down Expand Up @@ -49,8 +51,10 @@ trait Implicits {
}
}

implicit class withSinglebandGeoTiffSegmentConstructMethods(val self: Iterable[(SpatialKey, Tile)]) extends GeoTiffSegmentConstructMethods[Tile] {
def toGeoTiff[K](
implicit class withSinglebandGeoTiffSegmentConstructMethods[K](val self: Iterable[(K, Tile)])
(implicit val spatialComponent: SpatialComponent[K]) extends GeoTiffSegmentConstructMethods[K, Tile] {
// TODO: consider moving this code somewhere else, it's in fact a bit modified GeoTiffTile.apply function code
def toGeoTiff(
nextLayout: LayoutDefinition,
md: TileLayerMetadata[K],
options: GeoTiffOptions,
Expand All @@ -66,7 +70,8 @@ trait Implicits {

val segments: Map[Int, Array[Byte]] =
self
.map { case (spatialKey, tile) =>
.map { case (key, tile) =>
val spatialKey = key.getComponent[SpatialKey]
val updateCol = (spatialKey.col - gb.colMin) * md.tileLayout.tileCols
val updateRow = (spatialKey.row - gb.rowMin) * md.tileLayout.tileRows
val index = segmentLayout.getSegmentIndex(updateCol, updateRow)
Expand Down Expand Up @@ -97,8 +102,10 @@ trait Implicits {
}
}

implicit class withMultibandGeoTiffSegmentConstructMethods(val self: Iterable[(SpatialKey, MultibandTile)]) extends GeoTiffSegmentConstructMethods[MultibandTile] {
def toGeoTiff[K](
implicit class withMultibandGeoTiffSegmentConstructMethods[K](val self: Iterable[(K, MultibandTile)])
(implicit val spatialComponent: SpatialComponent[K]) extends GeoTiffSegmentConstructMethods[K, MultibandTile] {
// TODO: consider moving this code somewhere else, it's in fact a bit modified GeoTiffMultibandTile.apply function code
def toGeoTiff(
nextLayout: LayoutDefinition,
md: TileLayerMetadata[K],
options: GeoTiffOptions,
Expand All @@ -123,7 +130,8 @@ trait Implicits {
cfor(0)(_ < bandCount, _ + 1) { bandIndex =>
val bandTiles =
self
.map { case (spatialKey, tile) =>
.map { case (key, tile) =>
val spatialKey = key.getComponent[SpatialKey]
val updateCol = (spatialKey.col - gb.colMin) * md.tileLayout.tileCols
val updateRow = (spatialKey.row - gb.rowMin) * md.tileLayout.tileRows
val index = segmentLayout.getSegmentIndex(updateCol, updateRow)
Expand Down

0 comments on commit 4bd54b7

Please sign in to comment.