<?php
|
|
|
|
namespace OSM\Element;
|
|
|
|
use OSM\Element\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 \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;
|
|
}
|
|
|
|
}
|