Skip to content

Commit

Permalink
Other Changes
Browse files Browse the repository at this point in the history
Signed-off-by: James McClain <jmcclain@azavea.com>
  • Loading branch information
James McClain committed Mar 27, 2017
1 parent 6abd338 commit 91777a6
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 32 deletions.
Expand Up @@ -64,16 +64,16 @@ object SimpleCostDistance {
/**
* Generate a cost-distance raster based on a set of starting
* points and a friction raster. This is an implementation of the
* standard algorithm mentioned in the "previous work" section of [1].
* standard algorithm cited in the "previous work" section of [1].
*
* 1. Tomlin, Dana.
* "Propagating radial waves of travel cost in a grid."
* International Journal of Geographical Information Science 24.9 (2010): 1391-1413.
*
* @param friction Friction tile; pixels are interpreted as "second per meter"
* @param points List of starting points as tuples
* @param maxCost The maximum cost before pruning a path (in units of "seconds")
* @param resolution The resolution of the tiles (in units of "meters per pixel")
* @param frictionTile Friction tile; pixels are interpreted as "second per meter"
* @param points List of starting points as tuples
* @param maxCost The maximum cost before pruning a path (in units of "seconds")
* @param resolution The resolution of the tiles (in units of "meters per pixel")
*/
def apply(
frictionTile: Tile,
Expand All @@ -86,10 +86,12 @@ object SimpleCostDistance {
val costTile = generateEmptyCostTile(cols, rows)
val q: Q = generateEmptyQueue(cols, rows)

points.foreach({ case (col, row) =>
var i = 0; while (i < points.length) {
val (col, row) = points(i)
val entry = (col, row, frictionTile.getDouble(col, row), 0.0)
q.add(entry)
})
i += 1
}

compute(frictionTile, costTile, maxCost, resolution, q, nop)
}
Expand Down Expand Up @@ -133,6 +135,7 @@ object SimpleCostDistance {
* @param col The column of the given location
* @param row The row of the given location
* @param friction1 The instantaneous cost (friction) at the neighboring location
* @param neighborCost The cost of the neighbor
* @param cost The length of the best-known path from a source to the neighboring location
* @param distance The distance from the neighboring location to this location
*/
Expand All @@ -149,12 +152,12 @@ object SimpleCostDistance {
if (isPassable(friction2)) {
val step = resolution * distance * (friction1 + friction2) / 2.0
val candidateCost = neighborCost + step
val entry = (col, row, friction2, candidateCost)

// ... and the candidate cost is less than the maximum cost ...
if (candidateCost <= maxCost) {
// ... and the candidate is a possible improvement ...
if (!isData(currentCost) || candidateCost < currentCost) {
val entry = (col, row, friction2, candidateCost)
costTile.setDouble(col, row, candidateCost) // then increase lower bound on pixel,
q.add(entry) // and enqueue candidate for future processing
}
Expand All @@ -165,10 +168,6 @@ object SimpleCostDistance {

/**
* Process the candidate path on the top of the queue.
*
* @param frictionTile The friction tile
* @param costTile The cost tile
* @param q The priority queue of candidate paths
*/
def processNext(): Unit = {
val entry: Cost = q.poll
Expand Down
Expand Up @@ -79,9 +79,7 @@ object IterativeCostDistance {
) = {
val md = friction.metadata
val mt = md.mapTransform
val kv = friction.first
val key = implicitly[SpatialKey](kv._1)
val tile = implicitly[Tile](kv._2)
val (key: SpatialKey, tile: Tile) = friction.first
val extent = mt(key).reproject(md.crs, LatLng)
val degrees = extent.xmax - extent.xmin
val meters = degrees * (6378137 * 2.0 * math.Pi) / 360.0
Expand Down Expand Up @@ -115,7 +113,6 @@ object IterativeCostDistance {
.flatMap({ g => geometryToKeys(md, g).map({ k => (k, g) }) })
.groupBy(_._1)
.mapValues({ list => list.map({ case (_, v) => v }) })
.toMap
}

/**
Expand All @@ -136,13 +133,16 @@ object IterativeCostDistance {
val resolution = computeResolution(friction)
logger.debug(s"Computed resolution: $resolution meters/pixel")

val bounds = friction.metadata.bounds.asInstanceOf[KeyBounds[K]]
val minKey = implicitly[SpatialKey](bounds.minKey)
val minKeyCol = minKey._1
val minKeyRow = minKey._2
val maxKey = implicitly[SpatialKey](bounds.maxKey)
val maxKeyCol = maxKey._1
val maxKeyRow = maxKey._2
val bounds = friction.metadata.bounds match {
case b: KeyBounds[K] => b
case _ => throw new Exception
}
val minKey: SpatialKey = bounds.minKey
val minKeyCol = minKey.col
val minKeyRow = minKey.row
val maxKey: SpatialKey = bounds.maxKey
val maxKeyCol = maxKey.col
val maxKeyRow = maxKey.row

val accumulator = new ChangesAccumulator
sc.register(accumulator)
Expand All @@ -153,8 +153,8 @@ object IterativeCostDistance {
// Create RDD of initial (empty) cost tiles and load the
// accumulator with the starting values.
var costs: RDD[(K, V, DoubleArrayTile)] = friction.map({ case (k, v) =>
val key = implicitly[SpatialKey](k)
val tile = implicitly[Tile](v)
val key: SpatialKey = k
val tile: Tile = v
val cols = tile.cols
val rows = tile.rows
val extent = mt(key)
Expand Down Expand Up @@ -184,7 +184,6 @@ object IterativeCostDistance {
accumulator.value
.groupBy(_._1)
.map({ case (k, list) => (k, list.map({ case (_, v) => v })) })
.toMap
val changes = sc.broadcast(_changes)
logger.debug(s"At least ${changes.value.size} changed tiles")

Expand All @@ -193,10 +192,10 @@ object IterativeCostDistance {
val previous = costs

costs = previous.map({ case (k, v, oldCostTile) =>
val key = implicitly[SpatialKey](k)
val frictionTile = implicitly[Tile](v)
val keyCol = key._1
val keyRow = key._2
val key: SpatialKey = k
val frictionTile: Tile = v
val keyCol = key.col
val keyRow = key.row
val frictionTileCols = frictionTile.cols
val frictionTileRows = frictionTile.rows
val localChanges: Option[Seq[SimpleCostDistance.Cost]] = changes.value.get(key)
Expand Down Expand Up @@ -247,11 +246,11 @@ object IterativeCostDistance {

costs.count
previous.unpersist()
} while (accumulator.value.size > 0)
} while (accumulator.value.nonEmpty)

// Construct return value and return it
val metadata = TileLayerMetadata(DoubleCellType, md.layout, md.extent, md.crs, md.bounds)
val rdd = costs.map({ case (k, _, cost) => (k, cost.asInstanceOf[Tile]) })
val rdd = costs.map({ case (k, _, cost) => (k, cost: Tile) })
ContextRDD(rdd, metadata)
}

Expand Down

0 comments on commit 91777a6

Please sign in to comment.