<?php
							 | 
						|
								
							 | 
						|
								namespace OSM\Element;
							 | 
						|
								
							 | 
						|
								use OSM\Element\Member\Way;
							 | 
						|
								use OSM\Point;
							 | 
						|
								
							 | 
						|
								class Relation extends Element
							 | 
						|
								{
							 | 
						|
								    public function getOuterWays(): array
							 | 
						|
								    {
							 | 
						|
								        return array_filter($this->members, function ($member) {
							 | 
						|
								            return
							 | 
						|
								                ($member instanceof Way)
							 | 
						|
								                and ('outer' === $member->role)
							 | 
						|
								            ;
							 | 
						|
								        });
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    public function getOuterWaysStartingWith(Point $point, ?Way $exclude = null): array
							 | 
						|
								    {
							 | 
						|
								        return array_filter($this->members, function ($member) use ($point, $exclude) {
							 | 
						|
								            return
							 | 
						|
								                ($member instanceof Way)
							 | 
						|
								                and ('outer' === $member->role)
							 | 
						|
								                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 Way)
							 | 
						|
								                and ('outer' === $member->role)
							 | 
						|
								                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 (1 === count($nextWays)) {
							 | 
						|
								                $nextWay = reset($nextWays);
							 | 
						|
								                if ($veryFirstPoint->isSame($nextWay->getFirstPoint())) {
							 | 
						|
								                    break;
							 | 
						|
								                }
							 | 
						|
								                $currentWay = $nextWay;
							 | 
						|
								                continue;
							 | 
						|
								            } else {
							 | 
						|
								                $nextWays = $this->getOuterWaysStopingWith($currentWay->getLastPoint(), $currentWay);
							 | 
						|
								                assert(count($nextWays) <= 1);
							 | 
						|
								                if (1 === count($nextWays)) {
							 | 
						|
								                    $nextWay = reset($nextWays);
							 | 
						|
								                    $nextWay->reversePoints();
							 | 
						|
								                    if ($veryFirstPoint->isSame($nextWay->getFirstPoint())) {
							 | 
						|
								                        break;
							 | 
						|
								                    }
							 | 
						|
								                    $currentWay = $nextWay;
							 | 
						|
								                    continue;
							 | 
						|
								                } else {
							 | 
						|
								                    $isDone = true;
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return $orderedWays;
							 | 
						|
								    }
							 | 
						|
								}
							 |