• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

brick / geo / 13687942239

05 Mar 2025 11:54PM UTC coverage: 84.507% (+0.07%) from 84.44%
13687942239

push

github

BenMorel
Remove Psalm-specific annotations

1560 of 1846 relevant lines covered (84.51%)

1977.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.77
/src/GeometryCollection.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Brick\Geo;
6

7
use ArrayIterator;
8
use Brick\Geo\Exception\CoordinateSystemException;
9
use Brick\Geo\Exception\NoSuchGeometryException;
10
use Brick\Geo\Exception\UnexpectedGeometryException;
11
use Brick\Geo\Projector\Projector;
12
use Override;
13

14
/**
15
 * A GeometryCollection is a geometric object that is a collection of some number of geometric objects.
16
 *
17
 * All the elements in a GeometryCollection shall be in the same Spatial Reference System. This is also the Spatial
18
 * Reference System for the GeometryCollection.
19
 *
20
 * GeometryCollection places no other constraints on its elements. Subclasses of GeometryCollection may restrict
21
 * membership based on dimension and may also place other constraints on the degree of spatial overlap between
22
 * elements.
23
 *
24
 * By the nature of digital representations, collections are inherently ordered by the underlying storage mechanism.
25
 * Two collections whose difference is only this order are spatially equal and will return equivalent results in any
26
 * geometric-defined operations.
27
 *
28
 * @template T of Geometry
29
 * @template-implements \IteratorAggregate<T>
30
 */
