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

brick / geo / 13642551372

03 Mar 2025 11:25PM UTC coverage: 84.406% (+0.8%) from 83.61%
13642551372

push

github

BenMorel
Merge WKTParser & EWKTParser

31 of 32 new or added lines in 3 files covered. (96.88%)

69 existing lines in 8 files now uncovered.

1548 of 1834 relevant lines covered (84.41%)

1988.83 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
 */
30
class GeometryCollection extends Geometry
31
{
32
    /**
33
     * The geometries that compose this GeometryCollection.
34
     *
35
     * This array can be empty.
36
     *
37
     * @psalm-var list<T>
38
     *
39
     * @var Geometry[]
40
     */
41
    protected array $geometries = [];
42

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

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

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

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

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

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

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

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

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

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

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

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

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

142
    #[Override]
143
    public function geometryType() : string
144
    {
145
        return 'GeometryCollection';
953✔
146
    }
147

148
    #[Override]
149
    public function geometryTypeBinary() : int
150
    {
151
        return Geometry::GEOMETRYCOLLECTION;
336✔
152
    }
153

154
    #[Override]
155
    public function dimension() : int
156
    {
157
        $dimension = 0;
56✔
158

159
        foreach ($this->geometries as $geometry) {
56✔
160
            $dim = $geometry->dimension();
28✔
161

162
            if ($dim > $dimension) {
28✔
163
                $dimension = $dim;
21✔
164
            }
165
        }
166

167
        return $dimension;
56✔
168
    }
169

170
    #[Override]
171
    public function getBoundingBox() : BoundingBox
172
    {
173
        $boundingBox = BoundingBox::new();
×
174

UNCOV
175
        foreach ($this->geometries as $geometry) {
×
UNCOV
176
            $boundingBox = $boundingBox->extendedWithBoundingBox($geometry->getBoundingBox());
×
177
        }
178

UNCOV
179
        return $boundingBox;
×
180
    }
181

182
    #[Override]
183
    public function toArray() : array
184
    {
185
        $result = [];
1,624✔
186

187
        foreach ($this->geometries as $geometry) {
1,624✔
188
            $result[] = $geometry->toArray();
1,022✔
189
        }
190

191
        return $result;
1,624✔
192
    }
193

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

209
    /**
210
     * Returns the number of geometries in this GeometryCollection.
211
     *
212
     * Required by interface Countable.
213
     */
214
    #[Override]
215
    public function count() : int
216
    {
217
        return count($this->geometries);
2,059✔
218
    }
219

220
    /**
221
     * Returns an iterator for the geometries in this GeometryCollection.
222
     *
223
     * Required by interface IteratorAggregate.
224
     *
225
     * @psalm-return ArrayIterator<int<0, max>, T>
226
     */
227
    #[Override]
228
    public function getIterator() : ArrayIterator
229
    {
230
        return new ArrayIterator($this->geometries);
4,419✔
231
    }
232

233
    /**
234
     * Returns the FQCN of the contained Geometry type.
235
     *
236
     * @psalm-return class-string<T>
237
     */
238
    protected function containedGeometryType() : string
239
    {
240
        return Geometry::class;
1,103✔
241
    }
242

243
    /**
244
     * Returns a copy of this GeometryCollection, with the given geometries added.
245
     *
246
     * @param T ...$geometries
247
     *
248
     * @psalm-suppress UnsafeGenericInstantiation Not sure how to fix this.
249
     */
250
    public function withAddedGeometries(Geometry ...$geometries): static
251
    {
252
        return new static($this->coordinateSystem, ...$this->geometries, ...$geometries);
147✔
253
    }
254
}
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