Skip to content

Commit

Permalink
Fixed #31766 -- Avoided uncessary computation in GDALRaster
Browse files Browse the repository at this point in the history
Implemented a clone method using ds_copy to clone GDALRaster objects. Added conditional to simply clone GDALRaster if SRID matches with transform srs argument.
  • Loading branch information
bartondc committed Aug 30, 2020
1 parent 0be51d2 commit 23e5900
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -110,6 +110,7 @@ answer newbie questions, and generally made Django that much better:
Baptiste Mispelon <bmispelon@gmail.com>
Barry Pederson <bp@barryp.org>
Bartolome Sanchez Salado <i42sasab@uco.es>
Barton Ip <notbartonip@gmail.com>
Bartosz Grabski <bartosz.grabski@gmail.com>
Bashar Al-Abdulhadi
Bastian Kleineidam <calvin@debian.org>
Expand Down
8 changes: 8 additions & 0 deletions django/contrib/gis/gdal/raster/source.py
Expand Up @@ -425,6 +425,10 @@ def warp(self, ds_input, resampling='NearestNeighbour', max_error=0.0):

return target

def clone(self):
"Return a clone of this GDALRaster object"
return GDALRaster(self._ptr, write=self._write)

def transform(self, srs, driver=None, name=None, resampling='NearestNeighbour',
max_error=0.0):
"""
Expand All @@ -443,6 +447,10 @@ def transform(self, srs, driver=None, name=None, resampling='NearestNeighbour',
'Transform only accepts SpatialReference, string, and integer '
'objects.'
)

if target_srs.srid == self.srid:
return self.clone()

# Create warped virtual dataset in the target reference system
target = capi.auto_create_warped_vrt(
self._ptr, self.srs.wkt.encode(), target_srs.wkt.encode(),
Expand Down
55 changes: 55 additions & 0 deletions tests/gis_tests/gdal_tests/test_raster.py
Expand Up @@ -2,13 +2,15 @@
import shutil
import struct
import tempfile
from unittest import mock

from django.contrib.gis.gdal import GDAL_VERSION, GDALRaster, SpatialReference
from django.contrib.gis.gdal.error import GDALException
from django.contrib.gis.gdal.raster.band import GDALBand
from django.contrib.gis.shortcuts import numpy
from django.test import SimpleTestCase


from ..data.rasters.textrasters import JSON_RASTER


Expand Down Expand Up @@ -470,6 +472,59 @@ def test_raster_warp_nodata_zone(self):
# The result is an empty raster filled with the correct nodata value.
self.assertEqual(result, [23] * 16)

def test_raster_clone(self):
source = GDALRaster({
'datatype': 1,
'driver': 'MEM',
'width': 4,
'height': 4,
'srid': 3086,
'origin': (500000, 400000),
'scale': (100, -100),
'skew': (0, 0),
'bands': [{
'data': range(16),
'nodata_value': 23,
}],
})

clone = source.clone()

# Test cloned raster has same attributes
self.assertEqual(source.name, clone.name)
self.assertEqual(source.srs.srid, clone.srs.srid)
self.assertEqual(source.width, clone.width)
self.assertEqual(source.height, clone.height)
self.assertEqual(source.bands[0].datatype(), clone.bands[0].datatype())
self.assertAlmostEqual(source.origin[0], clone.origin[0], 3)
self.assertAlmostEqual(source.origin[1], clone.origin[1], 3)
self.assertAlmostEqual(source.scale[0], clone.scale[0], 3)
self.assertAlmostEqual(source.scale[1], clone.scale[1], 3)
self.assertEqual(source.skew, clone.skew)

def test_raster_transform_skips_recalculation(self):
with mock.patch.object(GDALRaster, "clone") as clone_func:
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,
}],
})

target = source.transform(4326)

self.assertEqual(clone_func.call_count, 1)

def test_raster_transform(self):
tests = [
3086,
Expand Down

0 comments on commit 23e5900

Please sign in to comment.