1<?php
2
3namespace geoPHP\Geometry;
4
5use geoPHP\geoPHP;
6
7/**
8 * MultiLineString: A collection of LineStrings
9 *
10 * @method LineString[] getComponents()
11 * @property LineString[] $components
12 */
13class MultiLineString extends MultiCurve
14{
15
16    public function __construct($components = [])
17    {
18        parent::__construct($components, true, LineString::class);
19    }
20
21    /**
22     * @var LineString[] The elements of a MultiLineString are LineStrings
23     */
24    protected $components = [];
25
26    public function geometryType()
27    {
28        return Geometry::MULTI_LINE_STRING;
29    }
30
31    public function centroid()
32    {
33        if ($this->isEmpty()) {
34            return null;
35        }
36
37        if ($this->getGeos()) {
38            // @codeCoverageIgnoreStart
39            /** @noinspection PhpUndefinedMethodInspection */
40            return geoPHP::geosToGeometry($this->getGeos()->centroid());
41            // @codeCoverageIgnoreEnd
42        }
43
44        $x = 0;
45        $y = 0;
46        $totalLength = 0;
47        $componentLength = 0;
48        $components = $this->getComponents();
49        foreach ($components as $line) {
50            if ($line->isEmpty()) {
51                continue;
52            }
53            $componentCentroid = $line->getCentroidAndLength($componentLength);
54            $x += $componentCentroid->x() * $componentLength;
55            $y += $componentCentroid->y() * $componentLength;
56            $totalLength += $componentLength;
57        }
58        if ($totalLength == 0) {
59            return $this->getPoints()[0];
60        }
61        return new Point($x / $totalLength, $y / $totalLength);
62    }
63
64    /**
65     * The boundary of a MultiLineString is a MultiPoint consists of the start and end points of its non-closed LineStrings
66     *
67     * @return MultiPoint
68     */
69    public function boundary()
70    {
71        $points = [];
72        foreach ($this->components as $line) {
73            if (!$line->isEmpty() && !$line->isClosed()) {
74                $points[] = $line->startPoint();
75                $points[] = $line->endPoint();
76            }
77        }
78        return new MultiPoint($points);
79    }
80}
81