31
class GeometryCollection extends Geometry implements \Countable, \IteratorAggregate
32
{
33
    /**
34
     * The geometries that compose this GeometryCollection.
35
     *
36
     * This array can be empty.
37
     *
38
     * @var list<T>
39
     */
40
    protected array $geometries = [];
41

42
    /**
43
     * @param T ...$geometries
44
     *
45
     * @throws CoordinateSystemException   If different coordinate systems are used.
46
     * @throws UnexpectedGeometryException If a geometry is not a valid type for a subclass of GeometryCollection.
47
     */
48
    final public function __construct(CoordinateSystem $cs, Geometry ...$geometries)
49
    {
50
        $isEmpty = true;
8,018✔
51

52
        foreach ($geometries as $geometry) {
8,018✔
53
            if (! $geometry->isEmpty()) {
5,011✔
54
                $isEmpty = false;
4,934✔
55
                break;
4,934✔
56
            }
57
        }
58

59
        parent::__construct($cs, $isEmpty);
8,018✔
60

61
        if (! $geometries) {
8,018✔
62
            return;
3,056✔
63
        }
64

65
        CoordinateSystem::check($this, ...$geometries);
5,011✔
66

67
        $containedGeometryType = $this->containedGeometryType();
5,011✔
68

69
        foreach ($geometries as $geometry) {
5,011✔
70
            /**
71
             * @psalm-suppress DocblockTypeContradiction We do want to enforce this in code, as not everyone uses static analysis!
72
             * @psalm-suppress MixedArgument It looks like due to this check, Psalm considers that $geometry has no type anymore.
73
             */
74
            if (! $geometry instanceof $containedGeometryType) {
5,011✔
75
                throw new UnexpectedGeometryException(sprintf(
×
76
                    '%s expects instance of %s, instance of %s given.',
×
77
                    static::class,
×
78
                    $containedGeometryType,
×
79
                    $geometry::class
×
80
                ));
×
81
            }
82
        }
83

84
        $this->geometries = array_values($geometries);
5,011✔
85
    }
86

87
    /**
88
     * Creates a non-empty GeometryCollection composed of the given geometries.
89
     *
90
     * @param Geometry    $geometry1 The first geometry.
91
     * @param Geometry ...$geometryN The subsequent geometries, if any.
92
     *
93
     * @throws CoordinateSystemException   If the geometries use different coordinate systems.
94
     * @throws UnexpectedGeometryException If a geometry is not a valid type for a subclass of GeometryCollection.
95
     *
96
     * @psalm-suppress UnsafeGenericInstantiation Not sure how to fix this.
97
     */
98
    public static function of(Geometry $geometry1, Geometry ...$geometryN) : static
99
    {
100
        return new static($geometry1->coordinateSystem(), $geometry1, ...$geometryN);
203✔
101
    }
102

103
    /**
104
     * Returns the number of geometries in this GeometryCollection.
105
     */
106
    public function numGeometries() : int
107
    {
108
        return count($this->geometries);
3,804✔
109
    }
110

111
    /**
112
     * Returns the specified geometry N in this GeometryCollection.
113
     *
114
     * @param int $n The geometry number, 1-based.
115
     *
116
     * @return T
117
     *
118
     * @throws NoSuchGeometryException If there is no Geometry at this index.
119
     */
120
    public function geometryN(int $n) : Geometry
121
    {
122
        if (! isset($this->geometries[$n - 1])) {
126✔
123
            throw new NoSuchGeometryException('There is no Geometry in this GeometryCollection at index ' . $n);
84✔
124
        }
125

126
        return $this->geometries[$n - 1];
42✔
127
    }
128

129
    /**
130
     * Returns the geometries that compose this GeometryCollection.
131
     *
132
     * @return list<T>
133
     */
134
    public function geometries() : array
135
    {
136
        return $this->geometries;
84✔
137
    }
138

139
    #[Override]
140
    public function geometryType() : string
141
    {
142
        return 'GeometryCollection';
953✔
143
    }
144

145
    #[Override]
146
    public function geometryTypeBinary() : int
147
    {
148
        return Geometry::GEOMETRYCOLLECTION;
336✔
149
    }
150

151
    #[Override]
152
    public function dimension() : int
153
    {
154
        $dimension = 0;
56✔
155

156
        foreach ($this->geometries as $geometry) {
56✔
157
            $dim = $geometry->dimension();
28✔
158

159
            if ($dim > $dimension) {
28✔
160
                $dimension = $dim;
21✔
161
            }
162
        }
163

164
        return $dimension;
56✔
165
    }
166

167
    #[Override]
168
    public function getBoundingBox() : BoundingBox
169
    {
170
        $boundingBox = BoundingBox::new();
×
171

172
        foreach ($this->geometries as $geometry) {
×
173
            $boundingBox = $boundingBox->extendedWithBoundingBox($geometry->getBoundingBox());
×
174
        }
175

176
        return $boundingBox;
×
177
    }
178

179
    #[Override]
180
    public function toArray() : array
181
    {
182
        return array_map(
350✔
183
            fn (Geometry $geometry) => $geometry->toArray(),
350✔
184
            $this->geometries,
350✔
185
        );
350✔
186
    }
187

188
    /**
189
     * @psalm-suppress UnsafeGenericInstantiation Not sure how to fix this.
190
     */
191
    #[Override]
192
    public function project(Projector $projector): static
193
    {
194
        return new static(
112✔
195
            $projector->getTargetCoordinateSystem($this->coordinateSystem),
112✔
196
            ...array_map(
112✔
197
                fn (Geometry $geometry) => $geometry->project($projector),
112✔
198
                $this->geometries,
112✔
199
            ),
112✔
200
        );
112✔
201
    }
202

203
    /**
204
     * Returns the number of geometries in this GeometryCollection.
205
     */
206
    #[Override]
207
    public function count() : int
208
    {
209
        return count($this->geometries);
2,059✔
210
    }
211

212
    /**
213
     * Returns an iterator for the geometries in this GeometryCollection.
214
     *
215
     * @return ArrayIterator<int<0, max>, T>
216
     */
217
    #[Override]
218
    public function getIterator() : ArrayIterator
219
    {
220
        return new ArrayIterator($this->geometries);
4,419✔
221
    }
222

223
    /**
224
     * Returns the FQCN of the contained Geometry type.
225
     *
226
     * @return class-string<T>
227
     */
228
    protected function containedGeometryType() : string
229
    {
230
        return Geometry::class;
1,103✔
231
    }
232

233
    /**
234
     * Returns a copy of this GeometryCollection, with the given geometries added.
235
     *
236
     * @param T ...$geometries
237
     *
238
     * @psalm-suppress UnsafeGenericInstantiation Not sure how to fix this.
239
     */
240
    public function withAddedGeometries(Geometry ...$geometries): static
241
    {
242
        return new static($this->coordinateSystem, ...$this->geometries, ...$geometries);
147✔
243
    }
244
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc