Dropped support for GEOS < 3.1

This commit is contained in:
Claude Paroz 2013-12-24 15:57:13 +01:00
parent 542198c1d0
commit d17404aa90
11 changed files with 51 additions and 121 deletions

View File

@ -6,9 +6,9 @@ for more details:
__all__ = ['HAS_GEOS'] __all__ = ['HAS_GEOS']
try: try:
from .libgeos import geos_version, geos_version_info, GEOS_PREPARE # NOQA: flake8 detects only the last __all__ from .libgeos import geos_version, geos_version_info # NOQA: flake8 detects only the last __all__
HAS_GEOS = True HAS_GEOS = True
__all__ += ['geos_version', 'geos_version_info', 'GEOS_PREPARE'] __all__ += ['geos_version', 'geos_version_info']
except ImportError: except ImportError:
HAS_GEOS = False HAS_GEOS = False

View File

@ -3,9 +3,8 @@
GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon
""" """
from ctypes import c_int, c_uint, byref from ctypes import c_int, c_uint, byref
from django.contrib.gis.geos.error import GEOSException
from django.contrib.gis.geos.geometry import GEOSGeometry from django.contrib.gis.geos.geometry import GEOSGeometry
from django.contrib.gis.geos.libgeos import get_pointer_arr, GEOS_PREPARE from django.contrib.gis.geos.libgeos import get_pointer_arr
from django.contrib.gis.geos.linestring import LineString, LinearRing from django.contrib.gis.geos.linestring import LineString, LinearRing
from django.contrib.gis.geos.point import Point from django.contrib.gis.geos.point import Point
from django.contrib.gis.geos.polygon import Polygon from django.contrib.gis.geos.polygon import Polygon
@ -119,10 +118,7 @@ class MultiPolygon(GeometryCollection):
@property @property
def cascaded_union(self): def cascaded_union(self):
"Returns a cascaded union of this MultiPolygon." "Returns a cascaded union of this MultiPolygon."
if GEOS_PREPARE:
return GEOSGeometry(capi.geos_cascaded_union(self.ptr), self.srid) return GEOSGeometry(capi.geos_cascaded_union(self.ptr), self.srid)
else:
raise GEOSException('The cascaded union operation requires GEOS 3.1+.')
# Setting the allowed types here since GeometryCollection is defined before # Setting the allowed types here since GeometryCollection is defined before
# its subclasses. # its subclasses.

View File

