measurement.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. """Methods for measuring (between) geometries."""
  2. import warnings
  3. import numpy as np
  4. from shapely import lib
  5. from shapely.decorators import multithreading_enabled
  6. __all__ = [
  7. "area",
  8. "bounds",
  9. "distance",
  10. "frechet_distance",
  11. "hausdorff_distance",
  12. "length",
  13. "minimum_bounding_radius",
  14. "minimum_clearance",
  15. "total_bounds",
  16. ]
  17. @multithreading_enabled
  18. def area(geometry, **kwargs):
  19. """Compute the area of a (multi)polygon.
  20. Parameters
  21. ----------
  22. geometry : Geometry or array_like
  23. Geometry or geometries for which to compute the area.
  24. **kwargs
  25. See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
  26. Examples
  27. --------
  28. >>> import shapely
  29. >>> from shapely import MultiPolygon, Polygon
  30. >>> polygon = Polygon([(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)])
  31. >>> shapely.area(polygon)
  32. 100.0
  33. >>> polygon2 = Polygon([(10, 10), (10, 20), (20, 20), (20, 10), (10, 10)])
  34. >>> shapely.area(MultiPolygon([polygon, polygon2]))
  35. 200.0
  36. >>> shapely.area(Polygon())
  37. 0.0
  38. >>> shapely.area(None)
  39. nan
  40. """
  41. return lib.area(geometry, **kwargs)
  42. @multithreading_enabled
  43. def distance(a, b, **kwargs):
  44. """Compute the Cartesian distance between two geometries.
  45. Parameters
  46. ----------
  47. a, b : Geometry or array_like
  48. Geometry or geometries to compute the distance between.
  49. **kwargs
  50. See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
  51. Examples
  52. --------
  53. >>> import shapely
  54. >>> from shapely import LineString, Point, Polygon
  55. >>> point = Point(0, 0)
  56. >>> shapely.distance(Point(10, 0), point)
  57. 10.0
  58. >>> shapely.distance(LineString([(1, 1), (1, -1)]), point)
  59. 1.0
  60. >>> shapely.distance(Polygon([(3, 0), (5, 0), (5, 5), (3, 5), (3, 0)]), point)
  61. 3.0
  62. >>> shapely.distance(Point(), point)
  63. nan
  64. >>> shapely.distance(None, point)
  65. nan
  66. """
  67. return lib.distance(a, b, **kwargs)
  68. @multithreading_enabled
  69. def bounds(geometry, **kwargs):
  70. """Compute the bounds (extent) of a geometry.
  71. For each geometry these 4 numbers are returned: min x, min y, max x, max y.
  72. Parameters
  73. ----------
  74. geometry : Geometry or array_like
  75. Geometry or geometries for which to compute the bounds.
  76. **kwargs
  77. See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
  78. Examples
  79. --------
  80. >>> import shapely
  81. >>> from shapely import LineString, Point, Polygon
  82. >>> shapely.bounds(Point(2, 3)).tolist()
  83. [2.0, 3.0, 2.0, 3.0]
  84. >>> shapely.bounds(LineString([(0, 0), (0, 2), (3, 2)])).tolist()
  85. [0.0, 0.0, 3.0, 2.0]
  86. >>> shapely.bounds(Polygon()).tolist()
  87. [nan, nan, nan, nan]
  88. >>> shapely.bounds(None).tolist()
  89. [nan, nan, nan, nan]
  90. """
  91. return lib.bounds(geometry, **kwargs)
  92. def total_bounds(geometry, **kwargs):
  93. """Compute the total bounds (extent) of the geometry.
  94. Parameters
  95. ----------
  96. geometry : Geometry or array_like
  97. Geometry or geometries for which to compute the total bounds.
  98. **kwargs
  99. See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
  100. Returns
  101. -------
  102. numpy ndarray of [xmin, ymin, xmax, ymax]
  103. Examples
  104. --------
  105. >>> import shapely
  106. >>> from shapely import LineString, Point, Polygon
  107. >>> shapely.total_bounds(Point(2, 3)).tolist()
  108. [2.0, 3.0, 2.0, 3.0]
  109. >>> shapely.total_bounds([Point(2, 3), Point(4, 5)]).tolist()
  110. [2.0, 3.0, 4.0, 5.0]
  111. >>> shapely.total_bounds([
  112. ... LineString([(0, 1), (0, 2), (3, 2)]),
  113. ... LineString([(4, 4), (4, 6), (6, 7)])
  114. ... ]).tolist()
  115. [0.0, 1.0, 6.0, 7.0]
  116. >>> shapely.total_bounds(Polygon()).tolist()
  117. [nan, nan, nan, nan]
  118. >>> shapely.total_bounds([Polygon(), Point(2, 3)]).tolist()
  119. [2.0, 3.0, 2.0, 3.0]
  120. >>> shapely.total_bounds(None).tolist()
  121. [nan, nan, nan, nan]
  122. """
  123. b = bounds(geometry, **kwargs)
  124. if b.ndim == 1:
  125. return b
  126. with warnings.catch_warnings():
  127. # ignore 'All-NaN slice encountered' warnings
  128. warnings.simplefilter("ignore", RuntimeWarning)
  129. return np.array(
  130. [
  131. np.nanmin(b[..., 0]),
  132. np.nanmin(b[..., 1]),
  133. np.nanmax(b[..., 2]),
  134. np.nanmax(b[..., 3]),
  135. ]
  136. )
  137. @multithreading_enabled
  138. def length(geometry, **kwargs):
  139. """Compute the length of a (multi)linestring or polygon perimeter.
  140. Parameters
  141. ----------
  142. geometry : Geometry or array_like
  143. Geometry or geometries for which to compute the length.
  144. **kwargs
  145. See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
  146. Examples
  147. --------
  148. >>> import shapely
  149. >>> from shapely import LineString, MultiLineString, Polygon
  150. >>> shapely.length(LineString([(0, 0), (0, 2), (3, 2)]))
  151. 5.0
  152. >>> shapely.length(MultiLineString([
  153. ... LineString([(0, 0), (1, 0)]),
  154. ... LineString([(1, 0), (2, 0)])
  155. ... ]))
  156. 2.0
  157. >>> shapely.length(Polygon([(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)]))
  158. 40.0
  159. >>> shapely.length(LineString())
  160. 0.0
  161. >>> shapely.length(None)
  162. nan
  163. """
  164. return lib.length(geometry, **kwargs)
  165. @multithreading_enabled
  166. def hausdorff_distance(a, b, densify=None, **kwargs):
  167. """Compute the discrete Hausdorff distance between two geometries.
  168. The Hausdorff distance is a measure of similarity: it is the greatest
  169. distance between any point in A and the closest point in B. The discrete
  170. distance is an approximation of this metric: only vertices are considered.
  171. The parameter 'densify' makes this approximation less coarse by splitting
  172. the line segments between vertices before computing the distance.
  173. Parameters
  174. ----------
  175. a, b : Geometry or array_like
  176. Geometry or geometries to compute the distance between.
  177. densify : float or array_like, optional
  178. The value of densify is required to be between 0 and 1.
  179. **kwargs
  180. See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
  181. Examples
  182. --------
  183. >>> import shapely
  184. >>> from shapely import LineString
  185. >>> line1 = LineString([(130, 0), (0, 0), (0, 150)])
  186. >>> line2 = LineString([(10, 10), (10, 150), (130, 10)])
  187. >>> shapely.hausdorff_distance(line1, line2)
  188. 14.142135623730951
  189. >>> shapely.hausdorff_distance(line1, line2, densify=0.5)
  190. 70.0
  191. >>> shapely.hausdorff_distance(line1, LineString())
  192. nan
  193. >>> shapely.hausdorff_distance(line1, None)
  194. nan
  195. """
  196. if densify is None:
  197. return lib.hausdorff_distance(a, b, **kwargs)
  198. else:
  199. return lib.hausdorff_distance_densify(a, b, densify, **kwargs)
  200. @multithreading_enabled
  201. def frechet_distance(a, b, densify=None, **kwargs):
  202. """Compute the discrete Fréchet distance between two geometries.
  203. The Fréchet distance is a measure of similarity: it is the greatest
  204. distance between any point in A and the closest point in B. The discrete
  205. distance is an approximation of this metric: only vertices are considered.
  206. The parameter 'densify' makes this approximation less coarse by splitting
  207. the line segments between vertices before computing the distance.
  208. Fréchet distance sweep continuously along their respective curves
  209. and the direction of curves is significant. This makes it a better measure
  210. of similarity than Hausdorff distance for curve or surface matching.
  211. Parameters
  212. ----------
  213. a, b : Geometry or array_like
  214. Geometry or geometries to compute the distance between.
  215. densify : float or array_like, optional
  216. The value of densify is required to be between 0 and 1.
  217. **kwargs
  218. See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
  219. Examples
  220. --------
  221. >>> import shapely
  222. >>> from shapely import LineString
  223. >>> line1 = LineString([(0, 0), (100, 0)])
  224. >>> line2 = LineString([(0, 0), (50, 50), (100, 0)])
  225. >>> shapely.frechet_distance(line1, line2)
  226. 70.71067811865476
  227. >>> shapely.frechet_distance(line1, line2, densify=0.5)
  228. 50.0
  229. >>> shapely.frechet_distance(line1, LineString())
  230. nan
  231. >>> shapely.frechet_distance(line1, None)
  232. nan
  233. """
  234. if densify is None:
  235. return lib.frechet_distance(a, b, **kwargs)
  236. return lib.frechet_distance_densify(a, b, densify, **kwargs)
  237. @multithreading_enabled
  238. def minimum_clearance(geometry, **kwargs):
  239. """Compute the Minimum Clearance distance.
  240. A geometry's "minimum clearance" is the smallest distance by which
  241. a vertex of the geometry could be moved to produce an invalid geometry.
  242. If no minimum clearance exists for a geometry (for example, a single
  243. point, or an empty geometry), infinity is returned.
  244. Parameters
  245. ----------
  246. geometry : Geometry or array_like
  247. Geometry or geometries for which to compute the minimum clearance.
  248. **kwargs
  249. See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
  250. Examples
  251. --------
  252. >>> import shapely
  253. >>> from shapely import Polygon
  254. >>> polygon = Polygon([(0, 0), (0, 10), (5, 6), (10, 10), (10, 0), (5, 4), (0, 0)])
  255. >>> shapely.minimum_clearance(polygon)
  256. 2.0
  257. >>> shapely.minimum_clearance(Polygon())
  258. inf
  259. >>> shapely.minimum_clearance(None)
  260. nan
  261. See Also
  262. --------
  263. minimum_clearance_line
  264. """
  265. return lib.minimum_clearance(geometry, **kwargs)
  266. @multithreading_enabled
  267. def minimum_bounding_radius(geometry, **kwargs):
  268. """Compute the radius of the minimum bounding circle of an input geometry.
  269. Parameters
  270. ----------
  271. geometry : Geometry or array_like
  272. Geometry or geometries for which to compute the minimum bounding radius.
  273. **kwargs
  274. See :ref:`NumPy ufunc docs <ufuncs.kwargs>` for other keyword arguments.
  275. Examples
  276. --------
  277. >>> import shapely
  278. >>> from shapely import GeometryCollection, LineString, MultiPoint, Point, Polygon
  279. >>> shapely.minimum_bounding_radius(
  280. ... Polygon([(0, 5), (5, 10), (10, 5), (5, 0), (0, 5)])
  281. ... )
  282. 5.0
  283. >>> shapely.minimum_bounding_radius(LineString([(1, 1), (1, 10)]))
  284. 4.5
  285. >>> shapely.minimum_bounding_radius(MultiPoint([(2, 2), (4, 2)]))
  286. 1.0
  287. >>> shapely.minimum_bounding_radius(Point(0, 1))
  288. 0.0
  289. >>> shapely.minimum_bounding_radius(GeometryCollection())
  290. 0.0
  291. See Also
  292. --------
  293. minimum_bounding_circle
  294. """
  295. return lib.minimum_bounding_radius(geometry, **kwargs)