Fixed #31713 -- Added SpatialReference support to GDALRaster.transform().

This commit is contained in:
rico-ci 2020-06-18 14:52:02 +02:00 committed by Mariusz Felisiak
parent 7af8f41273
commit cb0da637a6
4 changed files with 86 additions and 68 deletions

View File

@ -425,17 +425,24 @@ class GDALRaster(GDALRasterBase):
return target return target
def transform(self, srid, driver=None, name=None, resampling='NearestNeighbour', def transform(self, srs, driver=None, name=None, resampling='NearestNeighbour',
max_error=0.0): max_error=0.0):
""" """
Return a copy of this raster reprojected into the given SRID. Return a copy of this raster reprojected into the given spatial
reference system.
""" """
# Convert the resampling algorithm name into an algorithm id # Convert the resampling algorithm name into an algorithm id
algorithm = GDAL_RESAMPLE_ALGORITHMS[resampling] algorithm = GDAL_RESAMPLE_ALGORITHMS[resampling]
# Instantiate target spatial reference system if isinstance(srs, SpatialReference):
target_srs = SpatialReference(srid) target_srs = srs
elif isinstance(srs, (int, str)):
target_srs = SpatialReference(srs)
else:
raise TypeError(
'Transform only accepts SpatialReference, string, and integer '
'objects.'
)
# Create warped virtual dataset in the target reference system # Create warped virtual dataset in the target reference system
target = capi.auto_create_warped_vrt( target = capi.auto_create_warped_vrt(
self._ptr, self.srs.wkt.encode(), target_srs.wkt.encode(), self._ptr, self.srs.wkt.encode(), target_srs.wkt.encode(),
@ -445,7 +452,7 @@ class GDALRaster(GDALRasterBase):
# Construct the target warp dictionary from the virtual raster # Construct the target warp dictionary from the virtual raster
data = { data = {
'srid': srid, 'srid': target_srs.srid,
'width': target.width, 'width': target.width,
'height': target.height, 'height': target.height,
'origin': [target.origin.x, target.origin.y], 'origin': [target.origin.x, target.origin.y],

View File

@ -1368,14 +1368,16 @@ blue.
[ 19., 21., 23.], [ 19., 21., 23.],
[ 31., 33., 35.]], dtype=float32) [ 31., 33., 35.]], dtype=float32)
.. method:: transform(srid, driver=None, name=None, resampling='NearestNeighbour', max_error=0.0) .. method:: transform(srs, driver=None, name=None, resampling='NearestNeighbour', max_error=0.0)
Returns a transformed version of this raster with the specified SRID. Transforms this raster to a different spatial reference system
(``srs``), which may be a :class:`SpatialReference` object, or any
other input accepted by :class:`SpatialReference` (including spatial
reference WKT and PROJ strings, or an integer SRID).
This function transforms the current raster into a new spatial reference It calculates the bounds and scale of the current raster in the new
system that can be specified with an ``srid``. It calculates the bounds spatial reference system and warps the raster using the
and scale of the current raster in the new spatial reference system and :attr:`~GDALRaster.warp` function.
warps the raster using the :attr:`~GDALRaster.warp` function.
By default, the driver of the source raster is used and the name of the By default, the driver of the source raster is used and the name of the
raster is the original name appended with raster is the original name appended with
@ -1394,10 +1396,15 @@ blue.
... "scale": [100, -100], ... "scale": [100, -100],
... "bands": [{"data": range(36), "nodata_value": 99}] ... "bands": [{"data": range(36), "nodata_value": 99}]
... }) ... })
>>> target = rst.transform(4326) >>> target_srs = SpatialReference(4326)
>>> target = rst.transform(target_srs)
>>> target.origin >>> target.origin
[-82.98492744885776, 27.601924753080144] [-82.98492744885776, 27.601924753080144]
.. versionchanged:: 3.2
Support for :class:`SpatialReference` ``srs`` was added
.. attribute:: info .. attribute:: info
Returns a string with a summary of the raster. This is equivalent to Returns a string with a summary of the raster. This is equivalent to

View File

@ -68,7 +68,8 @@ Minor features
:mod:`django.contrib.gis` :mod:`django.contrib.gis`
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
* ... * The :meth:`.GDALRaster.transform` method now supports
:class:`~django.contrib.gis.gdal.SpatialReference`.
:mod:`django.contrib.messages` :mod:`django.contrib.messages`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -3,7 +3,7 @@ import shutil
import struct import struct
import tempfile import tempfile
from django.contrib.gis.gdal import GDAL_VERSION, GDALRaster from django.contrib.gis.gdal import GDAL_VERSION, GDALRaster, SpatialReference
from django.contrib.gis.gdal.error import GDALException from django.contrib.gis.gdal.error import GDALException
from django.contrib.gis.gdal.raster.band import GDALBand from django.contrib.gis.gdal.raster.band import GDALBand
from django.contrib.gis.shortcuts import numpy from django.contrib.gis.shortcuts import numpy
@ -471,11 +471,17 @@ class GDALRasterTests(SimpleTestCase):
self.assertEqual(result, [23] * 16) self.assertEqual(result, [23] * 16)
def test_raster_transform(self): def test_raster_transform(self):
# Prepare tempfile and nodata value tests = [
3086,
'3086',
SpatialReference(3086),
]
for srs in tests:
with self.subTest(srs=srs):
# Prepare tempfile and nodata value.
rstfile = tempfile.NamedTemporaryFile(suffix='.tif') rstfile = tempfile.NamedTemporaryFile(suffix='.tif')
ndv = 99 ndv = 99
# Create in file based raster.
# Create in file based raster
source = GDALRaster({ source = GDALRaster({
'datatype': 1, 'datatype': 1,
'driver': 'tif', 'driver': 'tif',
@ -493,12 +499,10 @@ class GDALRasterTests(SimpleTestCase):
}], }],
}) })
# Transform raster into srid 4326. target = source.transform(srs)
target = source.transform(3086)
# Reload data from disk # Reload data from disk.
target = GDALRaster(target.name) target = GDALRaster(target.name)
self.assertEqual(target.srs.srid, 3086) self.assertEqual(target.srs.srid, 3086)
self.assertEqual(target.width, 7) self.assertEqual(target.width, 7)
self.assertEqual(target.height, 7) self.assertEqual(target.height, 7)
@ -512,7 +516,6 @@ class GDALRasterTests(SimpleTestCase):
result = target.bands[0].data() result = target.bands[0].data()
if numpy: if numpy:
result = result.flatten().tolist() result = result.flatten().tolist()
# The reprojection of a raster that spans over a large area # The reprojection of a raster that spans over a large area
# skews the data matrix and might introduce nodata values. # skews the data matrix and might introduce nodata values.
self.assertEqual( self.assertEqual(
@ -525,7 +528,7 @@ class GDALRasterTests(SimpleTestCase):
ndv, 10, 11, 16, 22, 23, ndv, ndv, 10, 11, 16, 22, 23, ndv,
ndv, ndv, 15, 21, 22, ndv, ndv, ndv, ndv, 15, 21, 22, ndv, ndv,
ndv, ndv, 20, ndv, ndv, ndv, ndv, ndv, ndv, 20, ndv, ndv, ndv, ndv,
] ],
) )