common.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. import warnings
  2. from contextlib import contextmanager
  3. import numpy as np
  4. import shapely
  5. point_polygon_testdata = (
  6. shapely.points(np.arange(6), np.arange(6)),
  7. shapely.box(2, 2, 4, 4),
  8. )
  9. # XY
  10. point = shapely.Point(2, 3)
  11. line_string = shapely.LineString([(0, 0), (1, 0), (1, 1)])
  12. linear_ring = shapely.LinearRing([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)])
  13. polygon = shapely.Polygon([(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)])
  14. polygon_with_hole = shapely.Polygon(
  15. [(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)],
  16. holes=[[(2, 2), (2, 4), (4, 4), (4, 2), (2, 2)]],
  17. )
  18. multi_point = shapely.MultiPoint([(0, 0), (1, 2)])
  19. multi_line_string = shapely.MultiLineString([[(0, 0), (1, 2)]])
  20. multi_polygon = shapely.multipolygons(
  21. [
  22. [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)],
  23. [(2.1, 2.1), (2.2, 2.1), (2.2, 2.2), (2.1, 2.2), (2.1, 2.1)],
  24. ]
  25. )
  26. geometry_collection = shapely.GeometryCollection(
  27. [shapely.Point(51, -1), shapely.LineString([(52, -1), (49, 2)])]
  28. )
  29. empty = shapely.from_wkt("GEOMETRYCOLLECTION EMPTY")
  30. empty_point = shapely.from_wkt("POINT EMPTY")
  31. empty_line_string = shapely.from_wkt("LINESTRING EMPTY")
  32. empty_polygon = shapely.from_wkt("POLYGON EMPTY")
  33. empty_multi_point = shapely.from_wkt("MULTIPOINT EMPTY")
  34. empty_multi_line_string = shapely.from_wkt("MULTILINESTRING EMPTY")
  35. empty_multi_polygon = shapely.from_wkt("MULTIPOLYGON EMPTY")
  36. multi_point_empty = shapely.multipoints([empty_point])
  37. multi_line_string_empty = shapely.multilinestrings([empty_line_string])
  38. multi_polygon_empty = shapely.multipolygons([empty_polygon])
  39. geometry_collection_empty = shapely.geometrycollections([empty_line_string])
  40. # XYZ
  41. point_z = shapely.Point(2, 3, 4)
  42. line_string_z = shapely.LineString([(0, 0, 4), (1, 0, 4), (1, 1, 4)])
  43. linear_ring_z = shapely.LinearRing(
  44. [(0, 0, 8), (1, 0, 7), (1, 1, 6), (0, 1, 9), (0, 0, 8)]
  45. )
  46. polygon_z = shapely.Polygon([(0, 0, 4), (2, 0, 4), (2, 2, 4), (0, 2, 4), (0, 0, 4)])
  47. polygon_with_hole_z = shapely.Polygon(
  48. [(0, 0, 4), (0, 10, 4), (10, 10, 4), (10, 0, 4), (0, 0, 4)],
  49. holes=[[(2, 2, 4), (2, 4, 4), (4, 4, 4), (4, 2, 4), (2, 2, 4)]],
  50. )
  51. multi_point_z = shapely.MultiPoint([(0, 0, 4), (1, 2, 4)])
  52. multi_line_string_z = shapely.MultiLineString([[(0, 0, 4), (1, 2, 4)]])
  53. multi_polygon_z = shapely.multipolygons(
  54. [
  55. [(0, 0, 4), (1, 0, 4), (1, 1, 4), (0, 1, 4), (0, 0, 4)],
  56. [(2.1, 2.1, 4), (2.2, 2.1, 4), (2.2, 2.2, 4), (2.1, 2.2, 4), (2.1, 2.1, 4)],
  57. ]
  58. )
  59. geometry_collection_z = shapely.GeometryCollection([point_z, line_string_z])
  60. empty_geometry_collection_z = shapely.from_wkt("GEOMETRYCOLLECTION Z EMPTY")
  61. empty_point_z = shapely.from_wkt("POINT Z EMPTY")
  62. empty_line_string_z = shapely.from_wkt("LINESTRING Z EMPTY")
  63. empty_polygon_z = shapely.from_wkt("POLYGON Z EMPTY")
  64. empty_multi_point_z = shapely.from_wkt("MULTIPOINT Z EMPTY")
  65. empty_multi_line_string_z = shapely.from_wkt("MULTILINESTRING Z EMPTY")
  66. empty_multi_polygon_z = shapely.from_wkt("MULTIPOLYGON Z EMPTY")
  67. multi_point_empty_z = shapely.multipoints([empty_point_z])
  68. multi_line_string_empty_z = shapely.multilinestrings([empty_line_string_z])
  69. multi_polygon_empty_z = shapely.multipolygons([empty_polygon_z])
  70. geometry_collection_empty_z = shapely.geometrycollections([empty_line_string_z])
  71. # XYM
  72. point_m = shapely.from_wkt("POINT M (2 3 5)")
  73. line_string_m = shapely.from_wkt("LINESTRING M (0 0 1, 1 0 2, 1 1 3)")
  74. linear_ring_m = shapely.from_wkt("LINEARRING M (0 0 1, 1 0 2, 1 1 3, 0 1 2, 0 0 1)")
  75. polygon_m = shapely.from_wkt("POLYGON M ((0 0 1, 2 0 2, 2 2 3, 0 2 2, 0 0 1))")
  76. polygon_with_hole_m = shapely.from_wkt(
  77. """POLYGON M ((0 0 1, 0 10 2, 10 10 3, 10 0 2, 0 0 1),
  78. (2 2 6, 2 4 5, 4 4 4, 4 2 5, 2 2 6))"""
  79. )
  80. multi_point_m = shapely.from_wkt("MULTIPOINT M ((0 0 3), (1 2 5))")
  81. multi_line_string_m = shapely.from_wkt("MULTILINESTRING M ((0 0 3, 1 2 5))")
  82. multi_polygon_m = shapely.from_wkt(
  83. """MULTIPOLYGON M (((0 0 1, 2 0 2, 2 2 3, 0 2 2, 0 0 1)),
  84. ((2.1 2.1 1.1, 2.2 2.1 1.2, 2.2 2.2 1.3, 2.1 2.2 1.4, 2.1 2.1 1.1)))"""
  85. )
  86. geometry_collection_m = shapely.GeometryCollection([point_m, line_string_m])
  87. empty_geometry_collection_m = shapely.from_wkt("GEOMETRYCOLLECTION M EMPTY")
  88. empty_point_m = shapely.from_wkt("POINT M EMPTY")
  89. empty_line_string_m = shapely.from_wkt("LINESTRING M EMPTY")
  90. empty_polygon_m = shapely.from_wkt("POLYGON M EMPTY")
  91. empty_multi_point_m = shapely.from_wkt("MULTIPOINT M EMPTY")
  92. empty_multi_line_string_m = shapely.from_wkt("MULTILINESTRING M EMPTY")
  93. empty_multi_polygon_m = shapely.from_wkt("MULTIPOLYGON M EMPTY")
  94. multi_point_empty_m = shapely.multipoints([empty_point_m])
  95. multi_line_string_empty_m = shapely.multilinestrings([empty_line_string_m])
  96. multi_polygon_empty_m = shapely.multipolygons([empty_polygon_m])
  97. geometry_collection_empty_m = shapely.geometrycollections([empty_line_string_m])
  98. # XYZM
  99. point_zm = shapely.from_wkt("POINT ZM (2 3 4 5)")
  100. line_string_zm = shapely.from_wkt("LINESTRING ZM (0 0 4 1, 1 0 4 2, 1 1 4 3)")
  101. linear_ring_zm = shapely.from_wkt(
  102. "LINEARRING ZM (0 0 1 8, 1 0 2 7, 1 1 3 6, 0 1 2 9, 0 0 1 8)"
  103. )
  104. polygon_zm = shapely.from_wkt(
  105. "POLYGON ZM ((0 0 4 1, 2 0 4 2, 2 2 4 3, 0 2 4 2, 0 0 4 1))"
  106. )
  107. polygon_with_hole_zm = shapely.from_wkt(
  108. """POLYGON ZM ((0 0 4 1, 0 10 4 2, 10 10 4 3, 10 0 4 2, 0 0 4 1),
  109. (2 2 4 6, 2 4 4 5, 4 4 4 4, 4 2 4 5, 2 2 4 6))"""
  110. )
  111. multi_point_zm = shapely.from_wkt("MULTIPOINT ZM ((0 0 4 3), (1 2 4 5))")
  112. multi_line_string_zm = shapely.from_wkt("MULTILINESTRING ZM ((0 0 4 3, 1 2 4 5))")
  113. multi_polygon_zm = shapely.from_wkt(
  114. """MULTIPOLYGON ZM (((0 0 4 1, 2 0 4 2, 2 2 4 3, 0 2 4 2, 0 0 4 1)),
  115. ((2.1 2.1 4 1.1, 2.2 2.1 4 1.2, 2.2 2.2 4 1.3, 2.1 2.2 4 1.4, 2.1 2.1 4 1.1)))"""
  116. )
  117. geometry_collection_zm = shapely.GeometryCollection([point_zm, line_string_zm])
  118. empty_geometry_collection_zm = shapely.from_wkt("GEOMETRYCOLLECTION ZM EMPTY")
  119. empty_point_zm = shapely.from_wkt("POINT ZM EMPTY")
  120. empty_line_string_zm = shapely.from_wkt("LINESTRING ZM EMPTY")
  121. empty_polygon_zm = shapely.from_wkt("POLYGON ZM EMPTY")
  122. empty_multi_point_zm = shapely.from_wkt("MULTIPOINT ZM EMPTY")
  123. empty_multi_line_string_zm = shapely.from_wkt("MULTILINESTRING ZM EMPTY")
  124. empty_multi_polygon_zm = shapely.from_wkt("MULTIPOLYGON ZM EMPTY")
  125. multi_point_empty_zm = shapely.multipoints([empty_point_zm])
  126. multi_line_string_empty_zm = shapely.multilinestrings([empty_line_string_zm])
  127. multi_polygon_empty_zm = shapely.multipolygons([empty_polygon_zm])
  128. geometry_collection_empty_zm = shapely.geometrycollections([empty_line_string_zm])
  129. all_types = (
  130. point,
  131. line_string,
  132. linear_ring,
  133. polygon,
  134. polygon_with_hole,
  135. multi_point,
  136. multi_line_string,
  137. multi_polygon,
  138. geometry_collection,
  139. empty,
  140. empty_point,
  141. empty_line_string,
  142. empty_polygon,
  143. empty_multi_point,
  144. empty_multi_line_string,
  145. empty_multi_polygon,
  146. multi_point_empty,
  147. multi_line_string_empty,
  148. multi_polygon_empty,
  149. geometry_collection_empty,
  150. )
  151. all_types_z = (
  152. point_z,
  153. line_string_z,
  154. linear_ring_z,
  155. polygon_z,
  156. polygon_with_hole_z,
  157. multi_point_z,
  158. multi_line_string_z,
  159. multi_polygon_z,
  160. geometry_collection_z,
  161. empty_geometry_collection_z,
  162. empty_point_z,
  163. empty_line_string_z,
  164. empty_polygon_z,
  165. empty_multi_point_z,
  166. empty_multi_line_string_z,
  167. empty_multi_polygon_z,
  168. multi_point_empty_z,
  169. multi_line_string_empty_z,
  170. multi_polygon_empty_z,
  171. geometry_collection_empty_z,
  172. )
  173. all_types_m = (
  174. point_m,
  175. line_string_m,
  176. linear_ring_m,
  177. polygon_m,
  178. polygon_with_hole_m,
  179. multi_point_m,
  180. multi_line_string_m,
  181. multi_polygon_m,
  182. geometry_collection_m,
  183. empty_geometry_collection_m,
  184. empty_point_m,
  185. empty_line_string_m,
  186. empty_polygon_m,
  187. empty_multi_point_m,
  188. empty_multi_line_string_m,
  189. empty_multi_polygon_m,
  190. multi_point_empty_m,
  191. multi_line_string_empty_m,
  192. multi_polygon_empty_m,
  193. geometry_collection_empty_m,
  194. )
  195. all_types_zm = (
  196. point_zm,
  197. line_string_zm,
  198. linear_ring_zm,
  199. polygon_zm,
  200. polygon_with_hole_zm,
  201. multi_point_zm,
  202. multi_line_string_zm,
  203. multi_polygon_zm,
  204. geometry_collection_zm,
  205. empty_geometry_collection_zm,
  206. empty_point_zm,
  207. empty_line_string_zm,
  208. empty_polygon_zm,
  209. empty_multi_point_zm,
  210. empty_multi_line_string_zm,
  211. empty_multi_polygon_zm,
  212. multi_point_empty_zm,
  213. multi_line_string_empty_zm,
  214. multi_polygon_empty_zm,
  215. geometry_collection_empty_zm,
  216. )
  217. @contextmanager
  218. def ignore_invalid(condition=True):
  219. if condition:
  220. with np.errstate(invalid="ignore"):
  221. yield
  222. else:
  223. yield
  224. with ignore_invalid():
  225. line_string_nan = shapely.LineString([(np.nan, np.nan), (np.nan, np.nan)])
  226. @contextmanager
  227. def ignore_warnings(geos_version, category):
  228. if shapely.geos_version < geos_version:
  229. with warnings.catch_warnings():
  230. warnings.filterwarnings("ignore", category=category)
  231. yield
  232. else:
  233. yield
  234. def equal_geometries_abnormally_yield_unequal(geom):
  235. """Older GEOS versions have various issues with "equals"."""
  236. if geom.is_empty and shapely.get_num_geometries(geom) > 0:
  237. if shapely.geos_version < (3, 10, 0) and geom.geom_type == "GeometryCollection":
  238. return True
  239. if shapely.geos_version < (3, 13, 0) and geom.geom_type.startswith("Multi"):
  240. return True
  241. return False
  242. class ArrayLike:
  243. """
  244. Simple numpy Array like class that implements the
  245. ufunc protocol.
  246. """
  247. def __init__(self, array):
  248. self._array = np.asarray(array)
  249. def __len__(self):
  250. return len(self._array)
  251. def __getitem(self, key):
  252. return self._array[key]
  253. def __iter__(self):
  254. return self._array.__iter__()
  255. def __array__(self):
  256. return np.asarray(self._array)
  257. def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
  258. if method == "__call__":
  259. inputs = [
  260. arg._array if isinstance(arg, self.__class__) else arg for arg in inputs
  261. ]
  262. return self.__class__(ufunc(*inputs, **kwargs))
  263. else:
  264. return NotImplemented