mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refs #34406 -- Added support for GDAL curved geometries.
Co-authored-by: Fabien Le Frapper <contact@fabienlefrapper.me>
This commit is contained in:
		| @@ -64,6 +64,7 @@ class OGRGeometry(GDALBase): | ||||
|     """Encapsulate an OGR geometry.""" | ||||
|  | ||||
|     destructor = capi.destroy_geom | ||||
|     geos_support = True | ||||
|  | ||||
|     def __init__(self, geom_input, srs=None): | ||||
|         """Initialize Geometry on either WKT or an OGR pointer as input.""" | ||||
| @@ -304,6 +305,19 @@ class OGRGeometry(GDALBase): | ||||
|                 f"Input to 'set_measured' must be a boolean, got '{value!r}'." | ||||
|             ) | ||||
|  | ||||
|     @property | ||||
|     def has_curve(self): | ||||
|         """Return True if the geometry is or has curve geometry.""" | ||||
|         return capi.has_curve_geom(self.ptr, 0) | ||||
|  | ||||
|     def get_linear_geometry(self): | ||||
|         """Return a linear version of this geometry.""" | ||||
|         return OGRGeometry(capi.get_linear_geom(self.ptr, 0, None)) | ||||
|  | ||||
|     def get_curve_geometry(self): | ||||
|         """Return a curve version of this geometry.""" | ||||
|         return OGRGeometry(capi.get_curve_geom(self.ptr, None)) | ||||
|  | ||||
|     # #### SpatialReference-related Properties #### | ||||
|  | ||||
|     # The SRS property | ||||
| @@ -360,9 +374,14 @@ class OGRGeometry(GDALBase): | ||||
|     @property | ||||
|     def geos(self): | ||||
|         "Return a GEOSGeometry object from this OGRGeometry." | ||||
|         from django.contrib.gis.geos import GEOSGeometry | ||||
|         if self.geos_support: | ||||
|             from django.contrib.gis.geos import GEOSGeometry | ||||
|  | ||||
|         return GEOSGeometry(self._geos_ptr(), self.srid) | ||||
|             return GEOSGeometry(self._geos_ptr(), self.srid) | ||||
|         else: | ||||
|             from django.contrib.gis.geos import GEOSException | ||||
|  | ||||
|             raise GEOSException(f"GEOS does not support {self.__class__.__qualname__}.") | ||||
|  | ||||
|     @property | ||||
|     def gml(self): | ||||
| @@ -727,6 +746,18 @@ class Polygon(OGRGeometry): | ||||
|         return sum(self[i].point_count for i in range(self.geom_count)) | ||||
|  | ||||
|  | ||||
| class CircularString(LineString): | ||||
|     geos_support = False | ||||
|  | ||||
|  | ||||
| class CurvePolygon(Polygon): | ||||
|     geos_support = False | ||||
|  | ||||
|  | ||||
| class CompoundCurve(OGRGeometry): | ||||
|     geos_support = False | ||||
|  | ||||
|  | ||||
| # Geometry Collection base class. | ||||
| class GeometryCollection(OGRGeometry): | ||||
|     "The Geometry Collection class." | ||||
| @@ -788,6 +819,14 @@ class MultiPolygon(GeometryCollection): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class MultiSurface(GeometryCollection): | ||||
|     geos_support = False | ||||
|  | ||||
|  | ||||
| class MultiCurve(GeometryCollection): | ||||
|     geos_support = False | ||||
|  | ||||
|  | ||||
| # Class mapping dictionary (using the OGRwkbGeometryType as the key) | ||||
| GEO_CLASSES = { | ||||
|     1: Point, | ||||
| @@ -797,7 +836,17 @@ GEO_CLASSES = { | ||||
|     5: MultiLineString, | ||||
|     6: MultiPolygon, | ||||
|     7: GeometryCollection, | ||||
|     8: CircularString, | ||||
|     9: CompoundCurve, | ||||
|     10: CurvePolygon, | ||||
|     11: MultiCurve, | ||||
|     12: MultiSurface, | ||||
|     101: LinearRing, | ||||
|     1008: CircularString,  # CIRCULARSTRING Z | ||||
|     1009: CompoundCurve,  # COMPOUNDCURVE Z | ||||
|     1010: CurvePolygon,  # CURVEPOLYGON Z | ||||
|     1011: MultiCurve,  # MULTICURVE Z | ||||
|     1012: MultiSurface,  # MULTICURVE Z | ||||
|     2001: Point,  # POINT M | ||||
|     2002: LineString,  # LINESTRING M | ||||
|     2003: Polygon,  # POLYGON M | ||||
| @@ -805,6 +854,11 @@ GEO_CLASSES = { | ||||
|     2005: MultiLineString,  # MULTILINESTRING M | ||||
|     2006: MultiPolygon,  # MULTIPOLYGON M | ||||
|     2007: GeometryCollection,  # GEOMETRYCOLLECTION M | ||||
|     2008: CircularString,  # CIRCULARSTRING M | ||||
|     2009: CompoundCurve,  # COMPOUNDCURVE M | ||||
|     2010: CurvePolygon,  # CURVEPOLYGON M | ||||
|     2011: MultiCurve,  # MULTICURVE M | ||||
|     2012: MultiSurface,  # MULTICURVE M | ||||
|     3001: Point,  # POINT ZM | ||||
|     3002: LineString,  # LINESTRING ZM | ||||
|     3003: Polygon,  # POLYGON ZM | ||||
| @@ -812,6 +866,11 @@ GEO_CLASSES = { | ||||
|     3005: MultiLineString,  # MULTILINESTRING ZM | ||||
|     3006: MultiPolygon,  # MULTIPOLYGON ZM | ||||
|     3007: GeometryCollection,  # GEOMETRYCOLLECTION ZM | ||||
|     3008: CircularString,  # CIRCULARSTRING ZM | ||||
|     3009: CompoundCurve,  # COMPOUNDCURVE ZM | ||||
|     3010: CurvePolygon,  # CURVEPOLYGON ZM | ||||
|     3011: MultiCurve,  # MULTICURVE ZM | ||||
|     3012: MultiSurface,  # MULTISURFACE ZM | ||||
|     1 + OGRGeomType.wkb25bit: Point,  # POINT Z | ||||
|     2 + OGRGeomType.wkb25bit: LineString,  # LINESTRING Z | ||||
|     3 + OGRGeomType.wkb25bit: Polygon,  # POLYGON Z | ||||
|   | ||||
| @@ -85,6 +85,13 @@ is_3d = bool_output(lgdal.OGR_G_Is3D, [c_void_p]) | ||||
| set_3d = void_output(lgdal.OGR_G_Set3D, [c_void_p, c_int], errcheck=False) | ||||
| is_measured = bool_output(lgdal.OGR_G_IsMeasured, [c_void_p]) | ||||
| set_measured = void_output(lgdal.OGR_G_SetMeasured, [c_void_p, c_int], errcheck=False) | ||||
| has_curve_geom = bool_output(lgdal.OGR_G_HasCurveGeometry, [c_void_p, c_int]) | ||||
| get_linear_geom = geom_output( | ||||
|     lgdal.OGR_G_GetLinearGeometry, [c_void_p, c_double, POINTER(c_char_p)] | ||||
| ) | ||||
| get_curve_geom = geom_output( | ||||
|     lgdal.OGR_G_GetCurveGeometry, [c_void_p, POINTER(c_char_p)] | ||||
| ) | ||||
|  | ||||
| # Geometry modification routines. | ||||
| add_geom = void_output(lgdal.OGR_G_AddGeometry, [c_void_p, c_void_p]) | ||||
|   | ||||
| @@ -611,6 +611,26 @@ coordinate transformation: | ||||
|         >>> polygon.geom_count | ||||
|         1 | ||||
|  | ||||
|     .. attribute:: has_curve | ||||
|  | ||||
|     .. versionadded:: 5.2 | ||||
|  | ||||
|     A boolean indicating if this geometry is or contains a curve geometry. | ||||
|  | ||||
|     .. method:: get_linear_geometry | ||||
|  | ||||
|     .. versionadded:: 5.2 | ||||
|  | ||||
|     Returns a linear version of the geometry. If no conversion can be made, the | ||||
|     original geometry is returned. | ||||
|  | ||||
|     .. method:: get_curve_geometry | ||||
|  | ||||
|     .. versionadded:: 5.2 | ||||
|  | ||||
|     Returns a curved version of the geometry. If no conversion can be made, the | ||||
|     original geometry is returned. | ||||
|  | ||||
|     .. attribute:: point_count | ||||
|  | ||||
|     Returns the number of points used to describe this geometry: | ||||
|   | ||||
| @@ -94,7 +94,11 @@ Minor features | ||||
| :mod:`django.contrib.gis` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| * ... | ||||
| * GDAL now supports curved geometries ``CurvePolygon``, ``CompoundCurve``, | ||||
|   ``CircularString``, ``MultiSurface``, and ``MultiCurve`` via the new | ||||
|   :attr:`.OGRGeometry.has_curve` property, and the | ||||
|   :meth:`.OGRGeometry.get_linear_geometry` and | ||||
|   :meth:`.OGRGeometry.get_curve_geometry` methods. | ||||
|  | ||||
| :mod:`django.contrib.messages` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|   | ||||
| @@ -137,5 +137,87 @@ | ||||
|   "union_geoms": [ | ||||
|       {"wkt": "POLYGON ((-5 0,-5 10,5 10,5 5,10 5,10 -5,0 -5,0 0,-5 0))"}, | ||||
|       {"wkt": "POLYGON ((2 0, 2 15, 18 15, 18 0, 2 0))"} | ||||
|   ], | ||||
| "curved_geoms": [ | ||||
|     {"wkt": "CIRCULARSTRING(1 5, 6 2, 7 3)", | ||||
|      "name": "CircularString", | ||||
|      "num": 8 | ||||
|     }, | ||||
|     {"wkt": "COMPOUNDCURVE((5 3, 5 13), CIRCULARSTRING(5 13, 7 15, 9 13), (9 13, 9 3), CIRCULARSTRING(9 3, 7 1, 5 3))", | ||||
|      "name": "CompoundCurve", | ||||
|      "num": 9 | ||||
|     }, | ||||
|     {"wkt": "CURVEPOLYGON(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0),(1 1, 3 3, 3 1, 1 1))", | ||||
|      "name": "CurvePolygon", | ||||
|      "num": 10 | ||||
|     }, | ||||
|     {"wkt": "MULTICURVE((0 0, 5 5), CIRCULARSTRING(4 0, 4 4, 8 4))", | ||||
|      "name": "MultiCurve", | ||||
|      "num": 11 | ||||
|     }, | ||||
|     {"wkt": "MULTISURFACE(((0 0, 0 1, 1 1, 1 0, 0 0)), ((1 1, 1 2, 2 2, 2 1, 1 1)))", | ||||
|      "name": "MultiSurface", | ||||
|      "num": 12 | ||||
|     }, | ||||
|     {"wkt": "CIRCULARSTRING Z (1 5 1, 6 2 2, 7 3 3)", | ||||
|      "name": "CircularStringZ", | ||||
|      "num": 1008 | ||||
|     }, | ||||
|     {"wkt": "COMPOUNDCURVE Z ((5 3 0, 5 13 0), CIRCULARSTRING Z (5 13 0, 7 15 0, 9 13 0), (9 13 0 , 9 3 0), CIRCULARSTRING(9 3 0, 7 1 0, 5 3 0))", | ||||
|      "name": "CompoundCurveZ", | ||||
|      "num": 1009 | ||||
|     }, | ||||
|     {"wkt": "CURVEPOLYGON Z(CIRCULARSTRING Z (0 0 0, 4 0 0, 4 4 0, 0 4 0, 0 0 0),(1 1 0, 3 3 0, 3 1 0, 1 1 0))", | ||||
|      "name": "CurvePolygonZ", | ||||
|      "num": 1010 | ||||
|     }, | ||||
|     {"wkt": "MULTICURVE Z ((0 0 1, 5 5 2), CIRCULARSTRING Z (4 0 0, 4 4 0, 8 4 0))", | ||||
|      "name": "MultiCurveZ", | ||||
|      "num": 1011 | ||||
|     }, | ||||
|     {"wkt": "MULTISURFACE Z (((0 0 1, 0 1 2, 1 1 3, 1 0 4, 0 0 5)), ((1 1 0, 1 2 0, 2 2 0, 2 1 0, 1 1 0)))", | ||||
|      "name": "MultiSurfaceZ", | ||||
|      "num": 1012 | ||||
|     }, | ||||
|     {"wkt": "CIRCULARSTRING M (1 5 1, 6 2 2, 7 3 3)", | ||||
|      "name": "CircularStringM", | ||||
|      "num": 2008 | ||||
|     }, | ||||
|     {"wkt": "COMPOUNDCURVE M ((5 3 0, 5 13 0), CIRCULARSTRING M (5 13 0, 7 15 0, 9 13 0), (9 13 0 , 9 3 0), CIRCULARSTRING M (9 3 0, 7 1 0, 5 3 0))", | ||||
|      "name": "CompoundCurveM", | ||||
|      "num": 2009 | ||||
|     }, | ||||
|     {"wkt": "CURVEPOLYGON M (CIRCULARSTRING M (0 0 0, 4 0 0, 4 4 0, 0 4 0, 0 0 0),(1 1 0, 3 3 1, 3 1 1, 1 1 2))", | ||||
|      "name": "CurvePolygonM", | ||||
|      "num": 2010 | ||||
|     }, | ||||
|     {"wkt": "MULTICURVE M ((0 0 1, 5 5 2), CIRCULARSTRING M (4 0 0, 4 4 0, 8 4 0))", | ||||
|      "name": "MultiCurveM", | ||||
|      "num": 2011 | ||||
|     }, | ||||
|     {"wkt": "MULTISURFACE M (((0 0 1, 0 1 2, 1 1 3, 1 0 4, 0 0 5)), ((1 1 0, 1 2 0, 2 2 0, 2 1 0, 1 1 0)))", | ||||
|      "name": "MultiSurfaceM", | ||||
|      "num": 2012 | ||||
|     }, | ||||
|     {"wkt": "CIRCULARSTRING ZM (1 5 0 1, 6 2 0 2, 7 3 0 3)", | ||||
|      "name": "CircularStringZM", | ||||
|      "num": 3008 | ||||
|     }, | ||||
|     {"wkt": "COMPOUNDCURVE ZM ((5 3 0 0, 5 13 0 0), CIRCULARSTRING ZM (5 13 0 0, 7 15 0 0, 9 13 0 0), (9 13 0 0, 9 3 0 0), CIRCULARSTRING ZM (9 3 0 0, 7 1 0 0, 5 3 0 0))", | ||||
|      "name": "CompoundCurveZM", | ||||
|      "num": 3009 | ||||
|     }, | ||||
|     {"wkt": "CURVEPOLYGON ZM (CIRCULARSTRING ZM (0 0 0 0, 4 0 0 0, 4 4 0 0, 0 4 0 0, 0 0 0 0), (1 1 0 0, 3 3 0 0, 3 1 0 0, 1 1 0 0))", | ||||
|      "name": "CurvePolygonZM", | ||||
|      "num": 3010 | ||||
|     }, | ||||
|     {"wkt": "MULTICURVE ZM ((0 0 0 1, 5 5 0 2), CIRCULARSTRING ZM (4 0 0 0, 4 4 0 0, 8 4 0 0))", | ||||
|      "name": "MultiCurveZM", | ||||
|      "num": 3011 | ||||
|     }, | ||||
|     {"wkt": "MULTISURFACE ZM (((0 0 0 1, 0 1 0 2, 1 1 0 3, 1 0 0 4, 0 0 0 5)), ((1 1 0 0, 1 2 0 0, 2 2 0 0, 2 1 0 0, 1 1 0 0)))", | ||||
|      "name": "MultiSurfaceZM", | ||||
|      "num": 3012 | ||||
|     } | ||||
|   ] | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,8 @@ from django.contrib.gis.gdal import ( | ||||
|     OGRGeomType, | ||||
|     SpatialReference, | ||||
| ) | ||||
| from django.contrib.gis.gdal.geometries import CircularString, CurvePolygon | ||||
| from django.contrib.gis.geos import GEOSException | ||||
| from django.template import Context | ||||
| from django.template.engine import Engine | ||||
| from django.test import SimpleTestCase | ||||
| @@ -646,11 +648,11 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin): | ||||
|             ("Multilinestring", 5, True), | ||||
|             ("MultiPolygon", 6, True), | ||||
|             ("GeometryCollection", 7, True), | ||||
|             ("CircularString", 8, False), | ||||
|             ("CompoundCurve", 9, False), | ||||
|             ("CurvePolygon", 10, False), | ||||
|             ("MultiCurve", 11, False), | ||||
|             ("MultiSurface", 12, False), | ||||
|             ("CircularString", 8, True), | ||||
|             ("CompoundCurve", 9, True), | ||||
|             ("CurvePolygon", 10, True), | ||||
|             ("MultiCurve", 11, True), | ||||
|             ("MultiSurface", 12, True), | ||||
|             # 13 (Curve) and 14 (Surface) are abstract types. | ||||
|             ("PolyhedralSurface", 15, False), | ||||
|             ("TIN", 16, False), | ||||
| @@ -664,11 +666,11 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin): | ||||
|             ("Multilinestring Z", -2147483643, True),  # 1005 | ||||
|             ("MultiPolygon Z", -2147483642, True),  # 1006 | ||||
|             ("GeometryCollection Z", -2147483641, True),  # 1007 | ||||
|             ("CircularString Z", 1008, False), | ||||
|             ("CompoundCurve Z", 1009, False), | ||||
|             ("CurvePolygon Z", 1010, False), | ||||
|             ("MultiCurve Z", 1011, False), | ||||
|             ("MultiSurface Z", 1012, False), | ||||
|             ("CircularString Z", 1008, True), | ||||
|             ("CompoundCurve Z", 1009, True), | ||||
|             ("CurvePolygon Z", 1010, True), | ||||
|             ("MultiCurve Z", 1011, True), | ||||
|             ("MultiSurface Z", 1012, True), | ||||
|             ("PolyhedralSurface Z", 1015, False), | ||||
|             ("TIN Z", 1016, False), | ||||
|             ("Triangle Z", 1017, False), | ||||
| @@ -679,11 +681,11 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin): | ||||
|             ("MultiLineString M", 2005, True), | ||||
|             ("MultiPolygon M", 2006, True), | ||||
|             ("GeometryCollection M", 2007, True), | ||||
|             ("CircularString M", 2008, False), | ||||
|             ("CompoundCurve M", 2009, False), | ||||
|             ("CurvePolygon M", 2010, False), | ||||
|             ("MultiCurve M", 2011, False), | ||||
|             ("MultiSurface M", 2012, False), | ||||
|             ("CircularString M", 2008, True), | ||||
|             ("CompoundCurve M", 2009, True), | ||||
|             ("CurvePolygon M", 2010, True), | ||||
|             ("MultiCurve M", 2011, True), | ||||
|             ("MultiSurface M", 2012, True), | ||||
|             ("PolyhedralSurface M", 2015, False), | ||||
|             ("TIN M", 2016, False), | ||||
|             ("Triangle M", 2017, False), | ||||
| @@ -694,11 +696,11 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin): | ||||
|             ("MultiLineString ZM", 3005, True), | ||||
|             ("MultiPolygon ZM", 3006, True), | ||||
|             ("GeometryCollection ZM", 3007, True), | ||||
|             ("CircularString ZM", 3008, False), | ||||
|             ("CompoundCurve ZM", 3009, False), | ||||
|             ("CurvePolygon ZM", 3010, False), | ||||
|             ("MultiCurve ZM", 3011, False), | ||||
|             ("MultiSurface ZM", 3012, False), | ||||
|             ("CircularString ZM", 3008, True), | ||||
|             ("CompoundCurve ZM", 3009, True), | ||||
|             ("CurvePolygon ZM", 3010, True), | ||||
|             ("MultiCurve ZM", 3011, True), | ||||
|             ("MultiSurface ZM", 3012, True), | ||||
|             ("PolyhedralSurface ZM", 3015, False), | ||||
|             ("TIN ZM", 3016, False), | ||||
|             ("Triangle ZM", 3017, False), | ||||
| @@ -967,6 +969,101 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin): | ||||
|                 geom = OGRGeometry(geom_input) | ||||
|                 self.assertIs(geom.is_measured, True) | ||||
|  | ||||
|     def test_has_curve(self): | ||||
|         for geom in self.geometries.curved_geoms: | ||||
|             with self.subTest(wkt=geom.wkt): | ||||
|                 geom = OGRGeometry(geom.wkt) | ||||
|                 self.assertIs(geom.has_curve, True) | ||||
|                 msg = f"GEOS does not support {geom.__class__.__qualname__}." | ||||
|                 with self.assertRaisesMessage(GEOSException, msg): | ||||
|                     geom.geos | ||||
|         geom = OGRGeometry("POINT (0 1)") | ||||
|         self.assertIs(geom.has_curve, False) | ||||
|  | ||||
|     def test_get_linear_geometry(self): | ||||
|         geom = OGRGeometry("CIRCULARSTRING (-0.797 0.466,-0.481 0.62,-0.419 0.473)") | ||||
|         linear = geom.get_linear_geometry() | ||||
|         self.assertEqual(linear.geom_name, "LINESTRING") | ||||
|         self.assertIs(linear.has_curve, False) | ||||
|  | ||||
|     def test_get_linear_geometry_no_conversion_possible(self): | ||||
|         wkt = "POINT (0 0)" | ||||
|         geom = OGRGeometry(wkt) | ||||
|         geom2 = geom.get_linear_geometry() | ||||
|         self.assertEqual(geom2.wkt, wkt) | ||||
|  | ||||
|     def test_get_curve_geometry(self): | ||||
|         linear_string = OGRGeometry( | ||||
|             "LINESTRING (-0.797 0.466,-0.797500910583869 0.479079607685707," | ||||
|             "-0.797096828208069 0.49216256476959,-0.795789684575482 0.505186328593822," | ||||
|             "-0.793585728444384 0.518088639471983,-0.79049549575663 0.530807818319715," | ||||
|             "-0.786533759270668 0.543283061509385,-0.781719457941079 0.555454731539925," | ||||
|             "-0.776075606381369 0.567264642132187,-0.769629184843353 0.578656336386302," | ||||
|             "-0.76241101023902 0.589575356672327,-0.754455588821145 0.599969504963013," | ||||
|             "-0.745800951227352 0.609789092364991,-0.736488470675795 0.618987176654798," | ||||
|             "-0.726562665181888 0.627519786684672,-0.716070984741265 0.635346132585369," | ||||
|             "-0.705063584496685 0.642428800760598,-0.693593084972889 0.648733932741749," | ||||
|             "-0.681714320525941 0.654231387047048,-0.669484077209319 0.658894883272069," | ||||
|             "-0.656960821309923 0.662702127722269,-0.644204419852031 0.665634919987354," | ||||
|             "-0.631275854404748 0.667679239947688,-0.618236929561618 0.668825314797118," | ||||
|             "-0.60514997748578 0.669067665761503,-0.592077559933017 0.66840513428977," | ||||
|             "-0.579082169177269 0.666840887592428,-0.566225929268313 0.664382403500809," | ||||
|             "-0.553570299049824 0.661041434719465,-0.541175778357228 0.656833952642756," | ||||
|             "-0.529101618800212 0.651780071004197,-0.5174055405123 0.645903949723276," | ||||
|             "-0.506143456221622 0.639233679409784,-0.495369203961872 0.631801147077652," | ||||
|             "-0.485134289701335 0.623641883709865,-0.475487641120239 0.614794894404014," | ||||
|             "-0.46647537371355 0.605302471909454,-0.458140570337321 0.595209994448282," | ||||
|             "-0.450523075252448 0.58456570878613,-0.443659303650563 0.573420499590156," | ||||
|             "-0.437582067572208 0.561827646176397,-0.432320419050072 0.549842567809747," | ||||
|             "-0.427899511226613 0.537522558773986,-0.424340478110267 0.524926514478182," | ||||
|             "-0.421660333544978 0.512114649909193,-0.419871889876113 0.499148211775737," | ||||
|             "-0.418983696701434 0.486089185720561,-0.419 0.473)" | ||||
|         ) | ||||
|         curve = linear_string.get_curve_geometry() | ||||
|         self.assertEqual(curve.geom_name, "CIRCULARSTRING") | ||||
|         self.assertEqual( | ||||
|             curve.wkt, | ||||
|             "CIRCULARSTRING (-0.797 0.466,-0.618236929561618 " | ||||
|             "0.668825314797118,-0.419 0.473)", | ||||
|         ) | ||||
|  | ||||
|     def test_get_curve_geometry_no_conversion_possible(self): | ||||
|         geom = OGRGeometry("LINESTRING (0 0, 1 0, 2 0)") | ||||
|         geom2 = geom.get_curve_geometry() | ||||
|         self.assertEqual(geom2.wkt, geom.wkt) | ||||
|  | ||||
|     def test_curved_geometries(self): | ||||
|         for geom in self.geometries.curved_geoms: | ||||
|             with self.subTest(wkt=geom.wkt, geom_name=geom.name): | ||||
|                 g = OGRGeometry(geom.wkt) | ||||
|                 self.assertEqual(geom.name, g.geom_type.name) | ||||
|                 self.assertEqual(geom.num, g.geom_type.num) | ||||
|                 msg = f"GEOS does not support {g.__class__.__qualname__}." | ||||
|                 with self.assertRaisesMessage(GEOSException, msg): | ||||
|                     g.geos | ||||
|  | ||||
|     def test_circularstring_has_linestring_features(self): | ||||
|         geom = OGRGeometry("CIRCULARSTRING ZM (1 5 0 1, 6 2 0 2, 7 3 0 3)") | ||||
|         self.assertIsInstance(geom, CircularString) | ||||
|         self.assertEqual(geom.x, [1, 6, 7]) | ||||
|         self.assertEqual(geom.y, [5, 2, 3]) | ||||
|         self.assertEqual(geom.z, [0, 0, 0]) | ||||
|         self.assertEqual(geom.m, [1, 2, 3]) | ||||
|         self.assertEqual( | ||||
|             geom.tuple, | ||||
|             ((1.0, 5.0, 0.0, 1.0), (6.0, 2.0, 0.0, 2.0), (7.0, 3.0, 0.0, 3.0)), | ||||
|         ) | ||||
|         self.assertEqual(geom[0], (1, 5, 0, 1)) | ||||
|         self.assertEqual(len(geom), 3) | ||||
|  | ||||
|     def test_curvepolygon_has_polygon_features(self): | ||||
|         geom = OGRGeometry( | ||||
|             "CURVEPOLYGON ZM (CIRCULARSTRING ZM (0 0 0 0, 4 0 0 0, 4 4 0 0, 0 4 0 0, " | ||||
|             "0 0 0 0), (1 1 0 0, 3 3 0 0, 3 1 0 0, 1 1 0 0))" | ||||
|         ) | ||||
|         self.assertIsInstance(geom, CurvePolygon) | ||||
|         self.assertIsInstance(geom.shell, CircularString) | ||||
|  | ||||
|  | ||||
| class DeprecationTests(SimpleTestCase): | ||||
|     def test_coord_setter_deprecation(self): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user