Skip to content

Commit

Permalink
Refs #35058 -- Added support for measured geometries to GDAL LineString.
Browse files Browse the repository at this point in the history
  • Loading branch information
smithdc1 authored and felixxm committed Jan 29, 2024
1 parent 41aaf5a commit 1df8983
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 11 deletions.
18 changes: 15 additions & 3 deletions django/contrib/gis/gdal/geometries.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,10 +625,14 @@ class LineString(OGRGeometry):
def __getitem__(self, index):
"Return the Point at the given index."
if 0 <= index < self.point_count:
x, y, z = c_double(), c_double(), c_double()
capi.get_point(self.ptr, index, byref(x), byref(y), byref(z))
x, y, z, m = c_double(), c_double(), c_double(), c_double()
capi.get_point(self.ptr, index, byref(x), byref(y), byref(z), byref(m))
if self.is_3d and self.is_measured:
return x.value, y.value, z.value, m.value
if self.is_3d:
return x.value, y.value, z.value
if self.is_measured:
return x.value, y.value, m.value
dim = self.coord_dim
if dim == 1:
return (x.value,)
Expand Down Expand Up @@ -673,6 +677,12 @@ def z(self):
if self.is_3d:
return self._listarr(capi.getz)

@property
def m(self):
"""Return the M coordinates in a list."""
if self.is_measured:
return self._listarr(capi.getm)


# LinearRings are used in Polygons.
class LinearRing(LineString):
Expand Down Expand Up @@ -789,9 +799,11 @@ class MultiPolygon(GeometryCollection):
7: GeometryCollection,
101: LinearRing,
2001: Point, # POINT M
2002: LineString, # LINESTRING M
3001: Point, # POINT ZM
3002: LineString, # LINESTRING ZM
1 + OGRGeomType.wkb25bit: Point, # POINT Z
2 + OGRGeomType.wkb25bit: LineString,
2 + OGRGeomType.wkb25bit: LineString, # LINESTRING Z
3 + OGRGeomType.wkb25bit: Polygon,
4 + OGRGeomType.wkb25bit: MultiPoint,
5 + OGRGeomType.wkb25bit: MultiLineString,
Expand Down
11 changes: 9 additions & 2 deletions django/contrib/gis/gdal/prototypes/geom.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,15 @@ def topology_func(f):
get_geom_type = int_output(lgdal.OGR_G_GetGeometryType, [c_void_p])
get_point_count = int_output(lgdal.OGR_G_GetPointCount, [c_void_p])
get_point = void_output(
lgdal.OGR_G_GetPoint,
[c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)],
lgdal.OGR_G_GetPointZM,
[
c_void_p,
c_int,
POINTER(c_double),
POINTER(c_double),
POINTER(c_double),
POINTER(c_double),
],
errcheck=False,
)
geom_close_rings = void_output(lgdal.OGR_G_CloseRings, [c_void_p], errcheck=False)
Expand Down
11 changes: 11 additions & 0 deletions docs/ref/contrib/gis/gdal.txt
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,17 @@ coordinate transformation:
>>> OGRGeometry("LINESTRING (1 2 3,4 5 6)").z
[3.0, 6.0]

.. attribute:: m

.. versionadded:: 5.1

Returns a list of M coordinates in this line or ``None`` if the line does
not have M coordinates:

.. code-block:: pycon

>>> OGRGeometry("LINESTRING(0 1 2 10, 1 2 3 11, 2 3 4 12)").m
[10.0, 11.0, 12.0]

.. class:: Polygon

Expand Down
9 changes: 5 additions & 4 deletions docs/releases/5.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ Minor features
* The new :meth:`.OGRGeometry.set_3d` method allows addition and removal of the
``Z`` coordinate dimension.

* :class:`~django.contrib.gis.gdal.OGRGeometry` and
:class:`~django.contrib.gis.gdal.Point` now support measured geometries
via the new :attr:`.OGRGeometry.is_measured` and :attr:`.Point.m` properties,
and the :meth:`.OGRGeometry.set_measured` method.
* :class:`~django.contrib.gis.gdal.OGRGeometry`,
:class:`~django.contrib.gis.gdal.Point`, and
:class:`~django.contrib.gis.gdal.LineString` now support measured geometries
via the new :attr:`.OGRGeometry.is_measured` and ``m`` properties, and the
:meth:`.OGRGeometry.set_measured` method.

* :attr:`.OGRGeometry.centroid` is now available on all supported geometry
types.
Expand Down
19 changes: 17 additions & 2 deletions tests/gis_tests/gdal_tests/test_geom.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ def test_geometry_types(self):
("TIN Z", 1016, False),
("Triangle Z", 1017, False),
("Point M", 2001, True),
("LineString M", 2002, False),
("LineString M", 2002, True),
("Polygon M", 2003, False),
("MultiPoint M", 2004, False),
("MultiLineString M", 2005, False),
Expand All @@ -688,7 +688,7 @@ def test_geometry_types(self):
("TIN M", 2016, False),
("Triangle M", 2017, False),
("Point ZM", 3001, True),
("LineString ZM", 3002, False),
("LineString ZM", 3002, True),
("Polygon ZM", 3003, False),
("MultiPoint ZM", 3004, False),
("MultiLineString ZM", 3005, False),
Expand Down Expand Up @@ -900,6 +900,21 @@ def test_centroid(self):
)
self.assertEqual(geometrycollection.centroid.wkt, "POINT (110 30)")

def test_linestring_m_dimension(self):
geom = OGRGeometry("LINESTRING(0 1 2 10, 1 2 3 11, 2 3 4 12)")
self.assertIs(geom.is_measured, True)
self.assertEqual(geom.m, [10.0, 11.0, 12.0])
self.assertEqual(geom[0], (0.0, 1.0, 2.0, 10.0))

geom = OGRGeometry("LINESTRING M (0 1 10, 1 2 11)")
self.assertIs(geom.is_measured, True)
self.assertEqual(geom.m, [10.0, 11.0])
self.assertEqual(geom[0], (0.0, 1.0, 10.0))

geom.set_measured(False)
self.assertIs(geom.is_measured, False)
self.assertIs(geom.m, None)


class DeprecationTests(SimpleTestCase):
def test_coord_setter_deprecation(self):
Expand Down

0 comments on commit 1df8983

Please sign in to comment.