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

brick / geo / 13350035722

16 Feb 2025 12:31AM UTC coverage: 82.19% (+34.9%) from 47.314%
13350035722

push

github

BenMorel
Use PHP 8.4 lazy proxies

30 of 49 new or added lines in 2 files covered. (61.22%)

55 existing lines in 4 files now uncovered.

1486 of 1808 relevant lines covered (82.19%)

1750.76 hits per line

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

80.43
/src/Geometry.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Brick\Geo;
6

7
use Brick\Geo\Exception\CoordinateSystemException;
8
use Brick\Geo\Exception\GeometryIOException;
9
use Brick\Geo\Exception\InvalidGeometryException;
10
use Brick\Geo\Exception\UnexpectedGeometryException;
11
use Brick\Geo\IO\WKTReader;
12
use Brick\Geo\IO\WKTWriter;
13
use Brick\Geo\IO\WKBReader;
14
use Brick\Geo\IO\WKBWriter;
15
use Brick\Geo\Projector\Projector;
16
use Brick\Geo\Projector\RemoveZMProjector;
17
use Brick\Geo\Projector\SRIDProjector;
18
use Brick\Geo\Projector\SwapXYProjector;
19

20
/**
21
 * Geometry is the root class of the hierarchy.
22
 */
23
abstract class Geometry implements \Countable, \IteratorAggregate, \Stringable
24
{
25
    final public const int GEOMETRY           = 0;
26
    final public const int POINT              = 1;
27
    final public const int LINESTRING         = 2;
28
    final public const int POLYGON            = 3;
29
    final public const int MULTIPOINT         = 4;
30
    final public const int MULTILINESTRING    = 5;
31
    final public const int MULTIPOLYGON       = 6;
32
    final public const int GEOMETRYCOLLECTION = 7;
33
    final public const int CIRCULARSTRING     = 8;
34
    final public const int COMPOUNDCURVE      = 9;
35
    final public const int CURVEPOLYGON       = 10;
36
    final public const int MULTICURVE         = 11;
37
    final public const int MULTISURFACE       = 12;
38
    final public const int CURVE              = 13;
39
    final public const int SURFACE            = 14;
40
    final public const int POLYHEDRALSURFACE  = 15;
41
    final public const int TIN                = 16;
42
    final public const int TRIANGLE           = 17;
43

44
    /**
45
     * The coordinate system of this geometry.
46
     */
47
    protected CoordinateSystem $coordinateSystem;
48

49
    /**
50
     * Whether this geometry is empty.
51
     */
52
    protected bool $isEmpty;
53

54
    /**
55
     * @param CoordinateSystem $coordinateSystem The coordinate system of this geometry.
56
     * @param bool             $isEmpty          Whether this geometry is empty.
57
     */
58
    protected function __construct(CoordinateSystem $coordinateSystem, bool $isEmpty)
59
    {
60
        $this->coordinateSystem = $coordinateSystem;
23,438✔
61
        $this->isEmpty          = $isEmpty;
23,438✔
62
    }
63

64
    /**
65
     * Builds a Geometry from a WKT representation.
66
     *
67
     * If the resulting geometry is valid but is not an instance of the class this method is called on,
68
     * for example passing a Polygon WKT to Point::fromText(), an exception is thrown.
69
     *
70
     * @param string $wkt  The Well-Known Text representation.
71
     * @param int    $srid The optional SRID to use.
72
     *
73
     * @return static
74
     *
75
     * @throws GeometryIOException         If the given string is not a valid WKT representation.
76
     * @throws CoordinateSystemException   If the WKT contains mixed coordinate systems.
77
     * @throws InvalidGeometryException    If the WKT represents an invalid geometry.
78
     * @throws UnexpectedGeometryException If the resulting geometry is not an instance of the current class.
79
     */
80
    public static function fromText(string $wkt, int $srid = 0) : Geometry
81
    {
82
        /** @var WKTReader|null $wktReader */
83
        static $wktReader;
5,952✔
84

85
        if ($wktReader === null) {
5,952✔
86
            $wktReader = new WKTReader();
7✔
87
        }
88

89
        $geometry = $wktReader->read($wkt, $srid);
5,952✔
90

91
        if ($geometry instanceof static) {
5,903✔
92
            return $geometry;
5,840✔
93
        }
94

95
        throw UnexpectedGeometryException::unexpectedGeometryType(static::class, $geometry);
63✔
96
    }
97

98
    /**
99
     * Builds a Geometry from a WKB representation.
100
     *
101
     * If the resulting geometry is valid but is not an instance of the class this method is called on,
102
     * for example passing a Polygon WKB to Point::fromBinary(), an exception is thrown.
103
     *
104
     * @param string $wkb  The Well-Known Binary representation.
105
     * @param int    $srid The optional SRID to use.
106
     *
107
     * @return static
108
     *
109
     * @throws GeometryIOException         If the given string is not a valid WKB representation.
110
     * @throws CoordinateSystemException   If the WKB contains mixed coordinate systems.
111
     * @throws InvalidGeometryException    If the WKB represents an invalid geometry.
112
     * @throws UnexpectedGeometryException If the resulting geometry is not an instance of the current class.
113
     */
114
    public static function fromBinary(string $wkb, int $srid = 0) : Geometry
115
    {
116
        /** @var WKBReader|null $wkbReader */
117
        static $wkbReader;
326✔
118

119
        if ($wkbReader === null) {
326✔
120
            $wkbReader = new WKBReader();
7✔
121
        }
122

123
        $geometry = $wkbReader->read($wkb, $srid);
326✔
124

125
        if ($geometry instanceof static) {
326✔
126
            return $geometry;
256✔
127
        }
128

129
        throw UnexpectedGeometryException::unexpectedGeometryType(static::class, $geometry);
70✔
130
    }
131

132
    /**
133
     * Returns the inherent dimension of this geometry.
134
     *
135
     * This dimension must be less than or equal to the coordinate dimension.
136
     * In non-homogeneous collections, this will return the largest topological dimension of the contained objects.
137
     */
138
    abstract public function dimension() : int;
139

140
    /**
141
     * Returns the coordinate dimension of this geometry.
142
     *
143
     * The coordinate dimension is the total number of coordinates in the coordinate system.
144
     *
145
     * The coordinate dimension can be 2 (for x and y), 3 (with z or m added), or 4 (with both z and m added).
146
     * The ordinates x, y and z are spatial, and the ordinate m is a measure.
147
     *
148
     * @return int<2, 4>
149
     */
150
    public function coordinateDimension() : int
151
    {
152
        return $this->coordinateSystem->coordinateDimension();
56✔
153
    }
154

155
    /**
156
     * Returns the spatial dimension of this geometry.
157
     *
158
     * The spatial dimension is the number of measurements or axes needed to describe the
159
     * spatial position of this geometry in a coordinate system.
160
     *
161
     * The spatial dimension is 3 if the coordinate system has a Z coordinate, 2 otherwise.
162
     *
163
     * @return int<2, 3>
164
     */
165
    public function spatialDimension() : int
166
    {
167
        return $this->coordinateSystem->spatialDimension();
56✔
168
    }
169

170
    /**
171
     * Returns the name of the instantiable subtype of Geometry of which this Geometry is an instantiable member.
172
     */
173
    abstract public function geometryType() : string;
174

175
    abstract public function geometryTypeBinary() : int;
176

177
    /**
178
     * Returns the Spatial Reference System ID for this geometry.
179
     *
180
     * @return int The SRID, zero if not set.
181
     */
182
    public function SRID() : int
183
    {
184
        return $this->coordinateSystem->SRID();
14,055✔
185
    }
186

187
    /**
188
     * Returns the WKT representation of this geometry.
189
     */
190
    public function asText() : string
191
    {
192
        /** @var WKTWriter|null $wktWriter */
193
        static $wktWriter;
3,244✔
194

195
        if ($wktWriter === null) {
3,244✔
196
            $wktWriter = new WKTWriter();
7✔
197
        }
198

199
        return $wktWriter->write($this);
3,244✔
200
    }
201

202
    /**
203
     * Returns the WKB representation of this geometry.
204
     */
205
    public function asBinary() : string
206
    {
207
        /** @var WKBWriter|null $wkbWriter */
208
        static $wkbWriter;
1,181✔
209

210
        if ($wkbWriter === null) {
1,181✔
211
            $wkbWriter = new WKBWriter();
7✔
212
        }
213

214
        return $wkbWriter->write($this);
1,181✔
215
    }
216

217
    /**
218
     * Returns whether this geometry is the empty Geometry.
219
     *
220
     * If true, then this geometry represents the empty point set for the coordinate space.
221
     */
222
    public function isEmpty() : bool
223
    {
224
        return $this->isEmpty;
13,991✔
225
    }
226

227
    /**
228
     * Returns whether this geometry has z coordinate values.
229
     */
230
    public function is3D() : bool
231
    {
232
        return $this->coordinateSystem->hasZ();
5,236✔
233
    }
234

235
    /**
236
     * Returns whether this geometry has m coordinate values.
237
     */
238
    public function isMeasured() : bool
239
    {
240
        return $this->coordinateSystem->hasM();
5,236✔
241
    }
242

243
    /**
244
     * Returns the coordinate system of this geometry.
245
     */
246
    public function coordinateSystem() : CoordinateSystem
247
    {
248
        return $this->coordinateSystem;
19,245✔
249
    }
250

251
    /**
252
     * Returns a copy of this Geometry, with the SRID altered.
253
     *
254
     * Note that only the SRID value is changed, the coordinates are not reprojected.
255
     * Use GeometryEngine::transform() to reproject the Geometry to another SRID.
256
     *
257
     * @return static
258
     */
259
    public function withSRID(int $srid) : Geometry
260
    {
261
        if ($srid === $this->SRID()) {
196✔
262
            return $this;
×
263
        }
264

265
        return $this->project(new SRIDProjector($srid));
196✔
266
    }
267

268
    /**
269
     * Returns a copy of this Geometry, with Z and M coordinates removed.
270
     *
271
     * @return static
272
     */
273
    public function toXY(): Geometry
274
    {
275
        if ($this->coordinateDimension() === 2) {
×
276
            return $this;
×
277
        }
278

279
        return $this->project(new RemoveZMProjector(removeZ: true, removeM: true));
×
280
    }
281

282
    /**
283
     * Returns a copy of this Geometry, with the Z coordinate removed.
284
     *
285
     * @return static
286
     */
287
    public function withoutZ() : Geometry
288
    {
289
        if (! $this->coordinateSystem->hasZ()) {
×
290
            return $this;
×
291
        }
292

293
        return $this->project(new RemoveZMProjector(removeZ: true));
×
294
    }
295

296
    /**
297
     * Returns a copy of this Geometry, with the M coordinate removed.
298
     *
299
     * @return static
300
     */
301
    public function withoutM() : Geometry
302
    {
303
        if (! $this->coordinateSystem->hasM()) {
378✔
304
            return $this;
378✔
305
        }
306

307
        return $this->project(new RemoveZMProjector(removeM: true));
7✔
308
    }
309

310
    /**
311
     * Returns the bounding box of the Geometry.
312
     */
313
    abstract public function getBoundingBox() : BoundingBox;
314

315
    /**
316
     * Returns the raw coordinates of this geometry as an array.
317
     */
318
    abstract public function toArray() : array;
319

320
    /**
321
     * Returns a copy of this Geometry, with the X and Y coordinates swapped.
322
     *
323
     * @return static
324
     */
325
    public function swapXY() : Geometry
326
    {
327
        return $this->project(new SwapXYProjector());
×
328
    }
329

330
    /**
331
     * Projects this geometry to a different coordinate system.
332
     */
333
    abstract public function project(Projector $projector): Geometry;
334

335
    /**
336
     * Returns whether this Geometry is identical to another Geometry.
337
     *
338
     * This method will only return true if the geometries are of the same type, with the exact same coordinates,
339
     * in the same order, and with the same SRID.
340
     *
341
     * This is different from the concept of spatially equal; if you need to check for spatial equality,
342
     * please see `GeometryEngine::equals()` instead.
343
     */
344
    public function isIdenticalTo(Geometry $that) : bool
345
    {
346
        return $this->SRID() === $that->SRID() && $this->asText() === $that->asText();
196✔
347
    }
348

349
    /**
350
     * Returns a text representation of this geometry.
351
     */
352
    final public function __toString() : string
353
    {
UNCOV
354
        return $this->asText();
×
355
    }
356
}
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