members, function ($member) { return ( ($member instanceof \OSM\Element\Member\Way) and ($member->role === 'outer') ); }); } public function getOuterWaysStartingWith(Point $point, ?Way $exclude = null): array { return array_filter($this->members, function ($member) use ($point, $exclude) { return ( ($member instanceof \OSM\Element\Member\Way) and ($member->role === 'outer') and ($point->isSame($member->getFirstPoint())) and ( is_null($exclude) or !$member->isSame($exclude) ) ); }); } public function getOuterWaysStopingWith(Point $point, ?Way $exclude = null): array { return array_filter($this->members, function ($member) use ($point, $exclude) { return ( ($member instanceof \OSM\Element\Member\Way) and ($member->role === 'outer') and ($point->isSame($member->getLastPoint())) and ( is_null($exclude) or !$member->isSame($exclude) ) ); }); } public function getOrderedOuterWays(): array { $orderedWays = []; $ways = $this->getOuterWays(); $currentWay = reset($ways); $veryFirstPoint = $currentWay->getFirstPoint(); $isDone = false; while (!$isDone) { $orderedWays[] = $currentWay; $nextWays = $this->getOuterWaysStartingWith($currentWay->getLastPoint(), $currentWay); assert(count($nextWays) <= 1); if (count($nextWays) === 1) { $nextWay = reset($nextWays); if ($veryFirstPoint->isSame($nextWay->getFirstPoint())) { break; } $currentWay = $nextWay; continue; } else { $nextWays = $this->getOuterWaysStopingWith($currentWay->getLastPoint(), $currentWay); assert(count($nextWays) <= 1); if (count($nextWays) === 1) { $nextWay = reset($nextWays); $nextWay->reversePoints(); if ($veryFirstPoint->isSame($nextWay->getFirstPoint())) { break; } $currentWay = $nextWay; continue; } else { $isDone = true; } } } return $orderedWays; } }