Fixed #30678 -- Added support for GDAL 3.
This commit is contained in:
parent
0668164b4a
commit
58f1b07e49
|
@ -37,11 +37,13 @@ from django.contrib.gis.gdal.libgdal import (
|
||||||
GDAL_VERSION, gdal_full_version, gdal_version,
|
GDAL_VERSION, gdal_full_version, gdal_version,
|
||||||
)
|
)
|
||||||
from django.contrib.gis.gdal.raster.source import GDALRaster
|
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__ = (
|
__all__ = (
|
||||||
'Driver', 'DataSource', 'CoordTransform', 'Envelope', 'GDALException',
|
'AxisOrder', 'Driver', 'DataSource', 'CoordTransform', 'Envelope',
|
||||||
'GDALRaster', 'GDAL_VERSION', 'OGRGeometry', 'OGRGeomType',
|
'GDALException', 'GDALRaster', 'GDAL_VERSION', 'OGRGeometry',
|
||||||
'SpatialReference', 'SRSException', 'check_err', 'gdal_version',
|
'OGRGeomType', 'SpatialReference', 'SRSException', 'check_err',
|
||||||
'gdal_full_version',
|
'gdal_version', 'gdal_full_version',
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from ctypes import POINTER, c_char_p, c_int, c_void_p
|
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 (
|
from django.contrib.gis.gdal.prototypes.generation import (
|
||||||
const_string_output, double_output, int_output, srs_output, string_output,
|
const_string_output, double_output, int_output, srs_output, string_output,
|
||||||
void_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)
|
destroy_srs = void_output(std_call('OSRDestroySpatialReference'), [c_void_p], errcheck=False)
|
||||||
srs_validate = void_output(lgdal.OSRValidate, [c_void_p])
|
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.
|
# Getting the semi_major, semi_minor, and flattening functions.
|
||||||
semi_major = srs_double(lgdal.OSRGetSemiMajor)
|
semi_major = srs_double(lgdal.OSRGetSemiMajor)
|
||||||
semi_minor = srs_double(lgdal.OSRGetSemiMinor)
|
semi_minor = srs_double(lgdal.OSRGetSemiMinor)
|
||||||
|
|
|
@ -27,13 +27,20 @@
|
||||||
NAD83 / Texas South Central
|
NAD83 / Texas South Central
|
||||||
"""
|
"""
|
||||||
from ctypes import byref, c_char_p, c_int
|
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.base import GDALBase
|
||||||
from django.contrib.gis.gdal.error import SRSException
|
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.contrib.gis.gdal.prototypes import srs as capi
|
||||||
from django.utils.encoding import force_bytes, force_str
|
from django.utils.encoding import force_bytes, force_str
|
||||||
|
|
||||||
|
|
||||||
|
class AxisOrder(IntEnum):
|
||||||
|
TRADITIONAL = 0
|
||||||
|
AUTHORITY = 1
|
||||||
|
|
||||||
|
|
||||||
class SpatialReference(GDALBase):
|
class SpatialReference(GDALBase):
|
||||||
"""
|
"""
|
||||||
A wrapper for the OGRSpatialReference object. According to the GDAL Web site,
|
A wrapper for the OGRSpatialReference object. According to the GDAL Web site,
|
||||||
|
@ -42,17 +49,25 @@ class SpatialReference(GDALBase):
|
||||||
"""
|
"""
|
||||||
destructor = capi.release_srs
|
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.
|
Create a GDAL OSR Spatial Reference object from the given input.
|
||||||
The input may be string of OGC Well Known Text (WKT), an integer
|
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
|
EPSG code, a PROJ.4 string, and/or a projection "well known" shorthand
|
||||||
string (one of 'WGS84', 'WGS72', 'NAD27', 'NAD83').
|
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':
|
if srs_type == 'wkt':
|
||||||
self.ptr = capi.new_srs(c_char_p(b''))
|
self.ptr = capi.new_srs(c_char_p(b''))
|
||||||
self.import_wkt(srs_input)
|
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
|
return
|
||||||
elif isinstance(srs_input, str):
|
elif isinstance(srs_input, str):
|
||||||
try:
|
try:
|
||||||
|
@ -85,6 +100,10 @@ class SpatialReference(GDALBase):
|
||||||
else:
|
else:
|
||||||
self.ptr = srs
|
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.
|
# Importing from either the user input string or an integer SRID.
|
||||||
if srs_type == 'user':
|
if srs_type == 'user':
|
||||||
self.import_user_input(srs_input)
|
self.import_user_input(srs_input)
|
||||||
|
@ -143,7 +162,7 @@ class SpatialReference(GDALBase):
|
||||||
|
|
||||||
def clone(self):
|
def clone(self):
|
||||||
"Return a clone of this SpatialReference object."
|
"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):
|
def from_esri(self):
|
||||||
"Morph this SpatialReference from ESRI's format to EPSG."
|
"Morph this SpatialReference from ESRI's format to EPSG."
|
||||||
|
|
|
@ -434,7 +434,7 @@ class GEOSGeometryBase(GEOSBase):
|
||||||
if self.srid:
|
if self.srid:
|
||||||
try:
|
try:
|
||||||
return gdal.SpatialReference(self.srid)
|
return gdal.SpatialReference(self.srid)
|
||||||
except gdal.SRSException:
|
except (gdal.GDALException, gdal.SRSException):
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ geospatial libraries:
|
||||||
Program Description Required Supported Versions
|
Program Description Required Supported Versions
|
||||||
======================== ==================================== ================================ ===================================
|
======================== ==================================== ================================ ===================================
|
||||||
:doc:`GEOS <../geos>` Geometry Engine Open Source Yes 3.7, 3.6, 3.5
|
: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
|
`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 2.4, 2.3, 2.2, 2.1, 2.0
|
: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
|
: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
|
`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
|
`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.2.0 2017-05
|
||||||
GDAL 2.3.0 2018-05
|
GDAL 2.3.0 2018-05
|
||||||
GDAL 2.4.0 2018-12
|
GDAL 2.4.0 2018-12
|
||||||
|
GDAL 3.0.0 2019-05
|
||||||
PostGIS 2.2.0 2015-10-17
|
PostGIS 2.2.0 2015-10-17
|
||||||
PostGIS 2.3.0 2016-09-26
|
PostGIS 2.3.0 2016-09-26
|
||||||
PostGIS 2.4.0 2017-09-30
|
PostGIS 2.4.0 2017-09-30
|
||||||
|
|
|
@ -145,7 +145,7 @@ Minor features
|
||||||
* Added the :class:`~django.contrib.gis.db.models.functions.AsWKB` and
|
* Added the :class:`~django.contrib.gis.db.models.functions.AsWKB` and
|
||||||
:class:`~django.contrib.gis.db.models.functions.AsWKT` functions.
|
: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`
|
:mod:`django.contrib.humanize`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -146,7 +146,11 @@ class GDALRasterTests(SimpleTestCase):
|
||||||
|
|
||||||
# Reload newly created raster from file
|
# Reload newly created raster from file
|
||||||
restored_raster = GDALRaster(rstfile.name)
|
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)
|
self.assertEqual(restored_raster.geotransform, self.rs.geotransform)
|
||||||
if numpy:
|
if numpy:
|
||||||
numpy.testing.assert_equal(
|
numpy.testing.assert_equal(
|
||||||
|
@ -322,54 +326,33 @@ class GDALRasterTests(SimpleTestCase):
|
||||||
with self.assertRaisesMessage(ValueError, msg):
|
with self.assertRaisesMessage(ValueError, msg):
|
||||||
self.rs.info
|
self.rs.info
|
||||||
return
|
return
|
||||||
gdalinfo = """
|
infos = self.rs.info
|
||||||
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)
|
|
||||||
# Data
|
# Data
|
||||||
info_dyn = [line.strip() for line in self.rs.info.split('\n') if line.strip() != '']
|
info_lines = [line.strip() for line in infos.split('\n') if line.strip() != '']
|
||||||
info_ref = [line.strip() for line in gdalinfo.split('\n') if line.strip() != '']
|
for line in [
|
||||||
self.assertEqual(info_dyn, info_ref)
|
'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):
|
def test_compressed_file_based_raster_creation(self):
|
||||||
rstfile = tempfile.NamedTemporaryFile(suffix='.tif')
|
rstfile = tempfile.NamedTemporaryFile(suffix='.tif')
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import unittest
|
from unittest import skipIf
|
||||||
|
|
||||||
from django.contrib.gis.gdal import (
|
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:
|
class TestSRS:
|
||||||
|
@ -20,7 +23,8 @@ srlist = (
|
||||||
'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,'
|
'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"]],'
|
'AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],'
|
||||||
'PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",'
|
'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,
|
epsg=4326, projected=False, geographic=True, local=False,
|
||||||
lin_name='unknown', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
|
lin_name='unknown', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
|
||||||
auth={'GEOGCS': ('EPSG', '4326'), 'spheroid': ('EPSG', '7030')},
|
auth={'GEOGCS': ('EPSG', '4326'), 'spheroid': ('EPSG', '7030')},
|
||||||
|
@ -30,14 +34,14 @@ srlist = (
|
||||||
'PROJCS["NAD83 / Texas South Central",GEOGCS["NAD83",DATUM["North_American_Datum_1983",'
|
'PROJCS["NAD83 / Texas South Central",GEOGCS["NAD83",DATUM["North_American_Datum_1983",'
|
||||||
'SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],'
|
'SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],'
|
||||||
'AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],'
|
'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"],'
|
'AUTHORITY["EPSG","4269"]],PROJECTION["Lambert_Conformal_Conic_2SP"],'
|
||||||
'PARAMETER["standard_parallel_1",30.28333333333333],'
|
'PARAMETER["standard_parallel_1",30.2833333333333],'
|
||||||
'PARAMETER["standard_parallel_2",28.38333333333333],'
|
'PARAMETER["standard_parallel_2",28.3833333333333],'
|
||||||
'PARAMETER["latitude_of_origin",27.83333333333333],'
|
'PARAMETER["latitude_of_origin",27.8333333333333],'
|
||||||
'PARAMETER["central_meridian",-99],PARAMETER["false_easting",600000],'
|
'PARAMETER["central_meridian",-99],PARAMETER["false_easting",600000],'
|
||||||
'PARAMETER["false_northing",4000000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],'
|
'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,
|
epsg=32140, projected=True, geographic=False, local=False,
|
||||||
lin_name='metre', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
|
lin_name='metre', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
|
||||||
auth={'PROJCS': ('EPSG', '32140'), 'spheroid': ('EPSG', '7019'), 'unit': ('EPSG', '9001')},
|
auth={'PROJCS': ('EPSG', '32140'), 'spheroid': ('EPSG', '7019'), 'unit': ('EPSG', '9001')},
|
||||||
|
@ -48,25 +52,27 @@ srlist = (
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TestSRS(
|
TestSRS(
|
||||||
'PROJCS["NAD_1983_StatePlane_Texas_South_Central_FIPS_4204_Feet",'
|
'PROJCS["NAD83 / Texas South Central (ftUS)",'
|
||||||
'GEOGCS["GCS_North_American_1983",DATUM["North_American_Datum_1983",'
|
'GEOGCS["NAD83",DATUM["North_American_Datum_1983",'
|
||||||
'SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],'
|
'SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],'
|
||||||
|
'PRIMEM["Greenwich",0],'
|
||||||
'UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],'
|
'UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],'
|
||||||
'PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",13123333.33333333],'
|
'PARAMETER["false_easting",1968500],PARAMETER["false_northing",13123333.3333333],'
|
||||||
'PARAMETER["Central_Meridian",-99.0],PARAMETER["Standard_Parallel_1",28.38333333333333],'
|
'PARAMETER["central_meridian",-99],PARAMETER["standard_parallel_1",28.3833333333333],'
|
||||||
'PARAMETER["Standard_Parallel_2",30.28333333333334],PARAMETER["Latitude_Of_Origin",27.83333333333333],'
|
'PARAMETER["standard_parallel_2",30.2833333333333],PARAMETER["latitude_of_origin",27.8333333333333],'
|
||||||
'UNIT["Foot_US",0.3048006096012192]]',
|
'UNIT["US survey foot",0.304800609601219],AXIS["Easting",EAST],AXIS["Northing",NORTH]]',
|
||||||
epsg=None, projected=True, geographic=False, local=False,
|
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)},
|
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
|
# This is really ESRI format, not WKT -- but the import should work the same
|
||||||
TestSRS(
|
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,
|
esri=True, epsg=None, projected=False, geographic=False, local=True,
|
||||||
lin_name='Meter', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
|
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):
|
def test01_wkt(self):
|
||||||
"Testing initialization on valid OGC WKT."
|
"Testing initialization on valid OGC WKT."
|
||||||
|
@ -168,7 +174,11 @@ class SpatialRefTest(unittest.TestCase):
|
||||||
"Testing getting the WKT."
|
"Testing getting the WKT."
|
||||||
for s in srlist:
|
for s in srlist:
|
||||||
srs = SpatialReference(s.wkt)
|
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):
|
def test04_proj(self):
|
||||||
"Test PROJ.4 import and export."
|
"Test PROJ.4 import and export."
|
||||||
|
@ -264,11 +274,11 @@ class SpatialRefTest(unittest.TestCase):
|
||||||
'GEOGCS["DHDN",DATUM["Deutsches_Hauptdreiecksnetz",'
|
'GEOGCS["DHDN",DATUM["Deutsches_Hauptdreiecksnetz",'
|
||||||
'SPHEROID["Bessel 1841",6377397.155,299.1528128,AUTHORITY["EPSG","7004"]],AUTHORITY["EPSG","6314"]],'
|
'SPHEROID["Bessel 1841",6377397.155,299.1528128,AUTHORITY["EPSG","7004"]],AUTHORITY["EPSG","6314"]],'
|
||||||
'PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],'
|
'PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],'
|
||||||
'UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],'
|
'UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],'
|
||||||
'AUTHORITY["EPSG","4314"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],'
|
'AUTHORITY["EPSG","4314"]],PROJECTION["Cassini_Soldner"],'
|
||||||
'PROJECTION["Cassini_Soldner"],PARAMETER["latitude_of_origin",50.66738711],'
|
'PARAMETER["latitude_of_origin",50.66738711],PARAMETER["central_meridian",6.28935703],'
|
||||||
'PARAMETER["central_meridian",6.28935703],PARAMETER["false_easting",0],'
|
'PARAMETER["false_easting",0],PARAMETER["false_northing",0],'
|
||||||
'PARAMETER["false_northing",0],AUTHORITY["mj10777.de","187939"],AXIS["x",NORTH],AXIS["y",EAST]]'
|
'UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",NORTH],AXIS["Y",EAST],AUTHORITY["mj10777.de","187939"]]'
|
||||||
)
|
)
|
||||||
srs = SpatialReference(wkt)
|
srs = SpatialReference(wkt)
|
||||||
srs_list = [srs, srs.clone()]
|
srs_list = [srs, srs.clone()]
|
||||||
|
@ -279,3 +289,31 @@ class SpatialRefTest(unittest.TestCase):
|
||||||
self.assertEqual(srs.wkt, wkt)
|
self.assertEqual(srs.wkt, wkt)
|
||||||
self.assertIn('Langschoß', srs.pretty_wkt)
|
self.assertIn('Langschoß', srs.pretty_wkt)
|
||||||
self.assertIn('Langschoß', srs.xml)
|
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)
|
||||||
|
|
|
@ -828,8 +828,8 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
|
||||||
gdal.SpatialReference(4326))
|
gdal.SpatialReference(4326))
|
||||||
new_pnt = pnt.transform(c2w, clone=True)
|
new_pnt = pnt.transform(c2w, clone=True)
|
||||||
self.assertEqual(new_pnt.srid, 4326)
|
self.assertEqual(new_pnt.srid, 4326)
|
||||||
self.assertAlmostEqual(new_pnt.x, 1, 3)
|
self.assertAlmostEqual(new_pnt.x, 1, 1)
|
||||||
self.assertAlmostEqual(new_pnt.y, 2, 3)
|
self.assertAlmostEqual(new_pnt.y, 2, 1)
|
||||||
|
|
||||||
def test_mutable_geometries(self):
|
def test_mutable_geometries(self):
|
||||||
"Testing the mutability of Polygons and Geometry Collections."
|
"Testing the mutability of Polygons and Geometry Collections."
|
||||||
|
|
|
@ -28,7 +28,7 @@ class GeometryFieldTest(SimpleTestCase):
|
||||||
# Making the field in a different SRID from that of the geometry, and
|
# Making the field in a different SRID from that of the geometry, and
|
||||||
# asserting it transforms.
|
# asserting it transforms.
|
||||||
fld = forms.GeometryField(srid=32140)
|
fld = forms.GeometryField(srid=32140)
|
||||||
tol = 0.0000001
|
tol = 0.0001
|
||||||
xform_geom = GEOSGeometry('POINT (951640.547328465 4219369.26171664)', srid=32140)
|
xform_geom = GEOSGeometry('POINT (951640.547328465 4219369.26171664)', srid=32140)
|
||||||
# The cleaned geometry is transformed to 32140 (the widget map_srid is 3857).
|
# The cleaned geometry is transformed to 32140 (the widget map_srid is 3857).
|
||||||
cleaned_geom = fld.clean('SRID=3857;POINT (-10615777.40976205 3473169.895707852)')
|
cleaned_geom = fld.clean('SRID=3857;POINT (-10615777.40976205 3473169.895707852)')
|
||||||
|
|
|
@ -11,7 +11,7 @@ test_srs = ({
|
||||||
# Only the beginning, because there are differences depending on installed libs
|
# Only the beginning, because there are differences depending on installed libs
|
||||||
'srtext': 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84"',
|
'srtext': 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84"',
|
||||||
# +ellps=WGS84 has been removed in the 4326 proj string in proj-4.8
|
# +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',
|
'spheroid': 'WGS 84', 'name': 'WGS 84',
|
||||||
'geographic': True, 'projected': False, 'spatialite': True,
|
'geographic': True, 'projected': False, 'spatialite': True,
|
||||||
# From proj's "cs2cs -le" and Wikipedia (semi-minor only)
|
# From proj's "cs2cs -le" and Wikipedia (semi-minor only)
|
||||||
|
@ -37,9 +37,9 @@ test_srs = ({
|
||||||
'PROJCS["NAD83 / Texas South Central",GEOGCS["NAD83",'
|
'PROJCS["NAD83 / Texas South Central",GEOGCS["NAD83",'
|
||||||
'DATUM["North_American_Datum_1983",SPHEROID["GRS 1980"'
|
'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 '
|
'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'\+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 ',
|
r'(\+datum=NAD83 |\+towgs84=0,0,0,0,0,0,0 )?\+units=m \+no_defs ?',
|
||||||
'spheroid': 'GRS 1980', 'name': 'NAD83 / Texas South Central',
|
'spheroid': 'GRS 1980', 'name': 'NAD83 / Texas South Central',
|
||||||
'geographic': False, 'projected': True, 'spatialite': False,
|
'geographic': False, 'projected': True, 'spatialite': False,
|
||||||
# From proj's "cs2cs -le" and Wikipedia (semi-minor only)
|
# From proj's "cs2cs -le" and Wikipedia (semi-minor only)
|
||||||
|
|
Loading…
Reference in New Issue