test_polylabel.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import unittest
  2. import pytest
  3. import shapely
  4. from shapely.algorithms.polylabel import polylabel
  5. from shapely.geometry import LineString, Point, Polygon
  6. class PolylabelTestCase(unittest.TestCase):
  7. def test_polylabel(self):
  8. """
  9. Finds pole of inaccessibility for a polygon with a tolerance of 10
  10. """
  11. polygon = LineString(
  12. [(0, 0), (50, 200), (100, 100), (20, 50), (-100, -20), (-150, -200)]
  13. ).buffer(100)
  14. label = polylabel(polygon, tolerance=0.001)
  15. expected = Point(59.733, 111.330)
  16. assert expected.equals_exact(label, 1e-3)
  17. def test_concave_polygon(self):
  18. """
  19. Finds pole of inaccessibility for a concave polygon and ensures that
  20. the point is inside.
  21. """
  22. concave_polygon = LineString([(500, 0), (0, 0), (0, 500), (500, 500)]).buffer(
  23. 100
  24. )
  25. label = polylabel(concave_polygon)
  26. assert concave_polygon.contains(label)
  27. def test_rectangle_special_case(self):
  28. """
  29. The centroid algorithm used is vulnerable to floating point errors
  30. and can give unexpected results for rectangular polygons. Test
  31. that this special case is handled correctly.
  32. https://github.com/mapbox/polylabel/issues/3
  33. """
  34. polygon = Polygon(
  35. [
  36. (32.71997, -117.19310),
  37. (32.71997, -117.21065),
  38. (32.72408, -117.21065),
  39. (32.72408, -117.19310),
  40. ]
  41. )
  42. label = polylabel(polygon)
  43. if shapely.geos_version >= (3, 14, 0):
  44. # https://github.com/libgeos/geos/issues/1265
  45. assert label.coords[:] == [(32.722025, -117.195155)]
  46. elif shapely.geos_version >= (3, 12, 0):
  47. # recent GEOS corrects for this
  48. assert label.coords[:] == [(32.722025, -117.201875)]
  49. else:
  50. # older versions not
  51. assert label.coords[:] == [(32.722025, -117.208595)]
  52. def test_polygon_with_hole(self):
  53. """
  54. Finds pole of inaccessibility for a polygon with a hole
  55. https://github.com/shapely/shapely/issues/817
  56. """
  57. polygon = Polygon(
  58. shell=[(0, 0), (10, 0), (10, 10), (0, 10), (0, 0)],
  59. holes=[[(2, 2), (6, 2), (6, 6), (2, 6), (2, 2)]],
  60. )
  61. label = polylabel(polygon, 0.05)
  62. assert label.x == pytest.approx(7.65625)
  63. assert label.y == pytest.approx(7.65625)
  64. @pytest.mark.skipif(
  65. shapely.geos_version < (3, 12, 0), reason="Fails with GEOS < 3.12"
  66. )
  67. def test_polygon_infinite_loop(self):
  68. # https://github.com/shapely/shapely/issues/1836
  69. # corner case that caused an infinite loop in the old custom implemetation
  70. polygon = shapely.from_wkt(
  71. "POLYGON ((536520.0679737709 5438764.374763639, 536520.0679737704 5438764.374763602, 536520.0679737709 5438764.374763642, 536520.0679737709 5438764.374763639))" # noqa: E501
  72. )
  73. label = polylabel(polygon)
  74. assert label.x == pytest.approx(536520.068)
  75. assert label.y == pytest.approx(5438764.375)