From 2005530920e7c290bb1cf7d9ada155250faa81ad Mon Sep 17 00:00:00 2001 From: David Smith Date: Sun, 28 Jan 2024 08:41:25 +0000 Subject: [PATCH] Refs #35058 -- Made centroid available on all geometry types. Centroid is available on all geometry types since GDAL 1.8.0. Previously it was restricted to Polygon. https://gdal.org/doxygen/classOGRGeometry.html#a91787f669b2a148169667e270e7e40df --- django/contrib/gis/gdal/geometries.py | 16 ++++++++-------- docs/ref/contrib/gis/gdal.txt | 13 +++++++++---- docs/releases/5.1.txt | 3 +++ tests/gis_tests/gdal_tests/test_geom.py | 23 +++++++++++++++++++++++ 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py index 4c1f74d4b0..85ef265ad1 100644 --- a/django/contrib/gis/gdal/geometries.py +++ b/django/contrib/gis/gdal/geometries.py @@ -565,6 +565,14 @@ class OGRGeometry(GDALBase): """ return self._geomgen(capi.geom_union, other) + @property + def centroid(self): + """Return the centroid (a Point) of this Polygon.""" + # The centroid is a Point, create a geometry for this. + p = OGRGeometry(OGRGeomType("Point")) + capi.get_centroid(self.ptr, p.ptr) + return p + # The subclasses for OGR Geometry. class Point(OGRGeometry): @@ -708,14 +716,6 @@ class Polygon(OGRGeometry): # Summing up the number of points in each ring of the Polygon. return sum(self[i].point_count for i in range(self.geom_count)) - @property - def centroid(self): - "Return the centroid (a Point) of this Polygon." - # The centroid is a Point, create a geometry for this. - p = OGRGeometry(OGRGeomType("Point")) - capi.get_centroid(self.ptr, p.ptr) - return p - # Geometry Collection base class. class GeometryCollection(OGRGeometry): diff --git a/docs/ref/contrib/gis/gdal.txt b/docs/ref/contrib/gis/gdal.txt index f6e9ef0964..be6e738160 100644 --- a/docs/ref/contrib/gis/gdal.txt +++ b/docs/ref/contrib/gis/gdal.txt @@ -839,6 +839,15 @@ coordinate transformation: Returns the region consisting of the union of this geometry and the other, as a new :class:`OGRGeometry` object. + .. attribute:: centroid + + Returns a :class:`Point` representing the centroid of this geometry. + + .. versionchanged:: 5.1 + + ``centroid`` was promoted from a :class:`.Polygon` only attribute to + being available on all geometry types. + .. attribute:: tuple Returns the coordinates of a point geometry as a tuple, the @@ -939,10 +948,6 @@ coordinate transformation: An alias for :attr:`shell`. - .. attribute:: centroid - - Returns a :class:`Point` representing the centroid of this polygon. - .. class:: GeometryCollection .. method:: add(geom) diff --git a/docs/releases/5.1.txt b/docs/releases/5.1.txt index 463551e85c..34ef350afd 100644 --- a/docs/releases/5.1.txt +++ b/docs/releases/5.1.txt @@ -83,6 +83,9 @@ Minor features via the new :attr:`.OGRGeometry.is_measured` and :attr:`.Point.m` properties, and the :meth:`.OGRGeometry.set_measured` method. +* :attr:`.OGRGeometry.centroid` is now available on all supported geometry + types. + :mod:`django.contrib.messages` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/gis_tests/gdal_tests/test_geom.py b/tests/gis_tests/gdal_tests/test_geom.py index a2aa9d8e36..6bb7aa0724 100644 --- a/tests/gis_tests/gdal_tests/test_geom.py +++ b/tests/gis_tests/gdal_tests/test_geom.py @@ -877,6 +877,29 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin): geom = OGRGeometry("POINT M (1 2 3)") self.assertEqual(geom.geos.wkt, "POINT (1 2)") + def test_centroid(self): + point = OGRGeometry("POINT (1 2 3)") + self.assertEqual(point.centroid.wkt, "POINT (1 2)") + linestring = OGRGeometry("LINESTRING (0 0 0, 1 1 1, 2 2 2)") + self.assertEqual(linestring.centroid.wkt, "POINT (1 1)") + polygon = OGRGeometry("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))") + self.assertEqual(polygon.centroid.wkt, "POINT (5 5)") + multipoint = OGRGeometry("MULTIPOINT (0 0,10 10)") + self.assertEqual(multipoint.centroid.wkt, "POINT (5 5)") + multilinestring = OGRGeometry( + "MULTILINESTRING ((0 0,0 10,0 20),(10 0,10 10,10 20))" + ) + self.assertEqual(multilinestring.centroid.wkt, "POINT (5 10)") + multipolygon = OGRGeometry( + "MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0))," + "((20 20, 20 30, 30 30, 30 20, 20 20)))" + ) + self.assertEqual(multipolygon.centroid.wkt, "POINT (15 15)") + geometrycollection = OGRGeometry( + "GEOMETRYCOLLECTION (POINT (110 260),LINESTRING (110 0,110 60))" + ) + self.assertEqual(geometrycollection.centroid.wkt, "POINT (110 30)") + class DeprecationTests(SimpleTestCase): def test_coord_setter_deprecation(self):