<?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;
|
|
}
|
|
}
|