You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
2.7 KiB

7 days ago
7 days ago
7 days ago
7 days ago
7 days ago
7 days ago
7 days ago
7 days ago
7 days ago
7 days ago
7 days ago
7 days ago
7 days ago
  1. <?php
  2. namespace OSM\Element;
  3. use OSM\Element\Member\Way;
  4. use OSM\Point;
  5. class Relation extends Element
  6. {
  7. public function getOuterWays(): array
  8. {
  9. return array_filter($this->members, function ($member) {
  10. return
  11. ($member instanceof Way)
  12. and ('outer' === $member->role)
  13. ;
  14. });
  15. }
  16. public function getOuterWaysStartingWith(Point $point, ?Way $exclude = null): array
  17. {
  18. return array_filter($this->members, function ($member) use ($point, $exclude) {
  19. return
  20. ($member instanceof Way)
  21. and ('outer' === $member->role)
  22. and $point->isSame($member->getFirstPoint())
  23. and (
  24. is_null($exclude)
  25. or !$member->isSame($exclude)
  26. )
  27. ;
  28. });
  29. }
  30. public function getOuterWaysStopingWith(Point $point, ?Way $exclude = null): array
  31. {
  32. return array_filter($this->members, function ($member) use ($point, $exclude) {
  33. return
  34. ($member instanceof Way)
  35. and ('outer' === $member->role)
  36. and $point->isSame($member->getLastPoint())
  37. and (
  38. is_null($exclude)
  39. or !$member->isSame($exclude)
  40. )
  41. ;
  42. });
  43. }
  44. public function getOrderedOuterWays(): array
  45. {
  46. $orderedWays = [];
  47. $ways = $this->getOuterWays();
  48. $currentWay = reset($ways);
  49. $veryFirstPoint = $currentWay->getFirstPoint();
  50. $isDone = false;
  51. while (!$isDone) {
  52. $orderedWays[] = $currentWay;
  53. $nextWays = $this->getOuterWaysStartingWith($currentWay->getLastPoint(), $currentWay);
  54. assert(count($nextWays) <= 1);
  55. if (1 === count($nextWays)) {
  56. $nextWay = reset($nextWays);
  57. if ($veryFirstPoint->isSame($nextWay->getFirstPoint())) {
  58. break;
  59. }
  60. $currentWay = $nextWay;
  61. continue;
  62. } else {
  63. $nextWays = $this->getOuterWaysStopingWith($currentWay->getLastPoint(), $currentWay);
  64. assert(count($nextWays) <= 1);
  65. if (1 === count($nextWays)) {
  66. $nextWay = reset($nextWays);
  67. $nextWay->reversePoints();
  68. if ($veryFirstPoint->isSame($nextWay->getFirstPoint())) {
  69. break;
  70. }
  71. $currentWay = $nextWay;
  72. continue;
  73. } else {
  74. $isDone = true;
  75. }
  76. }
  77. }
  78. return $orderedWays;
  79. }
  80. }