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.

86 lines
2.8 KiB

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