Skip to content

Commit

Permalink
Fixed #35086 -- Added support for BoundedCircle on Spatialite 5.1+.
Browse files Browse the repository at this point in the history
Spatialite 5.1 added support for BoundingCircle
(GEOSMinimumBoundingCircle). GEOS 3.7 is required which is lower than
Django's currently supported minmum of 3.8.

https://groups.google.com/g/spatialite-users/c/hAJ2SgitN4M

https://www.gaia-gis.it/gaia-sins/spatialite-sql-5.1.0.html
  • Loading branch information
smithdc1 authored and felixxm committed Jan 5, 2024
1 parent 9b056aa commit 45f59d0
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 5 deletions.
5 changes: 4 additions & 1 deletion django/contrib/gis/db/backends/spatialite/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):

function_names = {
"AsWKB": "St_AsBinary",
"BoundingCircle": "GEOSMinimumBoundingCircle",
"ForcePolygonCW": "ST_ForceLHR",
"FromWKB": "ST_GeomFromWKB",
"FromWKT": "ST_GeomFromText",
Expand All @@ -80,9 +81,11 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):

@cached_property
def unsupported_functions(self):
unsupported = {"BoundingCircle", "GeometryDistance", "IsEmpty", "MemSize"}
unsupported = {"GeometryDistance", "IsEmpty", "MemSize"}
if not self.geom_lib_version():
unsupported |= {"Azimuth", "GeoHash", "MakeValid"}
if self.spatial_version < (5, 1):
unsupported |= {"BoundingCircle"}
return unsupported

@cached_property
Expand Down
7 changes: 7 additions & 0 deletions django/contrib/gis/db/models/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,13 @@ def as_oracle(self, compiler, connection, **extra_context):
compiler, connection, **extra_context
)

def as_sqlite(self, compiler, connection, **extra_context):
clone = self.copy()
clone.set_source_expressions([self.get_source_expressions()[0]])
return super(BoundingCircle, clone).as_sqlite(
compiler, connection, **extra_context
)


class Centroid(OracleToleranceMixin, GeomOutputGeoFunc):
arity = 1
Expand Down
2 changes: 1 addition & 1 deletion docs/ref/contrib/gis/db-api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ Function PostGIS Oracle MariaDB MySQL
:class:`AsWKB` X X X X X
:class:`AsWKT` X X X X X
:class:`Azimuth` X X (LWGEOM/RTTOPO)
:class:`BoundingCircle` X X
:class:`BoundingCircle` X X X (≥ 5.1)
:class:`Centroid` X X X X X
:class:`ClosestPoint` X X
:class:`Difference` X X X X X
Expand Down
7 changes: 6 additions & 1 deletion docs/ref/contrib/gis/functions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,18 @@ south = ``π``; west = ``3π/2``.

*Availability*: `PostGIS <https://postgis.net/docs/ST_MinimumBoundingCircle.html>`__,
`Oracle <https://docs.oracle.com/en/database/oracle/oracle-database/21/spatl/
SDO_GEOM-reference.html#GUID-82A61626-BB64-4793-B53D-A0DBEC91831A>`_
SDO_GEOM-reference.html#GUID-82A61626-BB64-4793-B53D-A0DBEC91831A>`_,
SpatiaLite 5.1+

Accepts a single geographic field or expression and returns the smallest circle
polygon that can fully contain the geometry.

The ``num_seg`` parameter is used only on PostGIS.

.. versionchanged:: 5.1

SpatiaLite 5.1+ support was added.

``Centroid``
============

Expand Down
3 changes: 2 additions & 1 deletion docs/releases/5.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ Minor features
:mod:`django.contrib.gis`
~~~~~~~~~~~~~~~~~~~~~~~~~

* ...
* :class:`~django.contrib.gis.db.models.functions.BoundingCircle` is now
supported on SpatiaLite 5.1+.

:mod:`django.contrib.messages`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
7 changes: 6 additions & 1 deletion tests/gis_tests/geoapp/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,12 @@ def circle_num_points(num_seg):
# num_seg is the number of segments per quarter circle.
return (4 * num_seg) + 1

expected_areas = (169, 136) if connection.ops.postgis else (171, 126)
if connection.ops.postgis:
expected_areas = (169, 136)
elif connection.ops.spatialite:
expected_areas = (168, 135)
else: # Oracle.
expected_areas = (171, 126)
qs = Country.objects.annotate(
circle=functions.BoundingCircle("mpoly")
).order_by("name")
Expand Down

0 comments on commit 45f59d0

Please sign in to comment.