test_creation.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. """See test_creation_indices.py for tests with 'indices' parameter."""
  2. import numpy as np
  3. import pytest
  4. from numpy.testing import assert_array_equal
  5. import shapely
  6. # Note: Point is not imported because it is overridden for testing
  7. from shapely import (
  8. GeometryCollection,
  9. GeometryType,
  10. LinearRing,
  11. LineString,
  12. MultiLineString,
  13. MultiPoint,
  14. MultiPolygon,
  15. Polygon,
  16. )
  17. from shapely.testing import assert_geometries_equal
  18. from shapely.tests.common import (
  19. empty_polygon,
  20. geometry_collection,
  21. ignore_invalid,
  22. line_string,
  23. linear_ring,
  24. multi_line_string,
  25. multi_point,
  26. multi_polygon,
  27. point,
  28. polygon,
  29. )
  30. def box_tpl(x1, y1, x2, y2):
  31. return (x2, y1), (x2, y2), (x1, y2), (x1, y1), (x2, y1)
  32. def test_points_from_coords():
  33. actual = shapely.points([[0, 0], [2, 2]])
  34. assert_geometries_equal(actual, [shapely.Point(0, 0), shapely.Point(2, 2)])
  35. def test_points_from_xy():
  36. actual = shapely.points(2, [0, 1])
  37. assert_geometries_equal(actual, [shapely.Point(2, 0), shapely.Point(2, 1)])
  38. def test_points_from_xyz():
  39. actual = shapely.points(1, 1, [0, 1])
  40. assert_geometries_equal(actual, [shapely.Point(1, 1, 0), shapely.Point(1, 1, 1)])
  41. def test_points_invalid_ndim():
  42. with pytest.raises(ValueError, match="dimension should be 2 or 3, got 4"):
  43. shapely.points([0, 1, 2, 3])
  44. with pytest.raises(ValueError, match="dimension should be 2 or 3, got 1"):
  45. shapely.points([0])
  46. @pytest.mark.skipif(
  47. shapely.geos_version[:2] not in ((3, 10), (3, 11), (3, 12)),
  48. reason="GEOS not in 3.10, 3.11, 3.12",
  49. )
  50. def test_points_nan_all_nan_becomes_empty():
  51. actual = shapely.points(np.nan, np.nan)
  52. assert actual.wkt == "POINT EMPTY"
  53. @pytest.mark.skipif(
  54. shapely.geos_version[:2] not in ((3, 10), (3, 11)),
  55. reason="GEOS not in 3.10, 3.11",
  56. )
  57. def test_points_nan_3D_all_nan_becomes_empty_2D():
  58. actual = shapely.points(np.nan, np.nan, np.nan)
  59. assert actual.wkt == "POINT EMPTY"
  60. @pytest.mark.skipif(shapely.geos_version[:2] != (3, 12), reason="GEOS != 3.12")
  61. def test_points_nan_3D_all_nan_becomes_empty():
  62. actual = shapely.points(np.nan, np.nan, np.nan)
  63. assert actual.wkt == "POINT Z EMPTY"
  64. @pytest.mark.skipif(shapely.geos_version < (3, 12, 0), reason="GEOS < 3.12")
  65. @pytest.mark.parametrize(
  66. "coords,expected_wkt",
  67. [
  68. pytest.param(
  69. [np.nan, np.nan],
  70. "POINT (NaN NaN)",
  71. marks=pytest.mark.skipif(
  72. shapely.geos_version < (3, 13, 0), reason="GEOS < 3.13"
  73. ),
  74. ),
  75. pytest.param(
  76. [np.nan, np.nan, np.nan],
  77. "POINT Z (NaN NaN NaN)",
  78. marks=pytest.mark.skipif(
  79. shapely.geos_version < (3, 13, 0), reason="GEOS < 3.13"
  80. ),
  81. ),
  82. ([1, np.nan], "POINT (1 NaN)"),
  83. ([np.nan, 1], "POINT (NaN 1)"),
  84. ([np.nan, 1, np.nan], "POINT Z (NaN 1 NaN)"),
  85. ([np.nan, np.nan, 1], "POINT Z (NaN NaN 1)"),
  86. ],
  87. )
  88. def test_points_handle_nan_allow(coords, expected_wkt):
  89. actual = shapely.points(coords, handle_nan="allow")
  90. assert actual.wkt == expected_wkt
  91. @pytest.mark.parametrize(
  92. "coords,handle_nan,expected_wkt",
  93. [
  94. ([0, np.nan], "skip", "POINT EMPTY"),
  95. ([np.nan, 0], "skip", "POINT EMPTY"),
  96. ([0, np.nan, 1], "skip", "POINT Z EMPTY"),
  97. ([0, 1, np.nan], "skip", "POINT Z EMPTY"),
  98. ([0, 1], "error", "POINT (0 1)"),
  99. ([0, 1, 2], "error", "POINT Z (0 1 2)"),
  100. ([0, np.inf], "skip", "POINT EMPTY"),
  101. ],
  102. )
  103. def test_points_handle_nan(coords, handle_nan, expected_wkt):
  104. actual = shapely.points(coords, handle_nan=handle_nan)
  105. assert actual.wkt in expected_wkt
  106. @pytest.mark.parametrize(
  107. "coords",
  108. [
  109. [0, np.nan],
  110. [np.nan, 0],
  111. [0, 0, np.nan],
  112. [0, np.inf],
  113. [0, -np.inf],
  114. ],
  115. )
  116. def test_points_handle_nan_error(coords):
  117. with pytest.raises(ValueError, match=".*NaN.*"):
  118. shapely.points(coords, handle_nan="error")
  119. def test_linestrings_from_coords():
  120. actual = shapely.linestrings([[[0, 0], [1, 1]], [[0, 0], [2, 2]]])
  121. assert_geometries_equal(
  122. actual,
  123. [
  124. LineString([(0, 0), (1, 1)]),
  125. LineString([(0, 0), (2, 2)]),
  126. ],
  127. )
  128. def test_linestrings_from_xy():
  129. actual = shapely.linestrings([0, 1], [2, 3])
  130. assert_geometries_equal(actual, LineString([(0, 2), (1, 3)]))
  131. def test_linestrings_from_xy_broadcast():
  132. x = [0, 1] # the same X coordinates for both linestrings
  133. y = [2, 3], [4, 5] # each linestring has a different set of Y coordinates
  134. actual = shapely.linestrings(x, y)
  135. assert_geometries_equal(
  136. actual,
  137. [
  138. LineString([(0, 2), (1, 3)]),
  139. LineString([(0, 4), (1, 5)]),
  140. ],
  141. )
  142. def test_linestrings_from_xyz():
  143. actual = shapely.linestrings([0, 1], [2, 3], 0)
  144. assert_geometries_equal(actual, LineString([(0, 2, 0), (1, 3, 0)]))
  145. @pytest.mark.parametrize("dim", [2, 3])
  146. def test_linestrings_buffer(dim):
  147. coords = np.random.randn(10, 3, dim)
  148. coords1 = np.asarray(coords, order="C")
  149. result1 = shapely.linestrings(coords1)
  150. coords2 = np.asarray(coords1, order="F")
  151. result2 = shapely.linestrings(coords2)
  152. assert_geometries_equal(result1, result2)
  153. # creating (.., 8, 8*3) strided array so it uses copyFromArrays
  154. coords3 = np.asarray(np.swapaxes(np.swapaxes(coords, 0, 2), 1, 0), order="F")
  155. coords3 = np.swapaxes(np.swapaxes(coords3, 0, 2), 1, 2)
  156. result3 = shapely.linestrings(coords3)
  157. assert_geometries_equal(result1, result3)
  158. def test_linestrings_empty():
  159. actual = shapely.linestrings(np.empty((0, 2)))
  160. assert actual.is_empty
  161. def test_linestrings_invalid_shape_scalar():
  162. with pytest.raises(ValueError):
  163. shapely.linestrings((1, 1))
  164. @pytest.mark.parametrize(
  165. "shape",
  166. [
  167. (2, 1, 2), # 2 linestrings of 1 2D point
  168. (1, 1, 2), # 1 linestring of 1 2D point
  169. (1, 2), # 1 linestring of 1 2D point (scalar)
  170. ],
  171. )
  172. def test_linestrings_invalid_shape(shape):
  173. with pytest.raises(shapely.GEOSException):
  174. shapely.linestrings(np.ones(shape))
  175. def test_linestrings_invalid_ndim():
  176. msg = r"The ordinate \(last\) dimension should be 2 or 3, got {}"
  177. coords = np.ones((10, 2, 4), order="C")
  178. with pytest.raises(ValueError, match=msg.format(4)):
  179. shapely.linestrings(coords)
  180. coords = np.ones((10, 2, 4), order="F")
  181. with pytest.raises(ValueError, match=msg.format(4)):
  182. shapely.linestrings(coords)
  183. coords = np.swapaxes(np.swapaxes(np.ones((10, 2, 4)), 0, 2), 1, 0)
  184. coords = np.swapaxes(np.swapaxes(np.asarray(coords, order="F"), 0, 2), 1, 2)
  185. with pytest.raises(ValueError, match=msg.format(4)):
  186. shapely.linestrings(coords)
  187. # too few ordinates
  188. coords = np.ones((10, 2, 1))
  189. with pytest.raises(ValueError, match=msg.format(1)):
  190. shapely.linestrings(coords)
  191. @pytest.mark.parametrize(
  192. "coords",
  193. [
  194. [[0, 1], [2, float("nan")]],
  195. [[0, 1, float("nan")], [2, 2, float("nan")]],
  196. [[0, 1, 2], [2, 2, float("nan")]],
  197. [[0, 1, float("nan")], [2, 2, 3]],
  198. [[float("nan"), float("nan")], [float("nan"), float("nan")]],
  199. ],
  200. )
  201. def test_linestrings_handle_nan_allow(coords):
  202. with ignore_invalid():
  203. actual = shapely.linestrings(coords, handle_nan="allow")
  204. actual = shapely.get_coordinates(actual, include_z=len(coords[0]) == 3)
  205. assert_array_equal(actual, coords)
  206. @pytest.mark.parametrize(
  207. "coords",
  208. [
  209. [[2, float("nan")], [0, 1], [2, 3]],
  210. [[0, 1], [2, float("nan")], [2, 3]],
  211. [[0, 1], [2, 3], [2, float("nan")]],
  212. ],
  213. )
  214. def test_linestrings_handle_nan_skip(coords):
  215. actual = shapely.linestrings(coords, handle_nan="skip")
  216. assert_geometries_equal(actual, LineString([(0, 1), (2, 3)]))
  217. def test_linestrings_handle_nan_skip_invalid():
  218. with pytest.raises(shapely.GEOSException):
  219. shapely.linestrings([[0, 1], [2, float("nan")]], handle_nan="skip")
  220. def test_linestrings_handle_nan_skip_only_nan():
  221. # all-nan becomes an empty linestring
  222. actual = shapely.linestrings(np.full((3, 2), fill_value=np.nan), handle_nan="skip")
  223. assert actual.is_empty
  224. def test_linestrings_handle_nan_error():
  225. with pytest.raises(ValueError, match=".*NaN.*"):
  226. shapely.linestrings([[0, 1], [2, float("nan")], [2, 3]], handle_nan="error")
  227. def test_linearrings():
  228. actual = shapely.linearrings(box_tpl(0, 0, 1, 1))
  229. assert_geometries_equal(
  230. actual, LinearRing([(1, 0), (1, 1), (0, 1), (0, 0), (1, 0)])
  231. )
  232. def test_linearrings_empty():
  233. actual = shapely.linearrings(np.empty((0, 2)))
  234. assert actual.is_empty
  235. def test_linearrings_from_xy():
  236. actual = shapely.linearrings([0, 1, 2, 0], [3, 4, 5, 3])
  237. assert_geometries_equal(actual, LinearRing([(0, 3), (1, 4), (2, 5), (0, 3)]))
  238. def test_linearrings_unclosed():
  239. actual = shapely.linearrings(box_tpl(0, 0, 1, 1)[:-1])
  240. assert_geometries_equal(
  241. actual, LinearRing([(1, 0), (1, 1), (0, 1), (0, 0), (1, 0)])
  242. )
  243. def test_linearrings_unclosed_all_coords_equal():
  244. actual = shapely.linearrings([(0, 0), (0, 0), (0, 0)])
  245. assert_geometries_equal(actual, LinearRing([(0, 0), (0, 0), (0, 0), (0, 0)]))
  246. def test_linearrings_invalid_shape_scalar():
  247. with pytest.raises(ValueError):
  248. shapely.linearrings((1, 1))
  249. @pytest.mark.parametrize(
  250. "shape",
  251. [
  252. (2, 1, 2), # 2 linearrings of 1 2D point
  253. (1, 1, 2), # 1 linearring of 1 2D point
  254. (1, 2), # 1 linearring of 1 2D point (scalar)
  255. (2, 2, 2), # 2 linearrings of 2 2D points
  256. (1, 2, 2), # 1 linearring of 2 2D points
  257. (2, 2), # 1 linearring of 2 2D points (scalar)
  258. ],
  259. )
  260. def test_linearrings_invalid_shape(shape):
  261. coords = np.ones(shape)
  262. with pytest.raises(ValueError):
  263. shapely.linearrings(coords)
  264. # make sure the first coordinate != second coordinate
  265. coords[..., 1] += 1
  266. with pytest.raises(ValueError):
  267. shapely.linearrings(coords)
  268. def test_linearrings_invalid_ndim():
  269. msg = r"The ordinate \(last\) dimension should be 2 or 3, got {}"
  270. coords1 = np.random.randn(10, 3, 4)
  271. with pytest.raises(ValueError, match=msg.format(4)):
  272. shapely.linearrings(coords1)
  273. coords2 = np.hstack((coords1, coords1[:, [0], :]))
  274. with pytest.raises(ValueError, match=msg.format(4)):
  275. shapely.linearrings(coords2)
  276. # too few ordinates
  277. coords3 = np.random.randn(10, 3, 1)
  278. with pytest.raises(ValueError, match=msg.format(1)):
  279. shapely.linearrings(coords3)
  280. def test_linearrings_all_nan():
  281. coords = np.full((4, 2), np.nan)
  282. with pytest.raises(shapely.GEOSException):
  283. shapely.linearrings(coords)
  284. @pytest.mark.parametrize("dim", [2, 3])
  285. @pytest.mark.parametrize("order", ["C", "F"])
  286. def test_linearrings_buffer(dim, order):
  287. coords1 = np.random.randn(10, 4, dim)
  288. coords1 = np.asarray(coords1, order=order)
  289. result1 = shapely.linearrings(coords1)
  290. # with manual closure -> can directly copy from buffer if C order
  291. coords2 = np.hstack((coords1, coords1[:, [0], :]))
  292. coords2 = np.asarray(coords2, order=order)
  293. result2 = shapely.linearrings(coords2)
  294. assert_geometries_equal(result1, result2)
  295. # create scalar -> can also directly copy from buffer if F order
  296. coords3 = np.asarray(coords2[0], order=order)
  297. result3 = shapely.linearrings(coords3)
  298. assert_geometries_equal(result3, result1[0])
  299. @pytest.mark.parametrize(
  300. "coords",
  301. [
  302. [[0, 2], [1, float("nan")], [1, 3], [0, 2]],
  303. [[0, 2], [float("nan"), 0], [1, 3], [0, 2]],
  304. [[0, 2, 5], [float("nan"), 2, 5], [1, 3, 5], [0, 2, 5]],
  305. [[0, 2, 5], [1, 2, float("nan")], [1, 3, 5], [0, 2, 5]],
  306. ],
  307. )
  308. def test_linearrings_handle_nan_allow(coords):
  309. with ignore_invalid():
  310. actual = shapely.linearrings(coords, handle_nan="allow")
  311. actual = shapely.get_coordinates(actual, include_z=len(coords[0]) == 3)
  312. assert_array_equal(actual, coords)
  313. @pytest.mark.parametrize(
  314. "x,y",
  315. [
  316. ([0, 1, float("nan"), 2, 0], [3, 4, 5, 5, 3]),
  317. ([0, 1, 1, 2, 0], [3, 4, float("nan"), 5, 3]),
  318. ([0, 1, 2, 0, float("nan")], [3, 4, 5, 3, 3]),
  319. ([float("nan"), 0, 1, 2, 0], [3, 3, 4, 5, 3]),
  320. ],
  321. )
  322. def test_linearrings_handle_nan_skip(x, y):
  323. actual = shapely.linearrings(x, y, handle_nan="skip")
  324. assert_geometries_equal(actual, LinearRing([(0, 3), (1, 4), (2, 5), (0, 3)]))
  325. def test_linearrings_handle_nan_skip_invalid():
  326. with pytest.raises(ValueError):
  327. shapely.linearrings([0, float("nan"), 0], [3, 4, 3], handle_nan="skip")
  328. def test_linearrings_handle_nan_skip_only_nan():
  329. actual = shapely.linearrings(np.full((5, 2), fill_value=np.nan), handle_nan="skip")
  330. assert actual.is_empty
  331. def test_linearrings_handle_nan_error():
  332. with pytest.raises(ValueError, match=".*NaN.*"):
  333. shapely.linearrings(
  334. [0, 1, float("nan"), 2, 0], [3, 4, 5, 5, 3], handle_nan="error"
  335. )
  336. def test_polygon_from_linearring():
  337. actual = shapely.polygons(shapely.linearrings(box_tpl(0, 0, 1, 1)))
  338. assert_geometries_equal(actual, Polygon([(1, 0), (1, 1), (0, 1), (0, 0), (1, 0)]))
  339. def test_polygons_none():
  340. assert_geometries_equal(shapely.polygons(None), empty_polygon)
  341. assert_geometries_equal(shapely.polygons(None, holes=[linear_ring]), empty_polygon)
  342. def test_polygons():
  343. actual = shapely.polygons(box_tpl(0, 0, 1, 1))
  344. assert_geometries_equal(actual, Polygon([(1, 0), (1, 1), (0, 1), (0, 0), (1, 0)]))
  345. def test_polygon_no_hole_list_raises():
  346. with pytest.raises(ValueError):
  347. shapely.polygons(box_tpl(0, 0, 10, 10), box_tpl(1, 1, 2, 2))
  348. def test_polygon_no_hole_wrong_type():
  349. with pytest.raises((TypeError, shapely.GEOSException)):
  350. shapely.polygons(point)
  351. def test_polygon_with_hole_wrong_type():
  352. with pytest.raises((TypeError, shapely.GEOSException)):
  353. shapely.polygons(point, [linear_ring])
  354. def test_polygon_wrong_hole_type():
  355. with pytest.raises((TypeError, shapely.GEOSException)):
  356. shapely.polygons(linear_ring, [point])
  357. def test_polygon_with_1_hole():
  358. actual = shapely.polygons(box_tpl(0, 0, 10, 10), [box_tpl(1, 1, 2, 2)])
  359. assert shapely.area(actual) == 99.0
  360. def test_polygon_with_2_holes():
  361. actual = shapely.polygons(
  362. box_tpl(0, 0, 10, 10), [box_tpl(1, 1, 2, 2), box_tpl(3, 3, 4, 4)]
  363. )
  364. assert shapely.area(actual) == 98.0
  365. def test_polygon_with_none_hole():
  366. actual = shapely.polygons(
  367. shapely.linearrings(box_tpl(0, 0, 10, 10)),
  368. [
  369. shapely.linearrings(box_tpl(1, 1, 2, 2)),
  370. None,
  371. shapely.linearrings(box_tpl(3, 3, 4, 4)),
  372. ],
  373. )
  374. assert shapely.area(actual) == 98.0
  375. def test_2_polygons_with_same_hole():
  376. actual = shapely.polygons(
  377. [box_tpl(0, 0, 10, 10), box_tpl(0, 0, 5, 5)], [box_tpl(1, 1, 2, 2)]
  378. )
  379. assert shapely.area(actual).tolist() == [99.0, 24.0]
  380. def test_2_polygons_with_2_same_holes():
  381. actual = shapely.polygons(
  382. [box_tpl(0, 0, 10, 10), box_tpl(0, 0, 5, 5)],
  383. [box_tpl(1, 1, 2, 2), box_tpl(3, 3, 4, 4)],
  384. )
  385. assert shapely.area(actual).tolist() == [98.0, 23.0]
  386. def test_2_polygons_with_different_holes():
  387. actual = shapely.polygons(
  388. [box_tpl(0, 0, 10, 10), box_tpl(0, 0, 5, 5)],
  389. [[box_tpl(1, 1, 3, 3)], [box_tpl(1, 1, 2, 2)]],
  390. )
  391. assert shapely.area(actual).tolist() == [96.0, 24.0]
  392. def test_polygons_not_enough_points_in_shell_scalar():
  393. with pytest.raises(ValueError):
  394. shapely.polygons((1, 1))
  395. @pytest.mark.parametrize(
  396. "shape",
  397. [
  398. (2, 1, 2), # 2 linearrings of 1 2D point
  399. (1, 1, 2), # 1 linearring of 1 2D point
  400. (1, 2), # 1 linearring of 1 2D point (scalar)
  401. (2, 2, 2), # 2 linearrings of 2 2D points
  402. (1, 2, 2), # 1 linearring of 2 2D points
  403. (2, 2), # 1 linearring of 2 2D points (scalar)
  404. ],
  405. )
  406. def test_polygons_not_enough_points_in_shell(shape):
  407. coords = np.ones(shape)
  408. with pytest.raises(ValueError):
  409. shapely.polygons(coords)
  410. # make sure the first coordinate != second coordinate
  411. coords[..., 1] += 1
  412. with pytest.raises(ValueError):
  413. shapely.polygons(coords)
  414. def test_polygons_not_enough_points_in_holes_scalar():
  415. with pytest.raises(ValueError):
  416. shapely.polygons(np.ones((1, 4, 2)), (1, 1))
  417. @pytest.mark.parametrize(
  418. "shape",
  419. [
  420. (2, 1, 2), # 2 linearrings of 1 2D point
  421. (1, 1, 2), # 1 linearring of 1 2D point
  422. (1, 2), # 1 linearring of 1 2D point (scalar)
  423. (2, 2, 2), # 2 linearrings of 2 2D points
  424. (1, 2, 2), # 1 linearring of 2 2D points
  425. (2, 2), # 1 linearring of 2 2D points (scalar)
  426. ],
  427. )
  428. def test_polygons_not_enough_points_in_holes(shape):
  429. coords = np.ones(shape)
  430. with pytest.raises(ValueError):
  431. shapely.polygons(np.ones((1, 4, 2)), coords)
  432. # make sure the first coordinate != second coordinate
  433. coords[..., 1] += 1
  434. with pytest.raises(ValueError):
  435. shapely.polygons(np.ones((1, 4, 2)), coords)
  436. @pytest.mark.parametrize(
  437. "func,expected",
  438. [
  439. (shapely.multipoints, MultiPoint()),
  440. (shapely.multilinestrings, MultiLineString()),
  441. (shapely.multipolygons, MultiPolygon()),
  442. (shapely.geometrycollections, GeometryCollection()),
  443. ],
  444. )
  445. def test_create_collection_only_none(func, expected):
  446. actual = func(np.array([None], dtype=object))
  447. assert_geometries_equal(actual, expected)
  448. @pytest.mark.parametrize(
  449. "func,sub_geom",
  450. [
  451. (shapely.multipoints, point),
  452. (shapely.multilinestrings, line_string),
  453. (shapely.multilinestrings, linear_ring),
  454. (shapely.multipolygons, polygon),
  455. (shapely.geometrycollections, point),
  456. (shapely.geometrycollections, line_string),
  457. (shapely.geometrycollections, linear_ring),
  458. (shapely.geometrycollections, polygon),
  459. (shapely.geometrycollections, multi_point),
  460. (shapely.geometrycollections, multi_line_string),
  461. (shapely.geometrycollections, multi_polygon),
  462. (shapely.geometrycollections, geometry_collection),
  463. ],
  464. )
  465. def test_create_collection(func, sub_geom):
  466. actual = func([sub_geom, sub_geom])
  467. assert shapely.get_num_geometries(actual) == 2
  468. @pytest.mark.parametrize(
  469. "func,sub_geom",
  470. [
  471. (shapely.multipoints, point),
  472. (shapely.multilinestrings, line_string),
  473. (shapely.multipolygons, polygon),
  474. (shapely.geometrycollections, polygon),
  475. ],
  476. )
  477. def test_create_collection_skips_none(func, sub_geom):
  478. actual = func([sub_geom, None, None, sub_geom])
  479. assert shapely.get_num_geometries(actual) == 2
  480. @pytest.mark.parametrize(
  481. "func,sub_geom",
  482. [
  483. (shapely.multipoints, line_string),
  484. (shapely.multipoints, geometry_collection),
  485. (shapely.multipoints, multi_point),
  486. (shapely.multilinestrings, point),
  487. (shapely.multilinestrings, polygon),
  488. (shapely.multilinestrings, multi_line_string),
  489. (shapely.multipolygons, linear_ring),
  490. (shapely.multipolygons, multi_point),
  491. (shapely.multipolygons, multi_polygon),
  492. ],
  493. )
  494. def test_create_collection_wrong_geom_type(func, sub_geom):
  495. with pytest.raises(TypeError):
  496. func([sub_geom])
  497. @pytest.mark.parametrize(
  498. "coords,ccw,expected",
  499. [
  500. ((0, 0, 1, 1), True, Polygon([(1, 0), (1, 1), (0, 1), (0, 0), (1, 0)])),
  501. (
  502. (0, 0, 1, 1),
  503. False,
  504. Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)]),
  505. ),
  506. ],
  507. )
  508. def test_box(coords, ccw, expected):
  509. actual = shapely.box(*coords, ccw=ccw)
  510. assert_geometries_equal(actual, expected)
  511. @pytest.mark.parametrize(
  512. "coords,ccw,expected",
  513. [
  514. (
  515. (0, 0, [1, 2], [1, 2]),
  516. True,
  517. [
  518. Polygon([(1, 0), (1, 1), (0, 1), (0, 0), (1, 0)]),
  519. Polygon([(2, 0), (2, 2), (0, 2), (0, 0), (2, 0)]),
  520. ],
  521. ),
  522. (
  523. (0, 0, [1, 2], [1, 2]),
  524. [True, False],
  525. [
  526. Polygon([(1, 0), (1, 1), (0, 1), (0, 0), (1, 0)]),
  527. Polygon([(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)]),
  528. ],
  529. ),
  530. ],
  531. )
  532. def test_box_array(coords, ccw, expected):
  533. actual = shapely.box(*coords, ccw=ccw)
  534. assert_geometries_equal(actual, expected)
  535. @pytest.mark.parametrize(
  536. "coords",
  537. [
  538. [np.nan, np.nan, np.nan, np.nan],
  539. [np.nan, 0, 1, 1],
  540. [0, np.nan, 1, 1],
  541. [0, 0, np.nan, 1],
  542. [0, 0, 1, np.nan],
  543. ],
  544. )
  545. def test_box_nan(coords):
  546. assert shapely.box(*coords) is None
  547. def test_box_deprecate_positional():
  548. with pytest.deprecated_call(
  549. match="positional argument `ccw` for `box` is deprecated"
  550. ):
  551. shapely.box(0, 0, 1, 1, True)
  552. def test_prepare():
  553. arr = np.array([shapely.points(1, 1), None, shapely.box(0, 0, 1, 1)])
  554. assert arr[0]._geom_prepared == 0
  555. assert arr[2]._geom_prepared == 0
  556. shapely.prepare(arr)
  557. assert arr[0]._geom_prepared != 0
  558. assert arr[1] is None
  559. assert arr[2]._geom_prepared != 0
  560. # preparing again actually does nothing
  561. original = arr[0]._geom_prepared
  562. shapely.prepare(arr)
  563. assert arr[0]._geom_prepared == original
  564. def test_destroy_prepared():
  565. arr = np.array([shapely.points(1, 1), None, shapely.box(0, 0, 1, 1)])
  566. shapely.prepare(arr)
  567. assert arr[0]._geom_prepared != 0
  568. assert arr[2]._geom_prepared != 0
  569. shapely.destroy_prepared(arr)
  570. assert arr[0]._geom_prepared == 0
  571. assert arr[1] is None
  572. assert arr[2]._geom_prepared == 0
  573. shapely.destroy_prepared(arr) # does not error
  574. @pytest.mark.parametrize("geom_type", [None, GeometryType.MISSING, -1])
  575. def test_empty_missing(geom_type):
  576. actual = shapely.empty((2,), geom_type=geom_type)
  577. assert shapely.is_missing(actual).all()
  578. @pytest.mark.parametrize("geom_type", range(8))
  579. def test_empty(geom_type):
  580. actual = shapely.empty((2,), geom_type=geom_type)
  581. assert (~shapely.is_missing(actual)).all()
  582. assert shapely.is_empty(actual).all()
  583. assert (shapely.get_type_id(actual) == geom_type).all()