1from . import unittest, numpy, shapely20_deprecated 2import pytest 3 4from shapely.coords import CoordinateSequence 5from shapely.errors import ShapelyDeprecationWarning 6from shapely.geometry import LineString, asLineString, Point, LinearRing 7 8 9def test_from_coordinate_sequence(): 10 # From coordinate tuples 11 line = LineString(((1.0, 2.0), (3.0, 4.0))) 12 assert len(line.coords) == 2 13 assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)] 14 15 line = LineString([(1.0, 2.0), (3.0, 4.0)]) 16 assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)] 17 18 19def test_from_coordinate_sequence_3D(): 20 line = LineString(((1.0, 2.0, 3.0), (3.0, 4.0, 5.0))) 21 assert line.has_z 22 assert line.coords[:] == [(1.0, 2.0, 3.0), (3.0, 4.0, 5.0)] 23 24 25def test_from_points(): 26 # From Points 27 line = LineString((Point(1.0, 2.0), Point(3.0, 4.0))) 28 assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)] 29 30 line = LineString([Point(1.0, 2.0), Point(3.0, 4.0)]) 31 assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)] 32 33 34def test_from_mix(): 35 # From mix of tuples and Points 36 line = LineString((Point(1.0, 2.0), (2.0, 3.0), Point(3.0, 4.0))) 37 assert line.coords[:] == [(1.0, 2.0), (2.0, 3.0), (3.0, 4.0)] 38 39 40def test_from_linestring(): 41 # From another linestring 42 line = LineString(((1.0, 2.0), (3.0, 4.0))) 43 copy = LineString(line) 44 assert copy.coords[:] == [(1.0, 2.0), (3.0, 4.0)] 45 assert copy.geom_type == 'LineString' 46 47 48def test_from_linearring(): 49 coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)] 50 ring = LinearRing(coords) 51 copy = LineString(ring) 52 assert copy.coords[:] == coords 53 assert copy.geom_type == 'LineString' 54 55 56def test_from_linestring_z(): 57 coords = [(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)] 58 line = LineString(coords) 59 copy = LineString(line) 60 assert copy.coords[:] == coords 61 assert copy.geom_type == 'LineString' 62 63 64def test_from_generator(): 65 gen = (coord for coord in [(1.0, 2.0), (3.0, 4.0)]) 66 line = LineString(gen) 67 assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)] 68 69 70def test_from_empty(): 71 line = LineString() 72 assert line.is_empty 73 assert isinstance(line.coords, CoordinateSequence) 74 assert line.coords[:] == [] 75 76 line = LineString([]) 77 assert line.is_empty 78 assert isinstance(line.coords, CoordinateSequence) 79 assert line.coords[:] == [] 80 81 82def test_from_numpy(): 83 # Construct from a numpy array 84 np = pytest.importorskip("numpy") 85 86 line = LineString(np.array([[1.0, 2.0], [3.0, 4.0]])) 87 assert line.coords[:] == [(1.0, 2.0), (3.0, 4.0)] 88 89 90@pytest.mark.filterwarnings("error:An exception was ignored") # NumPy 1.21 91def test_numpy_empty_linestring_coords(): 92 np = pytest.importorskip("numpy") 93 94 # Check empty 95 line = LineString([]) 96 la = np.asarray(line.coords) 97 98 assert la.shape == (0,) 99 100 101@shapely20_deprecated 102@pytest.mark.filterwarnings("error:An exception was ignored") # NumPy 1.21 103def test_numpy_object_array(): 104 np = pytest.importorskip("numpy") 105 106 geom = LineString([(0.0, 0.0), (0.0, 1.0)]) 107 ar = np.empty(1, object) 108 ar[:] = [geom] 109 assert ar[0] == geom 110 111 112def test_from_invalid_dim(): 113 with pytest.raises(ValueError, match="at least 2 coordinate tuples"): 114 LineString([(1, 2)]) 115 116 with pytest.raises(ValueError, match="Inconsistent coordinate dimensionality"): 117 LineString([(1, 2, 3), (4, 5)]) 118 119 # TODO this does not fail 120 # with pytest.raises(ValueError, match="Inconsistent coordinate dimensionality"): 121 # LineString([(1, 2), (3, 4, 5)])) 122 123 # TODO better error, right now raises AssertionError 124 with pytest.raises(Exception): 125 LineString([(1, 2, 3, 4), (4, 5, 6, 7)]) 126 127 128def test_from_single_coordinate(): 129 """Test for issue #486""" 130 coords = [[-122.185933073564, 37.3629353839073]] 131 with pytest.raises(ValueError): 132 ls = LineString(coords) 133 ls.geom_type # caused segfault before fix 134 135 136class LineStringTestCase(unittest.TestCase): 137 138 def test_linestring(self): 139 140 # From coordinate tuples 141 line = LineString(((1.0, 2.0), (3.0, 4.0))) 142 self.assertEqual(len(line.coords), 2) 143 self.assertEqual(line.coords[:], [(1.0, 2.0), (3.0, 4.0)]) 144 145 # Bounds 146 self.assertEqual(line.bounds, (1.0, 2.0, 3.0, 4.0)) 147 148 # Coordinate access 149 self.assertEqual(tuple(line.coords), ((1.0, 2.0), (3.0, 4.0))) 150 self.assertEqual(line.coords[0], (1.0, 2.0)) 151 self.assertEqual(line.coords[1], (3.0, 4.0)) 152 with self.assertRaises(IndexError): 153 line.coords[2] # index out of range 154 155 # Geo interface 156 self.assertEqual(line.__geo_interface__, 157 {'type': 'LineString', 158 'coordinates': ((1.0, 2.0), (3.0, 4.0))}) 159 160 @shapely20_deprecated 161 def test_linestring_mutate(self): 162 line = LineString(((1.0, 2.0), (3.0, 4.0))) 163 164 # Coordinate modification 165 line.coords = ((-1.0, -1.0), (1.0, 1.0)) 166 self.assertEqual(line.__geo_interface__, 167 {'type': 'LineString', 168 'coordinates': ((-1.0, -1.0), (1.0, 1.0))}) 169 170 @shapely20_deprecated 171 def test_linestring_adapter(self): 172 # Adapt a coordinate list to a line string 173 coords = [[5.0, 6.0], [7.0, 8.0]] 174 la = asLineString(coords) 175 self.assertEqual(la.coords[:], [(5.0, 6.0), (7.0, 8.0)]) 176 177 def test_linestring_empty(self): 178 # Test Non-operability of Null geometry 179 l_null = LineString() 180 self.assertEqual(l_null.wkt, 'GEOMETRYCOLLECTION EMPTY') 181 self.assertEqual(l_null.length, 0.0) 182 183 @shapely20_deprecated 184 def test_linestring_empty_mutate(self): 185 # Check that we can set coordinates of a null geometry 186 l_null = LineString() 187 l_null.coords = [(0, 0), (1, 1)] 188 self.assertAlmostEqual(l_null.length, 1.4142135623730951) 189 190 def test_equals_argument_order(self): 191 """ 192 Test equals predicate functions correctly regardless of the order 193 of the inputs. See issue #317. 194 """ 195 coords = ((0, 0), (1, 0), (1, 1), (0, 0)) 196 ls = LineString(coords) 197 lr = LinearRing(coords) 198 199 self.assertFalse(ls.__eq__(lr)) # previously incorrectly returned True 200 self.assertFalse(lr.__eq__(ls)) 201 self.assertFalse(ls == lr) 202 self.assertFalse(lr == ls) 203 204 ls_clone = LineString(coords) 205 lr_clone = LinearRing(coords) 206 207 self.assertTrue(ls.__eq__(ls_clone)) 208 self.assertTrue(lr.__eq__(lr_clone)) 209 self.assertTrue(ls == ls_clone) 210 self.assertTrue(lr == lr_clone) 211 212 @shapely20_deprecated 213 @unittest.skipIf(not numpy, 'Numpy required') 214 def test_numpy(self): 215 216 from numpy import array, asarray 217 from numpy.testing import assert_array_equal 218 219 # Construct from a numpy array 220 line = LineString(array([[0.0, 0.0], [1.0, 2.0]])) 221 self.assertEqual(len(line.coords), 2) 222 self.assertEqual(line.coords[:], [(0.0, 0.0), (1.0, 2.0)]) 223 224 line = LineString(((1.0, 2.0), (3.0, 4.0))) 225 la = asarray(line) 226 expected = array([[1.0, 2.0], [3.0, 4.0]]) 227 assert_array_equal(la, expected) 228 229 @unittest.skipIf(not numpy, 'Numpy required') 230 def test_numpy_linestring_coords(self): 231 from numpy.testing import assert_array_equal 232 233 line = LineString(((1.0, 2.0), (3.0, 4.0))) 234 expected = numpy.array([[1.0, 2.0], [3.0, 4.0]]) 235 236 # Coordinate sequences can be adapted as well 237 la = numpy.asarray(line.coords) 238 assert_array_equal(la, expected) 239 240 @shapely20_deprecated 241 @unittest.skipIf(not numpy, 'Numpy required') 242 def test_numpy_adapter(self): 243 from numpy import array, asarray 244 from numpy.testing import assert_array_equal 245 246 # Adapt a Numpy array to a line string 247 a = array([[1.0, 2.0], [3.0, 4.0]]) 248 la = asLineString(a) 249 assert_array_equal(la.context, a) 250 self.assertEqual(la.coords[:], [(1.0, 2.0), (3.0, 4.0)]) 251 252 # Now, the inverse 253 self.assertEqual(la.__array_interface__, 254 la.context.__array_interface__) 255 256 pas = asarray(la) 257 assert_array_equal(pas, array([[1.0, 2.0], [3.0, 4.0]])) 258 259 @shapely20_deprecated 260 @unittest.skipIf(not numpy, 'Numpy required') 261 def test_numpy_asarray(self): 262 from numpy import array, asarray 263 from numpy.testing import assert_array_equal 264 265 # From Array.txt 266 a = asarray([[0.0, 0.0], [2.0, 2.0], [1.0, 1.0]]) 267 line = LineString(a) 268 self.assertEqual(line.coords[:], [(0.0, 0.0), (2.0, 2.0), (1.0, 1.0)]) 269 270 data = line.ctypes 271 self.assertEqual(data[0], 0.0) 272 self.assertEqual(data[5], 1.0) 273 274 b = asarray(line) 275 assert_array_equal(b, array([[0., 0.], [2., 2.], [1., 1.]])) 276 277 @shapely20_deprecated 278 @unittest.skipIf(not numpy, 'Numpy required') 279 def test_numpy_empty(self): 280 from numpy import array, asarray 281 from numpy.testing import assert_array_equal 282 283 # Test array interface of empty linestring 284 le = LineString() 285 a = asarray(le) 286 self.assertEqual(a.shape[0], 0) 287 288 289def test_linestring_mutability_deprecated(): 290 line = LineString(((1.0, 2.0), (3.0, 4.0))) 291 with pytest.warns(ShapelyDeprecationWarning, match="Setting"): 292 line.coords = ((-1.0, -1.0), (1.0, 1.0)) 293 294 295def test_linestring_adapter_deprecated(): 296 coords = [[5.0, 6.0], [7.0, 8.0]] 297 with pytest.warns(ShapelyDeprecationWarning, match="proxy geometries"): 298 asLineString(coords) 299 300 301def test_linestring_ctypes_deprecated(): 302 line = LineString(((1.0, 2.0), (3.0, 4.0))) 303 with pytest.warns(ShapelyDeprecationWarning, match="ctypes"): 304 line.ctypes 305 306 307def test_linestring_array_interface_deprecated(): 308 line = LineString(((1.0, 2.0), (3.0, 4.0))) 309 with pytest.warns(ShapelyDeprecationWarning, match="array_interface"): 310 line.array_interface() 311 312 313@unittest.skipIf(not numpy, 'Numpy required') 314def test_linestring_array_interface_numpy_deprecated(): 315 import numpy as np 316 317 line = LineString(((1.0, 2.0), (3.0, 4.0))) 318 with pytest.warns(ShapelyDeprecationWarning, match="array interface"): 319 np.array(line) 320