Fixed #25950 -- Added support for GEOSisClosed.

This commit is contained in:
Sergey Fedoseev 2015-12-18 15:26:22 +05:00 committed by Tim Graham
parent 64ba7d8252
commit 5d348bba31
8 changed files with 60 additions and 24 deletions

View File

@ -7,10 +7,9 @@ import warnings
from ctypes import byref, c_int, c_uint from ctypes import byref, c_int, c_uint
from django.contrib.gis.geos import prototypes as capi from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.geometry import ( from django.contrib.gis.geos.error import GEOSException
GEOSGeometry, ProjectInterpolateMixin, from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin
) from django.contrib.gis.geos.libgeos import geos_version_info, get_pointer_arr
from django.contrib.gis.geos.libgeos import get_pointer_arr
from django.contrib.gis.geos.linestring import LinearRing, LineString from django.contrib.gis.geos.linestring import LinearRing, LineString
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
@ -114,17 +113,15 @@ class MultiPoint(GeometryCollection):
_typeid = 4 _typeid = 4
class MultiLineString(ProjectInterpolateMixin, GeometryCollection): class MultiLineString(LinearGeometryMixin, GeometryCollection):
_allowed = (LineString, LinearRing) _allowed = (LineString, LinearRing)
_typeid = 5 _typeid = 5
@property @property
def merged(self): def closed(self):
""" if geos_version_info()['version'] < '3.5':
Returns a LineString representing the line merge of this raise GEOSException("MultiLineString.closed requires GEOS >= 3.5.0.")
MultiLineString. return super(MultiLineString, self).closed
"""
return self._topology(capi.geos_linemerge(self.ptr))
class MultiPolygon(GeometryCollection): class MultiPolygon(GeometryCollection):

View File

@ -685,7 +685,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
return GEOSGeometry(capi.geom_clone(self.ptr), srid=self.srid) return GEOSGeometry(capi.geom_clone(self.ptr), srid=self.srid)
class ProjectInterpolateMixin(object): class LinearGeometryMixin(object):
""" """
Used for LineString and MultiLineString. Used for LineString and MultiLineString.
""" """
@ -706,3 +706,17 @@ class ProjectInterpolateMixin(object):
if not isinstance(point, Point): if not isinstance(point, Point):
raise TypeError('locate_point argument must be a Point') raise TypeError('locate_point argument must be a Point')
return capi.geos_project_normalized(self.ptr, point.ptr) return capi.geos_project_normalized(self.ptr, point.ptr)
@property
def merged(self):
"""
Return the line merge of this Geometry.
"""
return self._topology(capi.geos_linemerge(self.ptr))
@property
def closed(self):
"""
Return whether or not this Geometry is closed.
"""
return capi.geos_isclosed(self.ptr)

View File

@ -1,15 +1,13 @@
from django.contrib.gis.geos import prototypes as capi from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.coordseq import GEOSCoordSeq from django.contrib.gis.geos.coordseq import GEOSCoordSeq
from django.contrib.gis.geos.error import GEOSException from django.contrib.gis.geos.error import GEOSException
from django.contrib.gis.geos.geometry import ( from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin
GEOSGeometry, ProjectInterpolateMixin,
)
from django.contrib.gis.geos.point import Point from django.contrib.gis.geos.point import Point
from django.contrib.gis.shortcuts import numpy from django.contrib.gis.shortcuts import numpy
from django.utils.six.moves import range from django.utils.six.moves import range
class LineString(ProjectInterpolateMixin, GEOSGeometry): class LineString(LinearGeometryMixin, GEOSGeometry):
_init_func = capi.create_linestring _init_func = capi.create_linestring
_minlength = 2 _minlength = 2
has_cs = True has_cs = True
@ -154,11 +152,6 @@ class LineString(ProjectInterpolateMixin, GEOSGeometry):
"Returns a numpy array for the LineString." "Returns a numpy array for the LineString."
return self._listarr(self._cs.__getitem__) return self._listarr(self._cs.__getitem__)
@property
def merged(self):
"Returns the line merge of this LineString."
return self._topology(capi.geos_linemerge(self.ptr))
@property @property
def x(self): def x(self):
"Returns a list or numpy array of the X variable." "Returns a list or numpy array of the X variable."

View File