@ -17,7 +17,7 @@ from django.contrib.gis.gdal.error import SRSException
from django.contrib.gis.geos.base import GEOSBase, gdal from django.contrib.gis.geos.base import GEOSBase, gdal
from django.contrib.gis.geos.coordseq import GEOSCoordSeq from django.contrib.gis.geos.coordseq import GEOSCoordSeq
from django.contrib.gis.geos.error import GEOSException, GEOSIndexError from django.contrib.gis.geos.error import GEOSException, GEOSIndexError
from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOS_PREPARE from django.contrib.gis.geos.libgeos import GEOM_PTR
# All other functions in this module come from the ctypes # All other functions in this module come from the ctypes
# prototypes module -- which handles all interaction with # prototypes module -- which handles all interaction with
@ -289,8 +289,6 @@ class GEOSGeometry(GEOSBase, ListMixin):
""" """
Returns a string containing the reason for any invalidity. Returns a string containing the reason for any invalidity.
""" """
if not GEOS_PREPARE:
raise GEOSException('Upgrade GEOS to 3.1 to get validity reason.')
return capi.geos_isvalidreason(self.ptr).decode() return capi.geos_isvalidreason(self.ptr).decode()
#### Binary predicates. #### #### Binary predicates. ####
@ -411,9 +409,6 @@ class GEOSGeometry(GEOSBase, ListMixin):
extension of the WKB specification that includes SRID value that are extension of the WKB specification that includes SRID value that are
a part of this geometry. a part of this geometry.
""" """
if self.hasz and not GEOS_PREPARE:
# See: http://trac.osgeo.org/geos/ticket/216
raise GEOSException('Upgrade GEOS to 3.1 to get valid 3D HEXEWKB.')
return ewkb_w(3 if self.hasz else 2).write_hex(self) return ewkb_w(3 if self.hasz else 2).write_hex(self)
@property @property
@ -443,9 +438,6 @@ class GEOSGeometry(GEOSBase, ListMixin):
This is an extension of the WKB specification that includes any SRID This is an extension of the WKB specification that includes any SRID
value that are a part of this geometry. value that are a part of this geometry.
""" """
if self.hasz and not GEOS_PREPARE:
# See: http://trac.osgeo.org/geos/ticket/216
raise GEOSException('Upgrade GEOS to 3.1 to get valid 3D EWKB.')
return ewkb_w(3 if self.hasz else 2).write(self) return ewkb_w(3 if self.hasz else 2).write(self)
@property @property
@ -460,10 +452,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
Returns a PreparedGeometry corresponding to this geometry -- it is Returns a PreparedGeometry corresponding to this geometry -- it is
optimized for the contains, intersects, and covers operations. optimized for the contains, intersects, and covers operations.
""" """
if GEOS_PREPARE:
return PreparedGeometry(self) return PreparedGeometry(self)
else:
raise GEOSException('GEOS 3.1+ required for prepared geometry support.')
#### GDAL-specific output routines #### #### GDAL-specific output routines ####
@property @property
@ -707,7 +696,9 @@ from django.contrib.gis.geos.linestring import LineString, LinearRing
from django.contrib.gis.geos.point import Point from django.contrib.gis.geos.point import Point
from django.contrib.gis.geos.polygon import Polygon from django.contrib.gis.geos.polygon import Polygon
from django.contrib.gis.geos.collections import GeometryCollection, MultiPoint, MultiLineString, MultiPolygon from django.contrib.gis.geos.collections import GeometryCollection, MultiPoint, MultiLineString, MultiPolygon
GEOS_CLASSES = {0: Point, from django.contrib.gis.geos.prepared import PreparedGeometry
GEOS_CLASSES = {
0: Point,
1: LineString, 1: LineString,
2: LinearRing, 2: LinearRing,
3: Polygon, 3: Polygon,
@ -715,8 +706,4 @@ GEOS_CLASSES = {0: Point,
5: MultiLineString, 5: MultiLineString,
6: MultiPolygon, 6: MultiPolygon,
7: GeometryCollection, 7: GeometryCollection,
} }
# If supported, import the PreparedGeometry class.
if GEOS_PREPARE:
from django.contrib.gis.geos.prepared import PreparedGeometry

View File

@ -155,22 +155,10 @@ GEOS_MINOR_VERSION = int(_verinfo['minor'])
GEOS_SUBMINOR_VERSION = int(_verinfo['subminor']) GEOS_SUBMINOR_VERSION = int(_verinfo['subminor'])
del _verinfo del _verinfo
GEOS_VERSION = (GEOS_MAJOR_VERSION, GEOS_MINOR_VERSION, GEOS_SUBMINOR_VERSION) GEOS_VERSION = (GEOS_MAJOR_VERSION, GEOS_MINOR_VERSION, GEOS_SUBMINOR_VERSION)
GEOS_PREPARE = GEOS_VERSION >= (3, 1, 0)
if GEOS_PREPARE: # Here we set up the prototypes for the initGEOS_r and finishGEOS_r
# Here we set up the prototypes for the initGEOS_r and finishGEOS_r # routines. These functions aren't actually called until they are
# routines. These functions aren't actually called until they are # attached to a GEOS context handle -- this actually occurs in
# attached to a GEOS context handle -- this actually occurs in # geos/prototypes/threadsafe.py.
# geos/prototypes/threadsafe.py. lgeos.initGEOS_r.restype = CONTEXT_PTR
lgeos.initGEOS_r.restype = CONTEXT_PTR lgeos.finishGEOS_r.argtypes = [CONTEXT_PTR]
lgeos.finishGEOS_r.argtypes = [CONTEXT_PTR]
else:
# When thread-safety isn't available, the initGEOS routine must be called
# first. This function takes the notice and error functions, defined
# as Python callbacks above, as parameters. Here is the C code that is
# wrapped:
# extern void GEOS_DLL initGEOS(GEOSMessageHandler notice_function, GEOSMessageHandler error_function);
lgeos.initGEOS(notice_h, error_h)
# Calling finishGEOS() upon exit of the interpreter.
import atexit
atexit.register(lgeos.finishGEOS)

View File

@ -3,13 +3,13 @@
ones that return the area, distance, and length. ones that return the area, distance, and length.
""" """
from ctypes import c_int, c_double, POINTER from ctypes import c_int, c_double, POINTER
from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOS_PREPARE from django.contrib.gis.geos.libgeos import GEOM_PTR
from django.contrib.gis.geos.prototypes.errcheck import check_dbl, check_string from django.contrib.gis.geos.prototypes.errcheck import check_dbl, check_string
from django.contrib.gis.geos.prototypes.geom import geos_char_p from django.contrib.gis.geos.prototypes.geom import geos_char_p
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
from django.utils.six.moves import xrange from django.utils.six.moves import xrange
__all__ = ['geos_area', 'geos_distance', 'geos_length'] __all__ = ['geos_area', 'geos_distance', 'geos_length', 'geos_isvalidreason']
### ctypes generator function ### ### ctypes generator function ###
@ -31,11 +31,7 @@ def dbl_from_geom(func, num_geom=1):
geos_area = dbl_from_geom(GEOSFunc('GEOSArea')) geos_area = dbl_from_geom(GEOSFunc('GEOSArea'))
geos_distance = dbl_from_geom(GEOSFunc('GEOSDistance'), num_geom=2) geos_distance = dbl_from_geom(GEOSFunc('GEOSDistance'), num_geom=2)
geos_length = dbl_from_geom(GEOSFunc('GEOSLength')) geos_length = dbl_from_geom(GEOSFunc('GEOSLength'))
geos_isvalidreason = GEOSFunc('GEOSisValidReason')
# Validity reason; only in GEOS 3.1+ geos_isvalidreason.argtypes = [GEOM_PTR]
if GEOS_PREPARE: geos_isvalidreason.restype = geos_char_p
geos_isvalidreason = GEOSFunc('GEOSisValidReason') geos_isvalidreason.errcheck = check_string
geos_isvalidreason.argtypes = [GEOM_PTR]
geos_isvalidreason.restype = geos_char_p
geos_isvalidreason.errcheck = check_string
__all__.append('geos_isvalidreason')

View File

@ -2,13 +2,14 @@
This module houses the GEOS ctypes prototype functions for the This module houses the GEOS ctypes prototype functions for the
topological operations on geometries. topological operations on geometries.
""" """
__all__ = ['geos_boundary', 'geos_buffer', 'geos_centroid', 'geos_convexhull', __all__ = ['geos_boundary', 'geos_buffer', 'geos_cascaded_union',
'geos_difference', 'geos_envelope', 'geos_intersection', 'geos_centroid', 'geos_convexhull', 'geos_difference',
'geos_linemerge', 'geos_pointonsurface', 'geos_preservesimplify', 'geos_envelope', 'geos_intersection', 'geos_linemerge',
'geos_simplify', 'geos_symdifference', 'geos_union', 'geos_relate'] 'geos_pointonsurface', 'geos_preservesimplify', 'geos_simplify',
'geos_symdifference', 'geos_union', 'geos_relate']
from ctypes import c_double, c_int from ctypes import c_double, c_int
from django.contrib.gis.geos.libgeos import geos_version_info, GEOM_PTR, GEOS_PREPARE from django.contrib.gis.geos.libgeos import geos_version_info, GEOM_PTR
from django.contrib.gis.geos.prototypes.errcheck import check_geom, check_minus_one, check_string from django.contrib.gis.geos.prototypes.errcheck import check_geom, check_minus_one, check_string
from django.contrib.gis.geos.prototypes.geom import geos_char_p from django.contrib.gis.geos.prototypes.geom import geos_char_p
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
@ -39,19 +40,16 @@ geos_simplify = topology(GEOSFunc('GEOSSimplify'), c_double)
geos_symdifference = topology(GEOSFunc('GEOSSymDifference'), GEOM_PTR) geos_symdifference = topology(GEOSFunc('GEOSSymDifference'), GEOM_PTR)
geos_union = topology(GEOSFunc('GEOSUnion'), GEOM_PTR) geos_union = topology(GEOSFunc('GEOSUnion'), GEOM_PTR)
geos_cascaded_union = GEOSFunc('GEOSUnionCascaded')
geos_cascaded_union.argtypes = [GEOM_PTR]
geos_cascaded_union.restype = GEOM_PTR
# GEOSRelate returns a string, not a geometry. # GEOSRelate returns a string, not a geometry.
geos_relate = GEOSFunc('GEOSRelate') geos_relate = GEOSFunc('GEOSRelate')
geos_relate.argtypes = [GEOM_PTR, GEOM_PTR] geos_relate.argtypes = [GEOM_PTR, GEOM_PTR]
geos_relate.restype = geos_char_p geos_relate.restype = geos_char_p
geos_relate.errcheck = check_string geos_relate.errcheck = check_string
# Routines only in GEOS 3.1+
if GEOS_PREPARE:
geos_cascaded_union = GEOSFunc('GEOSUnionCascaded')
geos_cascaded_union.argtypes = [GEOM_PTR]
geos_cascaded_union.restype = GEOM_PTR
__all__.append('geos_cascaded_union')
# Linear referencing routines # Linear referencing routines
info = geos_version_info() info = geos_version_info()
if info['version'] >= '3.2.0': if info['version'] >= '3.2.0':

View File

@ -22,8 +22,7 @@ from .. import HAS_GEOS
if HAS_GEOS: if HAS_GEOS:
from .. import (GEOSException, GEOSIndexError, GEOSGeometry, from .. import (GEOSException, GEOSIndexError, GEOSGeometry,
GeometryCollection, Point, MultiPoint, Polygon, MultiPolygon, LinearRing, GeometryCollection, Point, MultiPoint, Polygon, MultiPolygon, LinearRing,
LineString, MultiLineString, fromfile, fromstr, geos_version_info, LineString, MultiLineString, fromfile, fromstr, geos_version_info)
GEOS_PREPARE)
from ..base import gdal, numpy, GEOSBase from ..base import gdal, numpy, GEOSBase
@ -121,20 +120,12 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
# a bug in versions prior to 3.1 that puts the X coordinate in # a bug in versions prior to 3.1 that puts the X coordinate in
# place of Z; an exception should be raised on those versions. # place of Z; an exception should be raised on those versions.
self.assertEqual(hexewkb_2d, pnt_2d.hexewkb) self.assertEqual(hexewkb_2d, pnt_2d.hexewkb)
if GEOS_PREPARE:
self.assertEqual(hexewkb_3d, pnt_3d.hexewkb) self.assertEqual(hexewkb_3d, pnt_3d.hexewkb)
self.assertEqual(True, GEOSGeometry(hexewkb_3d).hasz) self.assertEqual(True, GEOSGeometry(hexewkb_3d).hasz)
else:
with self.assertRaises(GEOSException):
pnt_3d.hexewkb
# Same for EWKB. # Same for EWKB.
self.assertEqual(memoryview(a2b_hex(hexewkb_2d)), pnt_2d.ewkb) self.assertEqual(memoryview(a2b_hex(hexewkb_2d)), pnt_2d.ewkb)
if GEOS_PREPARE:
self.assertEqual(memoryview(a2b_hex(hexewkb_3d)), pnt_3d.ewkb) self.assertEqual(memoryview(a2b_hex(hexewkb_3d)), pnt_3d.ewkb)
else:
with self.assertRaises(GEOSException):
pnt_3d.ewkb
# Redundant sanity check. # Redundant sanity check.
self.assertEqual(4326, GEOSGeometry(hexewkb_2d).srid) self.assertEqual(4326, GEOSGeometry(hexewkb_2d).srid)
@ -869,7 +860,6 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
self.assertIsInstance(g1.ogr, gdal.OGRGeometry) self.assertIsInstance(g1.ogr, gdal.OGRGeometry)
self.assertIsNone(g1.srs) self.assertIsNone(g1.srs)
if GEOS_PREPARE:
g1_3d = fromstr('POINT(5 23 8)') g1_3d = fromstr('POINT(5 23 8)')
self.assertIsInstance(g1_3d.ogr, gdal.OGRGeometry) self.assertIsInstance(g1_3d.ogr, gdal.OGRGeometry)
self.assertEqual(g1_3d.ogr.z, 8) self.assertEqual(g1_3d.ogr.z, 8)
@ -918,10 +908,7 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
def test_transform_3d(self): def test_transform_3d(self):
p3d = GEOSGeometry('POINT (5 23 100)', 4326) p3d = GEOSGeometry('POINT (5 23 100)', 4326)
p3d.transform(2774) p3d.transform(2774)
if GEOS_PREPARE:
self.assertEqual(p3d.z, 100) self.assertEqual(p3d.z, 100)
else:
self.assertIsNone(p3d.z)
@skipUnless(HAS_GDAL, "GDAL is required.") @skipUnless(HAS_GDAL, "GDAL is required.")
def test_transform_noop(self): def test_transform_noop(self):
@ -1030,7 +1017,6 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
if not no_srid: if not no_srid:
self.assertEqual(geom.srid, tmpg.srid) self.assertEqual(geom.srid, tmpg.srid)
@skipUnless(HAS_GEOS and GEOS_PREPARE, "geos >= 3.1.0 is required")
def test_prepared(self): def test_prepared(self):
"Testing PreparedGeometry support." "Testing PreparedGeometry support."
# Creating a simple multipolygon and getting a prepared version. # Creating a simple multipolygon and getting a prepared version.
@ -1061,7 +1047,6 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
for geom, merged in zip(ref_geoms, ref_merged): for geom, merged in zip(ref_geoms, ref_merged):
self.assertEqual(merged, geom.merged) self.assertEqual(merged, geom.merged)
@skipUnless(HAS_GEOS and GEOS_PREPARE, "geos >= 3.1.0 is required")
def test_valid_reason(self): def test_valid_reason(self):
"Testing IsValidReason support" "Testing IsValidReason support"

View File

@ -282,10 +282,6 @@ Returns the EWKB of this Geometry in hexadecimal form. This is an
extension of the WKB specification that includes the SRID value extension of the WKB specification that includes the SRID value
that are a part of this geometry. that are a part of this geometry.
.. note::
GEOS 3.1 is *required* if you want valid 3D HEXEWKB.
.. attribute:: GEOSGeometry.json .. attribute:: GEOSGeometry.json
Returns the GeoJSON representation of the geometry. Returns the GeoJSON representation of the geometry.
@ -329,10 +325,6 @@ Return the EWKB representation of this Geometry as a Python buffer.
This is an extension of the WKB specification that includes any SRID This is an extension of the WKB specification that includes any SRID
value that are a part of this geometry. value that are a part of this geometry.
.. note::
GEOS 3.1 is *required* if you want valid 3D EWKB.
.. attribute:: GEOSGeometry.wkt .. attribute:: GEOSGeometry.wkt
Returns the Well-Known Text of the geometry (an OGC standard). Returns the Well-Known Text of the geometry (an OGC standard).
@ -533,10 +525,6 @@ a :class:`Polygon`).
.. attribute:: GEOSGeometry.prepared .. attribute:: GEOSGeometry.prepared
.. note::
Support for prepared geometries requires GEOS 3.1.
Returns a GEOS ``PreparedGeometry`` for the contents of this geometry. Returns a GEOS ``PreparedGeometry`` for the contents of this geometry.
``PreparedGeometry`` objects are optimized for the contains, intersects, ``PreparedGeometry`` objects are optimized for the contains, intersects,
and covers operations. Refer to the :ref:`prepared-geometries` documentation and covers operations. Refer to the :ref:`prepared-geometries` documentation
@ -710,10 +698,6 @@ Geometry Collections
more efficient (faster) than trying to union the geometries together more efficient (faster) than trying to union the geometries together
individually. [#fncascadedunion]_ individually. [#fncascadedunion]_
.. note::
GEOS 3.1 is *required* to peform cascaded unions.
``GeometryCollection`` ``GeometryCollection``
---------------------- ----------------------
@ -740,10 +724,6 @@ geometry can be orders of magnitude faster -- the more complex the geometry
that is prepared, the larger the speedup in the operation. For more information, that is prepared, the larger the speedup in the operation. For more information,
please consult the `GEOS wiki page on prepared geometries <http://trac.osgeo.org/geos/wiki/PreparedGeometry>`_. please consult the `GEOS wiki page on prepared geometries <http://trac.osgeo.org/geos/wiki/PreparedGeometry>`_.
.. note::
GEOS 3.1 is *required* in order to use prepared geometries.
For example:: For example::
>>> from django.contrib.gis.geos import Point, Polygon >>> from django.contrib.gis.geos import Point, Polygon

View File

@ -10,7 +10,7 @@ geospatial libraries:
======================== ==================================== ================================ ========================== ======================== ==================================== ================================ ==========================
Program Description Required Supported Versions Program Description Required Supported Versions
======================== ==================================== ================================ ========================== ======================== ==================================== ================================ ==========================
:ref:`GEOS <ref-geos>` Geometry Engine Open Source Yes 3.3, 3.2, 3.1, 3.0 :ref:`GEOS <ref-geos>` Geometry Engine Open Source Yes 3.3, 3.2, 3.1
`PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 4.8, 4.7, 4.6, 4.5, 4.4 `PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 4.8, 4.7, 4.6, 4.5, 4.4
:ref:`GDAL <ref-gdal>` Geospatial Data Abstraction Library No (but, required for SQLite) 1.9, 1.8, 1.7, 1.6 :ref:`GDAL <ref-gdal>` Geospatial Data Abstraction Library No (but, required for SQLite) 1.9, 1.8, 1.7, 1.6
:ref:`GeoIP <ref-geoip>` IP-based geolocation library No 1.4 :ref:`GeoIP <ref-geoip>` IP-based geolocation library No 1.4
@ -20,7 +20,6 @@ Program Description Required
.. ..
Libs release dates: Libs release dates:
GEOS 3.0.0 2008-08-14
GEOS 3.1.0 2009-03-11 GEOS 3.1.0 2009-03-11
GEOS 3.2.0 2009-12-14 GEOS 3.2.0 2009-12-14
GEOS 3.3.0 2011-05-30 GEOS 3.3.0 2011-05-30

View File

@ -172,8 +172,7 @@ three-dimensonal support.
.. note:: .. note::
At this time 3D support requires that GEOS 3.1 be installed, and is At this time 3D support is limited to the PostGIS spatial backend.
limited only to the PostGIS spatial backend.
``geography`` ``geography``
------------- -------------

View File

@ -722,6 +722,8 @@ Miscellaneous
``select_related('foo').select_related('bar')``. Previously the latter would ``select_related('foo').select_related('bar')``. Previously the latter would
have been equivalent to ``select_related('bar')``. have been equivalent to ``select_related('bar')``.
* GeoDjango dropped support for GEOS < 3.1.
Features deprecated in 1.7 Features deprecated in 1.7
========================== ==========================