Fixed #12410 -- Added LineLocatePoint GIS function.
This commit is contained in:
parent
7b53041420
commit
ede4f6d48c
|
@ -27,10 +27,10 @@ class BaseSpatialOperations:
|
|||
unsupported_functions = {
|
||||
'Area', 'AsGeoJSON', 'AsGML', 'AsKML', 'AsSVG',
|
||||
'BoundingCircle', 'Centroid', 'Difference', 'Distance', 'Envelope',
|
||||
'ForceRHR', 'GeoHash', 'Intersection', 'IsValid', 'Length', 'MakeValid',
|
||||
'MemSize', 'NumGeometries', 'NumPoints', 'Perimeter', 'PointOnSurface',
|
||||
'Reverse', 'Scale', 'SnapToGrid', 'SymDifference', 'Transform',
|
||||
'Translate', 'Union',
|
||||
'ForceRHR', 'GeoHash', 'Intersection', 'IsValid', 'Length',
|
||||
'LineLocatePoint', 'MakeValid', 'MemSize', 'NumGeometries',
|
||||
'NumPoints', 'Perimeter', 'PointOnSurface', 'Reverse', 'Scale',
|
||||
'SnapToGrid', 'SymDifference', 'Transform', 'Translate', 'Union',
|
||||
}
|
||||
|
||||
# Constructors
|
||||
|
|
|
@ -73,8 +73,9 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
|
|||
def unsupported_functions(self):
|
||||
unsupported = {
|
||||
'AsGML', 'AsKML', 'AsSVG', 'BoundingCircle', 'ForceRHR',
|
||||
'MakeValid', 'MemSize', 'Perimeter', 'PointOnSurface', 'Reverse',
|
||||
'Scale', 'SnapToGrid', 'Transform', 'Translate',
|
||||
'LineLocatePoint', 'MakeValid', 'MemSize', 'Perimeter',
|
||||
'PointOnSurface', 'Reverse', 'Scale', 'SnapToGrid', 'Transform',
|
||||
'Translate',
|
||||
}
|
||||
if self.connection.mysql_version < (5, 7, 5):
|
||||
unsupported.update({'AsGeoJSON', 'GeoHash', 'IsValid'})
|
||||
|
|
|
@ -112,7 +112,8 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
|
|||
|
||||
unsupported_functions = {
|
||||
'AsGeoJSON', 'AsKML', 'AsSVG', 'Envelope', 'ForceRHR', 'GeoHash',
|
||||
'MakeValid', 'MemSize', 'Scale', 'SnapToGrid', 'Translate',
|
||||
'LineLocatePoint', 'MakeValid', 'MemSize', 'Scale', 'SnapToGrid',
|
||||
'Translate',
|
||||
}
|
||||
|
||||
def geo_quote_name(self, name):
|
||||
|
|
|
@ -81,6 +81,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
|
|||
def function_names(self):
|
||||
return {
|
||||
'Length': 'ST_Length',
|
||||
'LineLocatePoint': 'ST_Line_Locate_Point',
|
||||
'NumPoints': 'ST_NPoints',
|
||||
'Reverse': 'ST_Reverse',
|
||||
'Scale': 'ScaleCoords',
|
||||
|
|
|
@ -389,6 +389,12 @@ class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc):
|
|||
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):
|
||||
pass
|
||||
|
||||
|
|
|
@ -386,6 +386,7 @@ Function PostGIS Oracle MySQL Spat
|
|||
:class:`Intersection` X X X (≥ 5.6.1) X
|
||||
:class:`IsValid` X X X (≥ 5.7.5) X (LWGEOM)
|
||||
:class:`Length` X X X X
|
||||
:class:`LineLocatePoint` X X
|
||||
:class:`MakeValid` X X (LWGEOM)
|
||||
:class:`MemSize` 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
|
||||
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``
|
||||
=============
|
||||
|
||||
|
|
|
@ -68,6 +68,9 @@ Minor features
|
|||
:class:`~django.contrib.gis.db.models.functions.IsValid` function, and
|
||||
:lookup:`isvalid` lookup.
|
||||
|
||||
* Added the :class:`~django.contrib.gis.db.models.functions.LineLocatePoint`
|
||||
function, supported on PostGIS and SpatiaLite.
|
||||
|
||||
:mod:`django.contrib.messages`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -286,6 +286,11 @@ class GISFunctionsTests(TestCase):
|
|||
with self.assertRaisesMessage(ValueError, 'AreaField only accepts Area measurement objects.'):
|
||||
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")
|
||||
def test_make_valid(self):
|
||||
invalid_geom = fromstr('POLYGON((0 0, 0 1, 1 1, 1 0, 1 1, 1 0, 0 0))')
|
||||
|
|
Loading…
Reference in New Issue