1<?php
2
3namespace geoPHP\Geometry;
4
5use geoPHP\geoPHP;
6
7/**
8 * A MultiPoint is a 0-dimensional Collection.
9 * The elements of a MultiPoint are restricted to Points.
10 * The Points are not connected or ordered in any semantically important way.
11 * A MultiPoint is simple if no two Points in the MultiPoint are equal (have identical coordinate values in X and Y).
12 * Every MultiPoint is spatially equal under the definition in OGC 06-103r4 Clause 6.1.15.3 to a simple Multipoint.
13 *
14 * @method Point[] getComponents()
15 * @property Point[] $components The elements of a MultiPoint are Points
16 */
17class MultiPoint extends MultiGeometry
18{
19
20    public function __construct($components = [])
21    {
22        parent::__construct($components, true, Point::class);
23    }
24
25    /**
26     * @return string
27     */
28    public function geometryType()
29    {
30        return Geometry::MULTI_POINT;
31    }
32
33    /**
34     * MultiPoint is 0-dimensional
35     * @return int 0
36     */
37    public function dimension()
38    {
39        return 0;
40    }
41
42    public static function fromArray($array)
43    {
44        $points = [];
45        foreach ($array as $point) {
46            $points[] = Point::fromArray($point);
47        }
48        return new static($points);
49    }
50
51    /**
52     * A MultiPoint is simple if no two Points in the MultiPoint are equal
53     * (have identical coordinate values in X and Y).
54     *
55     * @return bool
56     */
57    public function isSimple()
58    {
59        $componentCount = count($this->components);
60        for ($i = 0; $i < $componentCount; $i++) {
61            for ($j = $i + 1; $j < $componentCount; $j++) {
62                if ($this->components[$i]->equals($this->components[$j])) {
63                    return false;
64                }
65            }
66        }
67        return true;
68    }
69
70    /**
71     * The boundary of a MultiPoint is the empty set.
72     * @return GeometryCollection
73     */
74    public function boundary()
75    {
76        return new GeometryCollection();
77    }
78
79    public function numPoints()
80    {
81        return $this->numGeometries();
82    }
83
84    public function centroid()
85    {
86        if ($this->isEmpty()) {
87            return new Point();
88        }
89
90        if ($this->getGeos()) {
91            // @codeCoverageIgnoreStart
92            /** @noinspection PhpUndefinedMethodInspection */
93            return geoPHP::geosToGeometry($this->getGeos()->centroid());
94            // @codeCoverageIgnoreEnd
95        }
96
97        $x = 0;
98        $y = 0;
99        foreach ($this->getComponents() as $component) {
100            $x += $component->x();
101            $y += $component->y();
102        }
103        return new Point($x / $this->numPoints(), $y / $this->numPoints());
104    }
105
106    // Not valid for this geometry type
107    // --------------------------------
108    public function explode($toArray = false)
109    {
110        return null;
111    }
112}
113