Fixed #31713 -- Added SpatialReference support to GDALRaster.transform().
This commit is contained in:
parent
7af8f41273
commit
cb0da637a6
|
@ -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],
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -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,62 +471,65 @@ 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 = [
|
||||||
rstfile = tempfile.NamedTemporaryFile(suffix='.tif')
|
3086,
|
||||||
ndv = 99
|
'3086',
|
||||||
|
SpatialReference(3086),
|
||||||
|
]
|
||||||
|
for srs in tests:
|
||||||
|
with self.subTest(srs=srs):
|
||||||
|
# Prepare tempfile and nodata value.
|
||||||
|
rstfile = tempfile.NamedTemporaryFile(suffix='.tif')
|
||||||
|
ndv = 99
|
||||||
|
# Create in file based raster.
|
||||||
|
source = GDALRaster({
|
||||||
|
'datatype': 1,
|
||||||
|
'driver': 'tif',
|
||||||
|
'name': rstfile.name,
|
||||||
|
'width': 5,
|
||||||
|
'height': 5,
|
||||||
|
'nr_of_bands': 1,
|
||||||
|
'srid': 4326,
|
||||||
|
'origin': (-5, 5),
|
||||||
|
'scale': (2, -2),
|
||||||
|
'skew': (0, 0),
|
||||||
|
'bands': [{
|
||||||
|
'data': range(25),
|
||||||
|
'nodata_value': ndv,
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
|
||||||
# Create in file based raster
|
target = source.transform(srs)
|
||||||
source = GDALRaster({
|
|
||||||
'datatype': 1,
|
|
||||||
'driver': 'tif',
|
|
||||||
'name': rstfile.name,
|
|
||||||
'width': 5,
|
|
||||||
'height': 5,
|
|
||||||
'nr_of_bands': 1,
|
|
||||||
'srid': 4326,
|
|
||||||
'origin': (-5, 5),
|
|
||||||
'scale': (2, -2),
|
|
||||||
'skew': (0, 0),
|
|
||||||
'bands': [{
|
|
||||||
'data': range(25),
|
|
||||||
'nodata_value': ndv,
|
|
||||||
}],
|
|
||||||
})
|
|
||||||
|
|
||||||
# Transform raster into srid 4326.
|
# Reload data from disk.
|
||||||
target = source.transform(3086)
|
target = GDALRaster(target.name)
|
||||||
|
self.assertEqual(target.srs.srid, 3086)
|
||||||
|
self.assertEqual(target.width, 7)
|
||||||
|
self.assertEqual(target.height, 7)
|
||||||
|
self.assertEqual(target.bands[0].datatype(), source.bands[0].datatype())
|
||||||
|
self.assertAlmostEqual(target.origin[0], 9124842.791079799, 3)
|
||||||
|
self.assertAlmostEqual(target.origin[1], 1589911.6476407414, 3)
|
||||||
|
self.assertAlmostEqual(target.scale[0], 223824.82664250192, 3)
|
||||||
|
self.assertAlmostEqual(target.scale[1], -223824.82664250192, 3)
|
||||||
|
self.assertEqual(target.skew, [0, 0])
|
||||||
|
|
||||||
# Reload data from disk
|
result = target.bands[0].data()
|
||||||
target = GDALRaster(target.name)
|
if numpy:
|
||||||
|
result = result.flatten().tolist()
|
||||||
self.assertEqual(target.srs.srid, 3086)
|
# The reprojection of a raster that spans over a large area
|
||||||
self.assertEqual(target.width, 7)
|
# skews the data matrix and might introduce nodata values.
|
||||||
self.assertEqual(target.height, 7)
|
self.assertEqual(
|
||||||
self.assertEqual(target.bands[0].datatype(), source.bands[0].datatype())
|
result,
|
||||||
self.assertAlmostEqual(target.origin[0], 9124842.791079799, 3)
|
[
|
||||||
self.assertAlmostEqual(target.origin[1], 1589911.6476407414, 3)
|
ndv, ndv, ndv, ndv, 4, ndv, ndv,
|
||||||
self.assertAlmostEqual(target.scale[0], 223824.82664250192, 3)
|
ndv, ndv, 2, 3, 9, ndv, ndv,
|
||||||
self.assertAlmostEqual(target.scale[1], -223824.82664250192, 3)
|
ndv, 1, 2, 8, 13, 19, ndv,
|
||||||
self.assertEqual(target.skew, [0, 0])
|
0, 6, 6, 12, 18, 18, 24,
|
||||||
|
ndv, 10, 11, 16, 22, 23, ndv,
|
||||||
result = target.bands[0].data()
|
ndv, ndv, 15, 21, 22, ndv, ndv,
|
||||||
if numpy:
|
ndv, ndv, 20, ndv, ndv, ndv, ndv,
|
||||||
result = result.flatten().tolist()
|
],
|
||||||
|
)
|
||||||
# The reprojection of a raster that spans over a large area
|
|
||||||
# skews the data matrix and might introduce nodata values.
|
|
||||||
self.assertEqual(
|
|
||||||
result,
|
|
||||||
[
|
|
||||||
ndv, ndv, ndv, ndv, 4, ndv, ndv,
|
|
||||||
ndv, ndv, 2, 3, 9, ndv, ndv,
|
|
||||||
ndv, 1, 2, 8, 13, 19, ndv,
|
|
||||||
0, 6, 6, 12, 18, 18, 24,
|
|
||||||
ndv, 10, 11, 16, 22, 23, ndv,
|
|
||||||
ndv, ndv, 15, 21, 22, ndv, ndv,
|
|
||||||
ndv, ndv, 20, ndv, ndv, ndv, ndv,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class GDALBandTests(SimpleTestCase):
|
class GDALBandTests(SimpleTestCase):
|
||||||
|
|
Loading…
Reference in New Issue