@ -19,8 +19,8 @@ from django.contrib.gis.geos.prototypes.geom import ( # NOQA
from django.contrib.gis.geos.prototypes.misc import * # NOQA from django.contrib.gis.geos.prototypes.misc import * # NOQA
from django.contrib.gis.geos.prototypes.predicates import ( # NOQA from django.contrib.gis.geos.prototypes.predicates import ( # NOQA
geos_contains, geos_covers, geos_crosses, geos_disjoint, geos_equals, geos_contains, geos_covers, geos_crosses, geos_disjoint, geos_equals,
geos_equalsexact, geos_hasz, geos_intersects, geos_isempty, geos_isring, geos_equalsexact, geos_hasz, geos_intersects, geos_isclosed, geos_isempty,
geos_issimple, geos_isvalid, geos_overlaps, geos_relatepattern, geos_isring, geos_issimple, geos_isvalid, geos_overlaps,
geos_touches, geos_within, geos_relatepattern, geos_touches, geos_within,
) )
from django.contrib.gis.geos.prototypes.topology import * # NOQA from django.contrib.gis.geos.prototypes.topology import * # NOQA

View File

@ -23,6 +23,7 @@ class BinaryPredicate(UnaryPredicate):
# ## Unary Predicates ## # ## Unary Predicates ##
geos_hasz = UnaryPredicate('GEOSHasZ') geos_hasz = UnaryPredicate('GEOSHasZ')
geos_isclosed = UnaryPredicate('GEOSisClosed')
geos_isempty = UnaryPredicate('GEOSisEmpty') geos_isempty = UnaryPredicate('GEOSisEmpty')
geos_isring = UnaryPredicate('GEOSisRing') geos_isring = UnaryPredicate('GEOSisRing')
geos_issimple = UnaryPredicate('GEOSisSimple') geos_issimple = UnaryPredicate('GEOSisSimple')

View File

@ -694,6 +694,12 @@ is returned instead.
In previous versions, an empty ``LineString`` couldn't be instantiated. In previous versions, an empty ``LineString`` couldn't be instantiated.
.. attribute:: closed
.. versionadded:: 1.10
Returns whether or not this ``LineString`` is closed.
``LinearRing`` ``LinearRing``
-------------- --------------
@ -790,6 +796,11 @@ Geometry Collections
Returns a :class:`LineString` representing the line merge of Returns a :class:`LineString` representing the line merge of
all the components in this ``MultiLineString``. all the components in this ``MultiLineString``.
.. attribute:: closed
.. versionadded:: 1.10
Returns ``True`` if and only if all elements are closed. Requires GEOS 3.5.
``MultiPolygon`` ``MultiPolygon``
---------------- ----------------

View File

@ -104,6 +104,11 @@ Minor features
of :class:`~django.contrib.gis.geos.WKTWriter` allow controlling of :class:`~django.contrib.gis.geos.WKTWriter` allow controlling
output of the fractional part of the coordinates in WKT. output of the fractional part of the coordinates in WKT.
* Added the :attr:`LineString.closed
<django.contrib.gis.geos.LineString.closed>` and
:attr:`MultiLineString.closed
<django.contrib.gis.geos.MultiLineString.closed>` properties.
:mod:`django.contrib.messages` :mod:`django.contrib.messages`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -15,6 +15,7 @@ from django.contrib.gis.geos import (
fromfile, fromstr, fromfile, fromstr,
) )
from django.contrib.gis.geos.base import GEOSBase from django.contrib.gis.geos.base import GEOSBase
from django.contrib.gis.geos.libgeos import geos_version_info
from django.contrib.gis.shortcuts import numpy from django.contrib.gis.shortcuts import numpy
from django.template import Context from django.template import Context
from django.template.engine import Engine from django.template.engine import Engine
@ -660,6 +661,20 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
self.assertTrue(poly.covers(Point(5, 5))) self.assertTrue(poly.covers(Point(5, 5)))
self.assertFalse(poly.covers(Point(100, 100))) self.assertFalse(poly.covers(Point(100, 100)))
def test_closed(self):
ls_closed = LineString((0, 0), (1, 1), (0, 0))
ls_not_closed = LineString((0, 0), (1, 1))
self.assertFalse(ls_not_closed.closed)
self.assertTrue(ls_closed.closed)
if geos_version_info()['version'] >= '3.5':
self.assertFalse(MultiLineString(ls_closed, ls_not_closed).closed)
self.assertTrue(MultiLineString(ls_closed, ls_closed).closed)
with mock.patch('django.contrib.gis.geos.collections.geos_version_info', lambda: {'version': '3.4.9'}):
with self.assertRaisesMessage(GEOSException, "MultiLineString.closed requires GEOS >= 3.5.0."):
MultiLineString().closed
def test_srid(self): def test_srid(self):
"Testing the SRID property and keyword." "Testing the SRID property and keyword."
# Testing SRID keyword on Point # Testing SRID keyword on Point