1<?php
2
3namespace geoPHP\Geometry;
4
5use geoPHP\geoPHP;
6
7/**
8 * MultiPolygon: A collection of Polygons
9 *
10 * @method Polygon[] getComponents()
11 * @property Polygon[] $components
12 */
13class MultiPolygon extends MultiSurface
14{
15
16    public function __construct($components = [])
17    {
18        parent::__construct($components, true, Polygon::class);
19    }
20
21    public function geometryType()
22    {
23        return Geometry::MULTI_POLYGON;
24    }
25
26    public function centroid()
27    {
28        if ($this->isEmpty()) {
29            return null;
30        }
31
32        if ($this->getGeos()) {
33            // @codeCoverageIgnoreStart
34            /** @noinspection PhpUndefinedMethodInspection */
35            return geoPHP::geosToGeometry($this->getGeos()->centroid());
36            // @codeCoverageIgnoreEnd
37        }
38
39        $x = 0;
40        $y = 0;
41        $totalArea = 0;
42        foreach ($this->getComponents() as $component) {
43            if ($component->isEmpty()) {
44                continue;
45            }
46            $componentArea = $component->area();
47            $totalArea += $componentArea;
48            $componentCentroid = $component->centroid();
49            $x += $componentCentroid->x() * $componentArea;
50            $y += $componentCentroid->y() * $componentArea;
51        }
52        return new Point($x / $totalArea, $y / $totalArea);
53    }
54
55    public function area()
56    {
57        if ($this->getGeos()) {
58            // @codeCoverageIgnoreStart
59            /** @noinspection PhpUndefinedMethodInspection */
60            return $this->getGeos()->area();
61            // @codeCoverageIgnoreEnd
62        }
63
64        $area = 0;
65        foreach ($this->components as $component) {
66            $area += $component->area();
67        }
68        return $area;
69    }
70
71    public function boundary()
72    {
73        $rings = [];
74        foreach ($this->getComponents() as $component) {
75            $rings = array_merge($rings, $component->components);
76        }
77        return new MultiLineString($rings);
78    }
79}
80