Skip to content

Commit db606a2

Browse files
pomadchinjdries
andauthored
Avoid GeoAttrsError by using more robust target extent calculation (#3572)
* avoid GeoAttrsError by using more robust target extent calculation in case a LayoutDefinition is available #3559 * Code cleanup --------- Co-authored-by: Jeroen Dries <jeroen.dries@vito.be>
1 parent 7375fb0 commit db606a2

File tree

3 files changed

+28
-6
lines changed

3 files changed

+28
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
- GeoTiffReader Unknown tags skip fix [#3557](https://github.com/locationtech/geotrellis/pull/3557)
1616
- Fix implicitNotFound error and rename RGBAMethods implicit class [#3563](https://github.com/locationtech/geotrellis/pull/3563)
1717
- Set 'role' attribute in GDALMetadata tag written to tiff header, to match GDAL behaviour. [#3496](https://github.com/locationtech/geotrellis/issues/3496)
18+
- Avoid GeoAttrsError by using more robust target extent calculation [#3572](https://github.com/locationtech/geotrellis/pull/3572)
1819

1920
## [3.7.1] - 2024-01-08
2021

spark/src/main/scala/geotrellis/spark/reproject/TileRDDReproject.scala

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,17 @@ object TileRDDReproject {
6666
): (Int, RDD[(K, V)] with Metadata[TileLayerMetadata[K]]) = {
6767
val crs: CRS = metadata.crs
6868
val layout = metadata.layout
69-
val tileLayout: TileLayout = layout.tileLayout
7069
implicit val sc = bufferedTiles.context
7170

7271
val sourceDataGridExtent = metadata.layout.createAlignedGridExtent(metadata.extent)
73-
val passthroughGridExtent = ReprojectRasterExtent(sourceDataGridExtent, metadata.crs, destCrs)
74-
val targetDataExtent = passthroughGridExtent.extent
72+
val (targetCellSize, targetDataExtent) =
73+
targetLayout match {
74+
case Right(l) =>
75+
l.cellSize -> l.createAlignedGridExtent(ProjectedExtent(metadata.extent,metadata.crs).reproject(destCrs)).extent
76+
case Left(_) =>
77+
val passthroughGridExtent = ReprojectRasterExtent(sourceDataGridExtent, metadata.crs, destCrs)
78+
passthroughGridExtent.cellSize -> passthroughGridExtent.extent
79+
}
7580

7681
val targetPartitioner: Option[Partitioner] = partitioner.orElse(bufferedTiles.partitioner)
7782

@@ -112,7 +117,7 @@ object TileRDDReproject {
112117
layoutScheme.levelFor(targetDataExtent, ct)
113118

114119
case None =>
115-
layoutScheme.levelFor(targetDataExtent, passthroughGridExtent.cellSize)
120+
layoutScheme.levelFor(targetDataExtent, targetCellSize)
116121
}
117122
}
118123
}

spark/src/test/scala/geotrellis/spark/reproject/TileRDDReprojectSpec.scala

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,8 @@ import geotrellis.spark.reproject.Reproject.Options
2626
import geotrellis.spark.testkit._
2727
import geotrellis.vector._
2828
import geotrellis.proj4._
29-
3029
import spire.syntax.cfor._
3130
import org.apache.spark._
32-
3331
import org.scalatest.funspec.AnyFunSpec
3432

3533
class TileRDDReprojectSpec extends AnyFunSpec with TestEnvironment {
@@ -328,4 +326,22 @@ class TileRDDReprojectSpec extends AnyFunSpec with TestEnvironment {
328326
afterMetadata.layout should be (beforeMetadata.layout)
329327
}
330328
}
329+
330+
describe("Very small cube at high latitude") {
331+
it("should reproject without error") {
332+
val layout = LayoutDefinition(RasterExtent(Extent(-120.550992, 71.82628788888888, -120.5421031111111, 71.83517677777778), 32, 32), 32, 32)
333+
val targetLayout = LayoutDefinition(RasterExtent(Extent(585180.0, 7971640.0, 585820.0, 7972280.0), 32, 32), 32, 32)
334+
val extent = Extent(-120.550992, 71.834899, -120.550792, 71.835099)
335+
val cube: TileLayerRDD[SpatialKey] = TileLayerRDDBuilders.createTileLayerRDD(sc, ByteArrayTile.fill(1, 32, 32), layout.tileLayout, LatLng)
336+
337+
val utm = CRS.fromEpsgCode(32610)
338+
339+
val badMetadata = cube.metadata.copy(crs = LatLng, extent = extent, layout = layout)
340+
val result = TileRDDReproject(ContextRDD(cube, badMetadata), utm, Right(targetLayout), 16, Reproject.Options.DEFAULT, None)
341+
//should not throw an error
342+
val resultMetadata = result._2.metadata
343+
targetLayout should be(resultMetadata.layout)
344+
utm should be(resultMetadata.crs)
345+
}
346+
}
331347
}

0 commit comments

Comments
 (0)