Fixed #34266 -- Added ClosestPoint GIS database functions.

This commit is contained in:
Niccolò Mineo 2023-01-13 17:48:27 +01:00 committed by Mariusz Felisiak
parent 4b066bde69
commit 79c298c9ce
8 changed files with 42 additions and 5 deletions

View File

@ -42,6 +42,7 @@ class BaseSpatialOperations:
"Azimuth",
"BoundingCircle",
"Centroid",
"ClosestPoint",
"Difference",
"Distance",
"Envelope",

View File

@ -75,6 +75,7 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
"AsSVG",
"Azimuth",
"BoundingCircle",
"ClosestPoint",
"ForcePolygonCW",
"GeometryDistance",
"IsEmpty",

View File

@ -121,6 +121,7 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
"AsKML",
"AsSVG",
"Azimuth",
"ClosestPoint",
"ForcePolygonCW",
"GeoHash",
"GeometryDistance",

View File

@ -280,6 +280,11 @@ class Centroid(OracleToleranceMixin, GeomOutputGeoFunc):
arity = 1
class ClosestPoint(GeomOutputGeoFunc):
arity = 2
geom_param_pos = (0, 1)
class Difference(OracleToleranceMixin, GeomOutputGeoFunc):
arity = 2
geom_param_pos = (0, 1)

View File

@ -356,6 +356,7 @@ Function PostGIS Oracle MariaDB MySQL
:class:`Azimuth` X X (LWGEOM/RTTOPO)
:class:`BoundingCircle` X X
:class:`Centroid` X X X X X
:class:`ClosestPoint` X X
:class:`Difference` X X X X X
:class:`Distance` X X X X X
:class:`Envelope` X X X X X

View File

@ -26,10 +26,10 @@ Measurement Relationships Operations Edi
:class:`Area` :class:`Azimuth` :class:`Difference` :class:`ForcePolygonCW` :class:`AsGeoJSON` :class:`IsEmpty`
:class:`Distance` :class:`BoundingCircle` :class:`Intersection` :class:`MakeValid` :class:`AsGML` :class:`IsValid`
:class:`GeometryDistance` :class:`Centroid` :class:`SymDifference` :class:`Reverse` :class:`AsKML` :class:`MemSize`
:class:`Length` :class:`Envelope` :class:`Union` :class:`Scale` :class:`AsSVG` :class:`NumGeometries`
:class:`Perimeter` :class:`LineLocatePoint` :class:`SnapToGrid` :class:`FromWKB` :class:`AsWKB` :class:`NumPoints`
:class:`PointOnSurface` :class:`Transform` :class:`FromWKT` :class:`AsWKT`
:class:`Translate` :class:`GeoHash`
:class:`Length` :class:`ClosestPoint` :class:`Union` :class:`Scale` :class:`AsSVG` :class:`NumGeometries`
:class:`Perimeter` :class:`Envelope` :class:`SnapToGrid` :class:`FromWKB` :class:`AsWKB` :class:`NumPoints`
:class:`LineLocatePoint` :class:`Transform` :class:`FromWKT` :class:`AsWKT`
:class:`PointOnSurface` :class:`Translate` :class:`GeoHash`
========================= ======================== ====================== ======================= ================== ================== ======================
``Area``
@ -237,6 +237,19 @@ The ``num_seg`` parameter is used only on PostGIS.
Accepts a single geographic field or expression and returns the ``centroid``
value of the geometry.
``ClosestPoint``
================
.. versionadded:: 5.0
.. class:: ClosestPoint(expr1, expr2, **extra)
*Availability*: `PostGIS <https://postgis.net/docs/ST_ClosestPoint.html>`__,
SpatiaLite
Accepts two geographic fields or expressions and returns the 2-dimensional
point on geometry A that is closest to geometry B.
``Difference``
==============

View File

@ -64,7 +64,10 @@ Minor features
:mod:`django.contrib.gis`
~~~~~~~~~~~~~~~~~~~~~~~~~
* ...
* The new
:class:`ClosestPoint() <django.contrib.gis.db.models.functions.ClosestPoint>`
function returns a 2-dimensional point on the geometry that is closest to
another geometry.
:mod:`django.contrib.messages`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -456,6 +456,18 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
):
qs.get(area__lt=500000)
@skipUnlessDBFeature("has_ClosestPoint_function")
def test_closest_point(self):
qs = Country.objects.annotate(
closest_point=functions.ClosestPoint("mpoly", functions.Centroid("mpoly"))
)
for country in qs:
self.assertIsInstance(country.closest_point, Point)
self.assertEqual(
country.mpoly.intersection(country.closest_point),
country.closest_point,
)
@skipUnlessDBFeature("has_LineLocatePoint_function")
def test_line_locate_point(self):
pos_expr = functions.LineLocatePoint(