Fixed #12410 -- Added LineLocatePoint GIS function.
This commit is contained in:
parent
7b53041420
commit
ede4f6d48c
|
@ -27,10 +27,10 @@ class BaseSpatialOperations:
|
||||||
unsupported_functions = {
|
unsupported_functions = {
|
||||||
'Area', 'AsGeoJSON', 'AsGML', 'AsKML', 'AsSVG',
|
'Area', 'AsGeoJSON', 'AsGML', 'AsKML', 'AsSVG',
|
||||||
'BoundingCircle', 'Centroid', 'Difference', 'Distance', 'Envelope',
|
'BoundingCircle', 'Centroid', 'Difference', 'Distance', 'Envelope',
|
||||||
'ForceRHR', 'GeoHash', 'Intersection', 'IsValid', 'Length', 'MakeValid',
|
'ForceRHR', 'GeoHash', 'Intersection', 'IsValid', 'Length',
|
||||||
'MemSize', 'NumGeometries', 'NumPoints', 'Perimeter', 'PointOnSurface',
|
'LineLocatePoint', 'MakeValid', 'MemSize', 'NumGeometries',
|
||||||
'Reverse', 'Scale', 'SnapToGrid', 'SymDifference', 'Transform',
|
'NumPoints', 'Perimeter', 'PointOnSurface', 'Reverse', 'Scale',
|
||||||
'Translate', 'Union',
|
'SnapToGrid', 'SymDifference', 'Transform', 'Translate', 'Union',
|
||||||
}
|
}
|
||||||
|
|
||||||
# Constructors
|
# Constructors
|
||||||
|
|
|
@ -73,8 +73,9 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
|
||||||
def unsupported_functions(self):
|
def unsupported_functions(self):
|
||||||
unsupported = {
|
unsupported = {
|
||||||
'AsGML', 'AsKML', 'AsSVG', 'BoundingCircle', 'ForceRHR',
|
'AsGML', 'AsKML', 'AsSVG', 'BoundingCircle', 'ForceRHR',
|
||||||
'MakeValid', 'MemSize', 'Perimeter', 'PointOnSurface', 'Reverse',
|
'LineLocatePoint', 'MakeValid', 'MemSize', 'Perimeter',
|
||||||
'Scale', 'SnapToGrid', 'Transform', 'Translate',
|
'PointOnSurface', 'Reverse', 'Scale', 'SnapToGrid', 'Transform',
|
||||||
|
'Translate',
|
||||||
}
|
}
|
||||||
if self.connection.mysql_version < (5, 7, 5):
|
if self.connection.mysql_version < (5, 7, 5):
|
||||||
unsupported.update({'AsGeoJSON', 'GeoHash', 'IsValid'})
|
unsupported.update({'AsGeoJSON', 'GeoHash', 'IsValid'})
|
||||||
|
|
|
@ -112,7 +112,8 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
|
||||||
|
|
||||||
unsupported_functions = {
|
unsupported_functions = {
|
||||||
'AsGeoJSON', 'AsKML', 'AsSVG', 'Envelope', 'ForceRHR', 'GeoHash',
|
'AsGeoJSON', 'AsKML', 'AsSVG', 'Envelope', 'ForceRHR', 'GeoHash',
|
||||||
'MakeValid', 'MemSize', 'Scale', 'SnapToGrid', 'Translate',
|
'LineLocatePoint', 'MakeValid', 'MemSize', 'Scale', 'SnapToGrid',
|
||||||
|
'Translate',
|
||||||
}
|
}
|
||||||
|
|
||||||
def geo_quote_name(self, name):
|
def geo_quote_name(self, name):
|
||||||
|
|
|
@ -81,6 +81,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
|
||||||
def function_names(self):
|
def function_names(self):
|
||||||
return {
|
return {
|
||||||
'Length': 'ST_Length',
|
'Length': 'ST_Length',
|
||||||
|
'LineLocatePoint': 'ST_Line_Locate_Point',
|
||||||
'NumPoints': 'ST_NPoints',
|
'NumPoints': 'ST_NPoints',
|
||||||
'Reverse': 'ST_Reverse',
|
'Reverse': 'ST_Reverse',
|
||||||
'Scale': 'ScaleCoords',
|
'Scale': 'ScaleCoords',
|
||||||
|
|
|
@ -389,6 +389,12 @@ class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc):
|
||||||
return super().as_sql(compiler, connection, function=function)
|
return super().as_sql(compiler, connection, function=function)
|
||||||
|
|
||||||
|
|
||||||
|
class LineLocatePoint(GeoFunc):
|
||||||
|
output_field_class = FloatField
|
||||||
|
arity = 2
|
||||||
|
geom_param_pos = (0, 1)
|
||||||
|
|
||||||
|
|
||||||
class MakeValid(GeoFunc):
|
class MakeValid(GeoFunc):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -386,6 +386,7 @@ Function PostGIS Oracle MySQL Spat
|
||||||
:class:`Intersection` X X X (≥ 5.6.1) X
|
:class:`Intersection` X X X (≥ 5.6.1) X
|
||||||
:class:`IsValid` X X X (≥ 5.7.5) X (LWGEOM)
|
:class:`IsValid` X X X (≥ 5.7.5) X (LWGEOM)
|
||||||
:class:`Length` X X X X
|
:class:`Length` X X X X
|
||||||
|
:class:`LineLocatePoint` X X
|
||||||
:class:`MakeValid` X X (LWGEOM)
|
:class:`MakeValid` X X (LWGEOM)
|
||||||
:class:`MemSize` X
|
:class:`MemSize` X
|
||||||
:class:`NumGeometries` X X X X
|
:class:`NumGeometries` X X X X
|
||||||
|
|
|
@ -358,6 +358,19 @@ resource-intensive) with the ``spheroid`` keyword argument.
|
||||||
In older versions, a raw value was returned on MySQL when used on
|
In older versions, a raw value was returned on MySQL when used on
|
||||||
projected SRS.
|
projected SRS.
|
||||||
|
|
||||||
|
``LineLocatePoint``
|
||||||
|
===================
|
||||||
|
|
||||||
|
.. class:: LineLocatePoint(linestring, point, **extra)
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
*Availability*: `PostGIS <https://postgis.net/docs/ST_LineLocatePoint.html>`__,
|
||||||
|
SpatiaLite
|
||||||
|
|
||||||
|
Returns a float between 0 and 1 representing the location of the closest point on
|
||||||
|
``linestring`` to the given ``point``, as a fraction of the 2D line length.
|
||||||
|
|
||||||
``MakeValid``
|
``MakeValid``
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,9 @@ Minor features
|
||||||
:class:`~django.contrib.gis.db.models.functions.IsValid` function, and
|
:class:`~django.contrib.gis.db.models.functions.IsValid` function, and
|
||||||
:lookup:`isvalid` lookup.
|
:lookup:`isvalid` lookup.
|
||||||
|
|
||||||
|
* Added the :class:`~django.contrib.gis.db.models.functions.LineLocatePoint`
|
||||||
|
function, supported on PostGIS and SpatiaLite.
|
||||||
|
|
||||||
:mod:`django.contrib.messages`
|
:mod:`django.contrib.messages`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,11 @@ class GISFunctionsTests(TestCase):
|
||||||
with self.assertRaisesMessage(ValueError, 'AreaField only accepts Area measurement objects.'):
|
with self.assertRaisesMessage(ValueError, 'AreaField only accepts Area measurement objects.'):
|
||||||
qs.get(area__lt=500000)
|
qs.get(area__lt=500000)
|
||||||
|
|
||||||
|
@skipUnlessDBFeature("has_LineLocatePoint_function")
|
||||||
|
def test_line_locate_point(self):
|
||||||
|
pos_expr = functions.LineLocatePoint(LineString((0, 0), (0, 3), srid=4326), Point(0, 1, srid=4326))
|
||||||
|
self.assertAlmostEqual(State.objects.annotate(pos=pos_expr).first().pos, 0.3333333)
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_MakeValid_function")
|
@skipUnlessDBFeature("has_MakeValid_function")
|
||||||
def test_make_valid(self):
|
def test_make_valid(self):
|
||||||
invalid_geom = fromstr('POLYGON((0 0, 0 1, 1 1, 1 0, 1 1, 1 0, 0 0))')
|
invalid_geom = fromstr('POLYGON((0 0, 0 1, 1 1, 1 0, 1 1, 1 0, 0 0))')
|
||||||
|
|
Loading…
Reference in New Issue