Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/django/contrib/gis/geos/linestring.py: 0%
108 statements
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
1from django.contrib.gis.geos import prototypes as capi
2from django.contrib.gis.geos.coordseq import GEOSCoordSeq
3from django.contrib.gis.geos.error import GEOSException
4from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin
5from django.contrib.gis.geos.point import Point
6from django.contrib.gis.shortcuts import numpy
9class LineString(LinearGeometryMixin, GEOSGeometry):
10 _init_func = capi.create_linestring
11 _minlength = 2
12 has_cs = True
14 def __init__(self, *args, **kwargs):
15 """
16 Initialize on the given sequence -- may take lists, tuples, NumPy arrays
17 of X,Y pairs, or Point objects. If Point objects are used, ownership is
18 _not_ transferred to the LineString object.
20 Examples:
21 ls = LineString((1, 1), (2, 2))
22 ls = LineString([(1, 1), (2, 2)])
23 ls = LineString(array([(1, 1), (2, 2)]))
24 ls = LineString(Point(1, 1), Point(2, 2))
25 """
26 # If only one argument provided, set the coords array appropriately
27 if len(args) == 1:
28 coords = args[0]
29 else:
30 coords = args
32 if not (
33 isinstance(coords, (tuple, list))
34 or numpy
35 and isinstance(coords, numpy.ndarray)
36 ):
37 raise TypeError("Invalid initialization input for LineStrings.")
39 # If SRID was passed in with the keyword arguments
40 srid = kwargs.get("srid")
42 ncoords = len(coords)
43 if not ncoords:
44 super().__init__(self._init_func(None), srid=srid)
45 return
47 if ncoords < self._minlength:
48 raise ValueError(
49 "%s requires at least %d points, got %s."
50 % (
51 self.__class__.__name__,
52 self._minlength,
53 ncoords,
54 )
55 )
57 numpy_coords = not isinstance(coords, (tuple, list))
58 if numpy_coords:
59 shape = coords.shape # Using numpy's shape.
60 if len(shape) != 2:
61 raise TypeError("Too many dimensions.")
62 self._checkdim(shape[1])
63 ndim = shape[1]
64 else:
65 # Getting the number of coords and the number of dimensions -- which
66 # must stay the same, e.g., no LineString((1, 2), (1, 2, 3)).
67 ndim = None
68 # Incrementing through each of the coordinates and verifying
69 for coord in coords:
70 if not isinstance(coord, (tuple, list, Point)):
71 raise TypeError(
72 "Each coordinate should be a sequence (list or tuple)"
73 )
75 if ndim is None:
76 ndim = len(coord)
77 self._checkdim(ndim)
78 elif len(coord) != ndim:
79 raise TypeError("Dimension mismatch.")
81 # Creating a coordinate sequence object because it is easier to
82 # set the points using its methods.
83 cs = GEOSCoordSeq(capi.create_cs(ncoords, ndim), z=bool(ndim == 3))
84 point_setter = cs._set_point_3d if ndim == 3 else cs._set_point_2d
86 for i in range(ncoords):
87 if numpy_coords:
88 point_coords = coords[i, :]
89 elif isinstance(coords[i], Point):
90 point_coords = coords[i].tuple
91 else:
92 point_coords = coords[i]
93 point_setter(i, point_coords)
95 # Calling the base geometry initialization with the returned pointer
96 # from the function.
97 super().__init__(self._init_func(cs.ptr), srid=srid)
99 def __iter__(self):
100 "Allow iteration over this LineString."
101 for i in range(len(self)):
102 yield self[i]
104 def __len__(self):
105 "Return the number of points in this LineString."
106 return len(self._cs)
108 def _get_single_external(self, index):
109 return self._cs[index]
111 _get_single_internal = _get_single_external
113 def _set_list(self, length, items):
114 ndim = self._cs.dims
115 hasz = self._cs.hasz # I don't understand why these are different
116 srid = self.srid
118 # create a new coordinate sequence and populate accordingly
119 cs = GEOSCoordSeq(capi.create_cs(length, ndim), z=hasz)
120 for i, c in enumerate(items):
121 cs[i] = c
123 ptr = self._init_func(cs.ptr)
124 if ptr:
125 capi.destroy_geom(self.ptr)
126 self.ptr = ptr
127 if srid is not None:
128 self.srid = srid
129 self._post_init()
130 else:
131 # can this happen?
132 raise GEOSException("Geometry resulting from slice deletion was invalid.")
134 def _set_single(self, index, value):
135 self._cs[index] = value
137 def _checkdim(self, dim):
138 if dim not in (2, 3):
139 raise TypeError("Dimension mismatch.")
141 # #### Sequence Properties ####
142 @property
143 def tuple(self):
144 "Return a tuple version of the geometry from the coordinate sequence."
145 return self._cs.tuple
147 coords = tuple
149 def _listarr(self, func):
150 """
151 Return a sequence (list) corresponding with the given function.
152 Return a numpy array if possible.
153 """
154 lst = [func(i) for i in range(len(self))]
155 if numpy:
156 return numpy.array(lst) # ARRRR!
157 else:
158 return lst
160 @property
161 def array(self):
162 "Return a numpy array for the LineString."
163 return self._listarr(self._cs.__getitem__)
165 @property
166 def x(self):
167 "Return a list or numpy array of the X variable."
168 return self._listarr(self._cs.getX)
170 @property
171 def y(self):
172 "Return a list or numpy array of the Y variable."
173 return self._listarr(self._cs.getY)
175 @property
176 def z(self):
177 "Return a list or numpy array of the Z variable."
178 if not self.hasz:
179 return None
180 else:
181 return self._listarr(self._cs.getZ)
184# LinearRings are LineStrings used within Polygons.
185class LinearRing(LineString):
186 _minlength = 4
187 _init_func = capi.create_linearring
189 @property
190 def is_counterclockwise(self):
191 if self.empty:
192 raise ValueError("Orientation of an empty LinearRing cannot be determined.")
193 return self._cs.is_counterclockwise