summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2020-05-08 11:28:52 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-05-12 09:06:06 +0200
commit58f1b07e49a98bb391c9e38b91f078ab2c302703 (patch)
treec97c666c8e18fa7653902f3fef66e5d2eb9c8319
parent0668164b4ac93a5be79f5b87fae83c657124d9ab (diff)
Fixed #30678 -- Added support for GDAL 3.
-rw-r--r--django/contrib/gis/gdal/__init__.py12
-rw-r--r--django/contrib/gis/gdal/prototypes/srs.py5
-rw-r--r--django/contrib/gis/gdal/srs.py25
-rw-r--r--django/contrib/gis/geos/geometry.py2
-rw-r--r--docs/ref/contrib/gis/install/geolibs.txt5
-rw-r--r--docs/releases/3.1.txt2
-rw-r--r--tests/gis_tests/gdal_tests/test_raster.py79
-rw-r--r--tests/gis_tests/gdal_tests/test_srs.py90
-rw-r--r--tests/gis_tests/geos_tests/test_geos.py4
-rw-r--r--tests/gis_tests/test_geoforms.py2
-rw-r--r--tests/gis_tests/test_spatialrefsys.py8
11 files changed, 140 insertions, 94 deletions
diff --git a/django/contrib/gis/gdal/__init__.py b/django/contrib/gis/gdal/__init__.py
index 6a0f5360d8..1d8c6884bd 100644
--- a/django/contrib/gis/gdal/__init__.py
+++ b/django/contrib/gis/gdal/__init__.py
@@ -37,11 +37,13 @@ from django.contrib.gis.gdal.libgdal import (
GDAL_VERSION, gdal_full_version, gdal_version,
)
from django.contrib.gis.gdal.raster.source import GDALRaster
-from django.contrib.gis.gdal.srs import CoordTransform, SpatialReference
+from django.contrib.gis.gdal.srs import (
+ AxisOrder, CoordTransform, SpatialReference,
+)
__all__ = (
- 'Driver', 'DataSource', 'CoordTransform', 'Envelope', 'GDALException',
- 'GDALRaster', 'GDAL_VERSION', 'OGRGeometry', 'OGRGeomType',
- 'SpatialReference', 'SRSException', 'check_err', 'gdal_version',
- 'gdal_full_version',
+ 'AxisOrder', 'Driver', 'DataSource', 'CoordTransform', 'Envelope',
+ 'GDALException', 'GDALRaster', 'GDAL_VERSION', 'OGRGeometry',
+ 'OGRGeomType', 'SpatialReference', 'SRSException', 'check_err',
+ 'gdal_version', 'gdal_full_version',
)
diff --git a/django/contrib/gis/gdal/prototypes/srs.py b/django/contrib/gis/gdal/prototypes/srs.py
index 45d5234346..004319f1b9 100644
--- a/django/contrib/gis/gdal/prototypes/srs.py
+++ b/django/contrib/gis/gdal/prototypes/srs.py
@@ -1,6 +1,6 @@
from ctypes import POINTER, c_char_p, c_int, c_void_p
-from django.contrib.gis.gdal.libgdal import lgdal, std_call
+from django.contrib.gis.gdal.libgdal import GDAL_VERSION, lgdal, std_call
from django.contrib.gis.gdal.prototypes.generation import (
const_string_output, double_output, int_output, srs_output, string_output,
void_output,
@@ -31,6 +31,9 @@ release_srs = void_output(lgdal.OSRRelease, [c_void_p], errcheck=False)
destroy_srs = void_output(std_call('OSRDestroySpatialReference'), [c_void_p], errcheck=False)
srs_validate = void_output(lgdal.OSRValidate, [c_void_p])
+if GDAL_VERSION >= (3, 0):
+ set_axis_strategy = void_output(lgdal.OSRSetAxisMappingStrategy, [c_void_p, c_int])
+
# Getting the semi_major, semi_minor, and flattening functions.
semi_major = srs_double(lgdal.OSRGetSemiMajor)
semi_minor = srs_double(lgdal.OSRGetSemiMinor)
diff --git a/django/contrib/gis/gdal/srs.py b/django/contrib/gis/gdal/srs.py
index 850196ccc3..d2e781e381 100644
--- a/django/contrib/gis/gdal/srs.py
+++ b/django/contrib/gis/gdal/srs.py
@@ -27,13 +27,20 @@
NAD83 / Texas South Central
"""
from ctypes import byref, c_char_p, c_int
+from enum import IntEnum
from django.contrib.gis.gdal.base import GDALBase
from django.contrib.gis.gdal.error import SRSException
+from django.contrib.gis.gdal.libgdal import GDAL_VERSION
from django.contrib.gis.gdal.prototypes import srs as capi
from django.utils.encoding import force_bytes, force_str
+class AxisOrder(IntEnum):
+ TRADITIONAL = 0
+ AUTHORITY = 1
+
+
class SpatialReference(GDALBase):
"""
A wrapper for the OGRSpatialReference object. According to the GDAL Web site,
@@ -42,17 +49,25 @@ class SpatialReference(GDALBase):
"""
destructor = capi.release_srs
- def __init__(self, srs_input='', srs_type='user'):
+ def __init__(self, srs_input='', srs_type='user', axis_order=None):
"""
Create a GDAL OSR Spatial Reference object from the given input.
The input may be string of OGC Well Known Text (WKT), an integer
EPSG code, a PROJ.4 string, and/or a projection "well known" shorthand
string (one of 'WGS84', 'WGS72', 'NAD27', 'NAD83').
"""
-
+ if not isinstance(axis_order, (type(None), AxisOrder)):
+ raise ValueError(
+ 'SpatialReference.axis_order must be an AxisOrder instance.'
+ )
+ self.axis_order = axis_order or AxisOrder.TRADITIONAL
if srs_type == 'wkt':
self.ptr = capi.new_srs(c_char_p(b''))
self.import_wkt(srs_input)
+ if self.axis_order == AxisOrder.TRADITIONAL and GDAL_VERSION >= (3, 0):
+ capi.set_axis_strategy(self.ptr, self.axis_order)
+ elif self.axis_order != AxisOrder.TRADITIONAL and GDAL_VERSION < (3, 0):
+ raise ValueError('%s is not supported in GDAL < 3.0.' % self.axis_order)
return
elif isinstance(srs_input, str):
try:
@@ -85,6 +100,10 @@ class SpatialReference(GDALBase):
else:
self.ptr = srs
+ if self.axis_order == AxisOrder.TRADITIONAL and GDAL_VERSION >= (3, 0):
+ capi.set_axis_strategy(self.ptr, self.axis_order)
+ elif self.axis_order != AxisOrder.TRADITIONAL and GDAL_VERSION < (3, 0):
+ raise ValueError('%s is not supported in GDAL < 3.0.' % self.axis_order)
# Importing from either the user input string or an integer SRID.
if srs_type == 'user':
self.import_user_input(srs_input)
@@ -143,7 +162,7 @@ class SpatialReference(GDALBase):
def clone(self):
"Return a clone of this SpatialReference object."
- return SpatialReference(capi.clone_srs(self.ptr))
+ return SpatialReference(capi.clone_srs(self.ptr), axis_order=self.axis_order)
def from_esri(self):
"Morph this SpatialReference from ESRI's format to EPSG."
diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py
index 221af4fc68..8fb0117b3e 100644
--- a/django/contrib/gis/geos/geometry.py
+++ b/django/contrib/gis/geos/geometry.py
@@ -434,7 +434,7 @@ class GEOSGeometryBase(GEOSBase):
if self.srid:
try:
return gdal.SpatialReference(self.srid)
- except gdal.SRSException:
+ except (gdal.GDALException, gdal.SRSException):
pass
return None
diff --git a/docs/ref/contrib/gis/install/geolibs.txt b/docs/ref/contrib/gis/install/geolibs.txt
index b0878a9e4c..ee60ee3fbd 100644
--- a/docs/ref/contrib/gis/install/geolibs.txt
+++ b/docs/ref/contrib/gis/install/geolibs.txt
@@ -9,8 +9,8 @@ geospatial libraries:
Program Description Required Supported Versions
======================== ==================================== ================================ ===================================
:doc:`GEOS <../geos>` Geometry Engine Open Source Yes 3.7, 3.6, 3.5
-`PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 5.2, 5.1, 5.0, 4.x
-:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 2.4, 2.3, 2.2, 2.1, 2.0
+`PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 6.3, 6.2, 6.1, 6.0, 5.x, 4.x
+:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 3.0, 2.4, 2.3, 2.2, 2.1, 2.0
:doc:`GeoIP <../geoip2>` IP-based geolocation library No 2
`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 3.0, 2.5, 2.4, 2.3, 2.2
`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 4.3
@@ -29,6 +29,7 @@ totally fine with GeoDjango. Your mileage may vary.
GDAL 2.2.0 2017-05
GDAL 2.3.0 2018-05
GDAL 2.4.0 2018-12
+ GDAL 3.0.0 2019-05
PostGIS 2.2.0 2015-10-17
PostGIS 2.3.0 2016-09-26
PostGIS 2.4.0 2017-09-30
diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt
index 2d9ae7ed4c..7a446c68d8 100644
--- a/docs/releases/3.1.txt
+++ b/docs/releases/3.1.txt
@@ -145,7 +145,7 @@ Minor features
* Added the :class:`~django.contrib.gis.db.models.functions.AsWKB` and
:class:`~django.contrib.gis.db.models.functions.AsWKT` functions.
-* Added support for PostGIS 3.
+* Added support for PostGIS 3 and GDAL 3.
:mod:`django.contrib.humanize`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/gis_tests/gdal_tests/test_raster.py b/tests/gis_tests/gdal_tests/test_raster.py
index 018871efc3..3369d71ea0 100644
--- a/tests/gis_tests/gdal_tests/test_raster.py
+++ b/tests/gis_tests/gdal_tests/test_raster.py
@@ -146,7 +146,11 @@ class GDALRasterTests(SimpleTestCase):
# Reload newly created raster from file
restored_raster = GDALRaster(rstfile.name)
- self.assertEqual(restored_raster.srs.wkt, self.rs.srs.wkt)
+ # Presence of TOWGS84 depend on GDAL/Proj versions.
+ self.assertEqual(
+ restored_raster.srs.wkt.replace('TOWGS84[0,0,0,0,0,0,0],', ''),
+ self.rs.srs.wkt.replace('TOWGS84[0,0,0,0,0,0,0],', '')
+ )
self.assertEqual(restored_raster.geotransform, self.rs.geotransform)
if numpy:
numpy.testing.assert_equal(
@@ -322,54 +326,33 @@ class GDALRasterTests(SimpleTestCase):
with self.assertRaisesMessage(ValueError, msg):
self.rs.info
return
- gdalinfo = """
- Driver: GTiff/GeoTIFF
- Files: {}
- Size is 163, 174
- Coordinate System is:
- PROJCS["NAD83 / Florida GDL Albers",
- GEOGCS["NAD83",
- DATUM["North_American_Datum_1983",
- SPHEROID["GRS 1980",6378137,298.257222101,
- AUTHORITY["EPSG","7019"]],
- TOWGS84[0,0,0,0,0,0,0],
- AUTHORITY["EPSG","6269"]],
- PRIMEM["Greenwich",0,
- AUTHORITY["EPSG","8901"]],
- UNIT["degree",0.0174532925199433,
- AUTHORITY["EPSG","9122"]],
- AUTHORITY["EPSG","4269"]],
- PROJECTION["Albers_Conic_Equal_Area"],
- PARAMETER["standard_parallel_1",24],
- PARAMETER["standard_parallel_2",31.5],
- PARAMETER["latitude_of_center",24],
- PARAMETER["longitude_of_center",-84],
- PARAMETER["false_easting",400000],
- PARAMETER["false_northing",0],
- UNIT["metre",1,
- AUTHORITY["EPSG","9001"]],
- AXIS["X",EAST],
- AXIS["Y",NORTH],
- AUTHORITY["EPSG","3086"]]
- Origin = (511700.468070655711927,435103.377123198588379)
- Pixel Size = (100.000000000000000,-100.000000000000000)
- Metadata:
- AREA_OR_POINT=Area
- Image Structure Metadata:
- INTERLEAVE=BAND
- Corner Coordinates:
- Upper Left ( 511700.468, 435103.377) ( 82d51'46.16"W, 27d55' 1.53"N)
- Lower Left ( 511700.468, 417703.377) ( 82d51'52.04"W, 27d45'37.50"N)
- Upper Right ( 528000.468, 435103.377) ( 82d41'48.81"W, 27d54'56.30"N)
- Lower Right ( 528000.468, 417703.377) ( 82d41'55.54"W, 27d45'32.28"N)
- Center ( 519850.468, 426403.377) ( 82d46'50.64"W, 27d50'16.99"N)
- Band 1 Block=163x50 Type=Byte, ColorInterp=Gray
- NoData Value=15
- """.format(self.rs_path)
+ infos = self.rs.info
# Data
- info_dyn = [line.strip() for line in self.rs.info.split('\n') if line.strip() != '']
- info_ref = [line.strip() for line in gdalinfo.split('\n') if line.strip() != '']
- self.assertEqual(info_dyn, info_ref)
+ info_lines = [line.strip() for line in infos.split('\n') if line.strip() != '']
+ for line in [
+ 'Driver: GTiff/GeoTIFF',
+ 'Files: {}'.format(self.rs_path),
+ 'Size is 163, 174',
+ 'Origin = (511700.468070655711927,435103.377123198588379)',
+ 'Pixel Size = (100.000000000000000,-100.000000000000000)',
+ 'Metadata:',
+ 'AREA_OR_POINT=Area',
+ 'Image Structure Metadata:',
+ 'INTERLEAVE=BAND',
+ 'Band 1 Block=163x50 Type=Byte, ColorInterp=Gray',
+ 'NoData Value=15'
+ ]:
+ self.assertIn(line, info_lines)
+ for line in [
+ r'Upper Left \( 511700.468, 435103.377\) \( 82d51\'46.1\d"W, 27d55\' 1.5\d"N\)',
+ r'Lower Left \( 511700.468, 417703.377\) \( 82d51\'52.0\d"W, 27d45\'37.5\d"N\)',
+ r'Upper Right \( 528000.468, 435103.377\) \( 82d41\'48.8\d"W, 27d54\'56.3\d"N\)',
+ r'Lower Right \( 528000.468, 417703.377\) \( 82d41\'55.5\d"W, 27d45\'32.2\d"N\)',
+ r'Center \( 519850.468, 426403.377\) \( 82d46\'50.6\d"W, 27d50\'16.9\d"N\)',
+ ]:
+ self.assertRegex(infos, line)
+ # CRS (skip the name because string depends on the GDAL/Proj versions).
+ self.assertIn("NAD83 / Florida GDL Albers", infos)
def test_compressed_file_based_raster_creation(self):
rstfile = tempfile.NamedTemporaryFile(suffix='.tif')
diff --git a/tests/gis_tests/gdal_tests/test_srs.py b/tests/gis_tests/gdal_tests/test_srs.py
index 02af60bc7a..27974c8b80 100644
--- a/tests/gis_tests/gdal_tests/test_srs.py
+++ b/tests/gis_tests/gdal_tests/test_srs.py
@@ -1,8 +1,11 @@
-import unittest
+from unittest import skipIf
from django.contrib.gis.gdal import (
- CoordTransform, GDALException, SpatialReference, SRSException,
+ GDAL_VERSION, AxisOrder, CoordTransform, GDALException, SpatialReference,
+ SRSException,
)
+from django.contrib.gis.geos import GEOSGeometry
+from django.test import SimpleTestCase
class TestSRS:
@@ -20,7 +23,8 @@ srlist = (
'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,'
'AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],'
'PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",'
- '0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]',
+ '0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],'
+ 'AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]',
epsg=4326, projected=False, geographic=True, local=False,
lin_name='unknown', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
auth={'GEOGCS': ('EPSG', '4326'), 'spheroid': ('EPSG', '7030')},
@@ -30,14 +34,14 @@ srlist = (
'PROJCS["NAD83 / Texas South Central",GEOGCS["NAD83",DATUM["North_American_Datum_1983",'
'SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],'
'AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],'
- 'UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],'
+ 'UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],'
'AUTHORITY["EPSG","4269"]],PROJECTION["Lambert_Conformal_Conic_2SP"],'
- 'PARAMETER["standard_parallel_1",30.28333333333333],'
- 'PARAMETER["standard_parallel_2",28.38333333333333],'
- 'PARAMETER["latitude_of_origin",27.83333333333333],'
+ 'PARAMETER["standard_parallel_1",30.2833333333333],'
+ 'PARAMETER["standard_parallel_2",28.3833333333333],'
+ 'PARAMETER["latitude_of_origin",27.8333333333333],'
'PARAMETER["central_meridian",-99],PARAMETER["false_easting",600000],'
'PARAMETER["false_northing",4000000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],'
- 'AUTHORITY["EPSG","32140"]]',
+ 'AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","32140"]]',
epsg=32140, projected=True, geographic=False, local=False,
lin_name='metre', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
auth={'PROJCS': ('EPSG', '32140'), 'spheroid': ('EPSG', '7019'), 'unit': ('EPSG', '9001')},
@@ -48,25 +52,27 @@ srlist = (
),
),
TestSRS(
- 'PROJCS["NAD_1983_StatePlane_Texas_South_Central_FIPS_4204_Feet",'
- 'GEOGCS["GCS_North_American_1983",DATUM["North_American_Datum_1983",'
- 'SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],'
+ 'PROJCS["NAD83 / Texas South Central (ftUS)",'
+ 'GEOGCS["NAD83",DATUM["North_American_Datum_1983",'
+ 'SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],'
+ 'PRIMEM["Greenwich",0],'
'UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],'
- 'PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",13123333.33333333],'
- 'PARAMETER["Central_Meridian",-99.0],PARAMETER["Standard_Parallel_1",28.38333333333333],'
- 'PARAMETER["Standard_Parallel_2",30.28333333333334],PARAMETER["Latitude_Of_Origin",27.83333333333333],'
- 'UNIT["Foot_US",0.3048006096012192]]',
+ 'PARAMETER["false_easting",1968500],PARAMETER["false_northing",13123333.3333333],'
+ 'PARAMETER["central_meridian",-99],PARAMETER["standard_parallel_1",28.3833333333333],'
+ 'PARAMETER["standard_parallel_2",30.2833333333333],PARAMETER["latitude_of_origin",27.8333333333333],'
+ 'UNIT["US survey foot",0.304800609601219],AXIS["Easting",EAST],AXIS["Northing",NORTH]]',
epsg=None, projected=True, geographic=False, local=False,
- lin_name='Foot_US', ang_name='Degree', lin_units=0.3048006096012192, ang_units=0.0174532925199,
+ lin_name='US survey foot', ang_name='Degree', lin_units=0.3048006096012192, ang_units=0.0174532925199,
auth={'PROJCS': (None, None)},
- attr=(('PROJCS|GeOgCs|spheroid', 'GRS_1980'), (('projcs', 9), 'UNIT'), (('projcs', 11), None),),
+ attr=(('PROJCS|GeOgCs|spheroid', 'GRS 1980'), (('projcs', 9), 'UNIT'), (('projcs', 11), 'AXIS'),),
),
# This is really ESRI format, not WKT -- but the import should work the same
TestSRS(
- 'LOCAL_CS["Non-Earth (Meter)",LOCAL_DATUM["Local Datum",0],UNIT["Meter",1.0],AXIS["X",EAST],AXIS["Y",NORTH]]',
+ 'LOCAL_CS["Non-Earth (Meter)",LOCAL_DATUM["Local Datum",32767],'
+ 'UNIT["Meter",1],AXIS["X",EAST],AXIS["Y",NORTH]]',
esri=True, epsg=None, projected=False, geographic=False, local=True,
lin_name='Meter', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
- attr=(('LOCAL_DATUM', 'Local Datum'), ('unit', 'Meter')),
+ attr=(('LOCAL_DATUM', 'Local Datum'),),
),
)
@@ -146,7 +152,7 @@ bad_srlist = (
)
-class SpatialRefTest(unittest.TestCase):
+class SpatialRefTest(SimpleTestCase):
def test01_wkt(self):
"Testing initialization on valid OGC WKT."
@@ -168,7 +174,11 @@ class SpatialRefTest(unittest.TestCase):
"Testing getting the WKT."
for s in srlist:
srs = SpatialReference(s.wkt)
- self.assertEqual(s.wkt, srs.wkt)
+ # GDAL 3 strips UNIT part in the last occurrence.
+ self.assertEqual(
+ s.wkt.replace(',UNIT["Meter",1]', ''),
+ srs.wkt.replace(',UNIT["Meter",1]', ''),
+ )
def test04_proj(self):
"Test PROJ.4 import and export."
@@ -264,11 +274,11 @@ class SpatialRefTest(unittest.TestCase):
'GEOGCS["DHDN",DATUM["Deutsches_Hauptdreiecksnetz",'
'SPHEROID["Bessel 1841",6377397.155,299.1528128,AUTHORITY["EPSG","7004"]],AUTHORITY["EPSG","6314"]],'
'PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],'
- 'UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],'
- 'AUTHORITY["EPSG","4314"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],'
- 'PROJECTION["Cassini_Soldner"],PARAMETER["latitude_of_origin",50.66738711],'
- 'PARAMETER["central_meridian",6.28935703],PARAMETER["false_easting",0],'
- 'PARAMETER["false_northing",0],AUTHORITY["mj10777.de","187939"],AXIS["x",NORTH],AXIS["y",EAST]]'
+ 'UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],'
+ 'AUTHORITY["EPSG","4314"]],PROJECTION["Cassini_Soldner"],'
+ 'PARAMETER["latitude_of_origin",50.66738711],PARAMETER["central_meridian",6.28935703],'
+ 'PARAMETER["false_easting",0],PARAMETER["false_northing",0],'
+ 'UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",NORTH],AXIS["Y",EAST],AUTHORITY["mj10777.de","187939"]]'
)
srs = SpatialReference(wkt)
srs_list = [srs, srs.clone()]
@@ -279,3 +289,31 @@ class SpatialRefTest(unittest.TestCase):
self.assertEqual(srs.wkt, wkt)
self.assertIn('Langschoß', srs.pretty_wkt)
self.assertIn('Langschoß', srs.xml)
+
+ @skipIf(GDAL_VERSION < (3, 0), 'GDAL >= 3.0 is required')
+ def test_axis_order(self):
+ wgs84_trad = SpatialReference(4326, axis_order=AxisOrder.TRADITIONAL)
+ wgs84_auth = SpatialReference(4326, axis_order=AxisOrder.AUTHORITY)
+ # Coordinate interpretation may depend on the srs axis predicate.
+ pt = GEOSGeometry('POINT (992385.4472045 481455.4944650)', 2774)
+ pt_trad = pt.transform(wgs84_trad, clone=True)
+ self.assertAlmostEqual(pt_trad.x, -104.609, 3)
+ self.assertAlmostEqual(pt_trad.y, 38.255, 3)
+ pt_auth = pt.transform(wgs84_auth, clone=True)
+ self.assertAlmostEqual(pt_auth.x, 38.255, 3)
+ self.assertAlmostEqual(pt_auth.y, -104.609, 3)
+ # clone() preserves the axis order.
+ pt_auth = pt.transform(wgs84_auth.clone(), clone=True)
+ self.assertAlmostEqual(pt_auth.x, 38.255, 3)
+ self.assertAlmostEqual(pt_auth.y, -104.609, 3)
+
+ def test_axis_order_invalid(self):
+ msg = 'SpatialReference.axis_order must be an AxisOrder instance.'
+ with self.assertRaisesMessage(ValueError, msg):
+ SpatialReference(4326, axis_order='other')
+
+ @skipIf(GDAL_VERSION > (3, 0), "GDAL < 3.0 doesn't support authority.")
+ def test_axis_order_non_traditional_invalid(self):
+ msg = 'AxisOrder.AUTHORITY is not supported in GDAL < 3.0.'
+ with self.assertRaisesMessage(ValueError, msg):
+ SpatialReference(4326, axis_order=AxisOrder.AUTHORITY)
diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py
index e43561e67c..ca493c87f1 100644
--- a/tests/gis_tests/geos_tests/test_geos.py
+++ b/tests/gis_tests/geos_tests/test_geos.py
@@ -828,8 +828,8 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
gdal.SpatialReference(4326))
new_pnt = pnt.transform(c2w, clone=True)
self.assertEqual(new_pnt.srid, 4326)
- self.assertAlmostEqual(new_pnt.x, 1, 3)
- self.assertAlmostEqual(new_pnt.y, 2, 3)
+ self.assertAlmostEqual(new_pnt.x, 1, 1)
+ self.assertAlmostEqual(new_pnt.y, 2, 1)
def test_mutable_geometries(self):
"Testing the mutability of Polygons and Geometry Collections."
diff --git a/tests/gis_tests/test_geoforms.py b/tests/gis_tests/test_geoforms.py
index 0ce3b5f66b..0360156b50 100644
--- a/tests/gis_tests/test_geoforms.py
+++ b/tests/gis_tests/test_geoforms.py
@@ -28,7 +28,7 @@ class GeometryFieldTest(SimpleTestCase):
# Making the field in a different SRID from that of the geometry, and
# asserting it transforms.
fld = forms.GeometryField(srid=32140)
- tol = 0.0000001
+ tol = 0.0001
xform_geom = GEOSGeometry('POINT (951640.547328465 4219369.26171664)', srid=32140)
# The cleaned geometry is transformed to 32140 (the widget map_srid is 3857).
cleaned_geom = fld.clean('SRID=3857;POINT (-10615777.40976205 3473169.895707852)')
diff --git a/tests/gis_tests/test_spatialrefsys.py b/tests/gis_tests/test_spatialrefsys.py
index 90e8084af1..6c5a1b9218 100644
--- a/tests/gis_tests/test_spatialrefsys.py
+++ b/tests/gis_tests/test_spatialrefsys.py
@@ -11,7 +11,7 @@ test_srs = ({
# Only the beginning, because there are differences depending on installed libs
'srtext': 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84"',
# +ellps=WGS84 has been removed in the 4326 proj string in proj-4.8
- 'proj4_re': r'\+proj=longlat (\+ellps=WGS84 )?(\+datum=WGS84 |\+towgs84=0,0,0,0,0,0,0 )\+no_defs ',
+ 'proj4_re': r'\+proj=longlat (\+ellps=WGS84 )?(\+datum=WGS84 |\+towgs84=0,0,0,0,0,0,0 )\+no_defs ?',
'spheroid': 'WGS 84', 'name': 'WGS 84',
'geographic': True, 'projected': False, 'spatialite': True,
# From proj's "cs2cs -le" and Wikipedia (semi-minor only)
@@ -37,9 +37,9 @@ test_srs = ({
'PROJCS["NAD83 / Texas South Central",GEOGCS["NAD83",'
'DATUM["North_American_Datum_1983",SPHEROID["GRS 1980"'
),
- 'proj4_re': r'\+proj=lcc \+lat_1=30.28333333333333 \+lat_2=28.38333333333333 \+lat_0=27.83333333333333 '
- r'\+lon_0=-99 \+x_0=600000 \+y_0=4000000 (\+ellps=GRS80 )?'
- r'(\+datum=NAD83 |\+towgs84=0,0,0,0,0,0,0 )?\+units=m \+no_defs ',
+ 'proj4_re': r'\+proj=lcc (\+lat_1=30.28333333333333? |\+lat_2=28.38333333333333? |\+lat_0=27.83333333333333? |'
+ r'\+lon_0=-99 ){4}\+x_0=600000 \+y_0=4000000 (\+ellps=GRS80 )?'
+ r'(\+datum=NAD83 |\+towgs84=0,0,0,0,0,0,0 )?\+units=m \+no_defs ?',
'spheroid': 'GRS 1980', 'name': 'NAD83 / Texas South Central',
'geographic': False, 'projected': True, 'spatialite': False,
# From proj's "cs2cs -le" and Wikipedia (semi-minor only)