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

brick / geo / 14062713921

25 Mar 2025 02:49PM UTC coverage: 62.13% (+0.2%) from 61.936%
14062713921

push

github

BenMorel
Implement PgsqlDriver (pgsql extension)

0 of 52 new or added lines in 1 file covered. (0.0%)

59 existing lines in 8 files now uncovered.

1890 of 3042 relevant lines covered (62.13%)

1687.76 hits per line

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

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

3
declare(strict_types=1);
4

5
namespace Brick\Geo;
6

7
use Brick\Geo\Attribute\NoProxy;
8
use Brick\Geo\Exception\CoordinateSystemException;
9
use Brick\Geo\Exception\GeometryIoException;
10
use Brick\Geo\Exception\InvalidGeometryException;
11
use Brick\Geo\Exception\UnexpectedGeometryException;
12
use Brick\Geo\Io\WktReader;
13
use Brick\Geo\Io\WktWriter;
14
use Brick\Geo\Io\WkbReader;
15
use Brick\Geo\Io\WkbWriter;
16
use Brick\Geo\Projector\Projector;
17
use Brick\Geo\Projector\RemoveZmProjector;
18
use Brick\Geo\Projector\RoundCoordinatesProjector;
19
use Brick\Geo\Projector\SridProjector;
20
use Brick\Geo\Projector\SwapXyProjector;
21
use Override;
22

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

47
    /**
48
     * The coordinate system of this geometry.
49
     */
50
    protected CoordinateSystem $coordinateSystem;
51

52
    /**
53
     * Whether this geometry is empty.
54
     */
55
    protected bool $isEmpty;
56

57
    /**
58
     * @param CoordinateSystem $coordinateSystem The coordinate system of this geometry.
59
     * @param bool             $isEmpty          Whether this geometry is empty.
60
     */
61
    protected function __construct(CoordinateSystem $coordinateSystem, bool $isEmpty)
62
    {
63
        $this->coordinateSystem = $coordinateSystem;
35,959✔
64
        $this->isEmpty          = $isEmpty;
35,959✔
65
    }
66

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

88
        if ($wktReader === null) {
8,263✔
89
            $wktReader = new WktReader();
8✔
90
        }
91

92
        $geometry = $wktReader->read($wkt, $srid);
8,263✔
93

94
        if ($geometry instanceof static) {
8,207✔
95
            return $geometry;
8,135✔
96
        }
97

98
        throw UnexpectedGeometryException::unexpectedGeometryType(static::class, $geometry);
72✔
99
    }
100

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

122
        if ($wkbReader === null) {
128✔
123
            $wkbReader = new WkbReader();
8✔
124
        }
125

126
        $geometry = $wkbReader->read($wkb, $srid);
128✔
127

128
        if ($geometry instanceof static) {
128✔
129
            return $geometry;
48✔
130
        }
131

132
        throw UnexpectedGeometryException::unexpectedGeometryType(static::class, $geometry);
80✔
133
    }
134

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

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

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

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

178
    abstract public function geometryTypeBinary() : int;
179

180
    /**
181
     * Returns the Spatial Reference System ID for this geometry.
182
     *
183
     * @return int The SRID, zero if not set.
184
     */
185
    #[NoProxy]
186
    public function srid() : int
187
    {
188
        return $this->coordinateSystem->srid();
17,076✔
189
    }
190

191
    /**
192
     * Returns the WKT representation of this geometry.
193
     */
194
    #[NoProxy]
195
    public function asText() : string
196
    {
197
        /** @var WktWriter|null $wktWriter */
198
        static $wktWriter;
4,750✔
199

200
        if ($wktWriter === null) {
4,750✔
201
            $wktWriter = new WktWriter();
8✔
202
        }
203

204
        return $wktWriter->write($this);
4,750✔
205
    }
206

207
    /**
208
     * Returns the WKB representation of this geometry.
209
     */
210
    #[NoProxy]
211
    public function asBinary() : string
212
    {
213
        /** @var WkbWriter|null $wkbWriter */
214
        static $wkbWriter;
40✔
215

216
        if ($wkbWriter === null) {
40✔
217
            $wkbWriter = new WkbWriter();
8✔
218
        }
219

220
        return $wkbWriter->write($this);
40✔
221
    }
222

223
    /**
224
     * Returns whether this geometry is the empty Geometry.
225
     *
226
     * If true, then this geometry represents the empty point set for the coordinate space.
227
     */
228
    public function isEmpty() : bool
229
    {
230
        return $this->isEmpty;
19,377✔
231
    }
232

233
    /**
234
     * Returns whether this geometry has z coordinate values.
235
     */
236
    public function is3D() : bool
237
    {
238
        return $this->coordinateSystem->hasZ();
6,403✔
239
    }
240

241
    /**
242
     * Returns whether this geometry has m coordinate values.
243
     */
244
    public function isMeasured() : bool
245
    {
246
        return $this->coordinateSystem->hasM();
6,371✔
247
    }
248

249
    /**
250
     * Returns the coordinate system of this geometry.
251
     */
252
    public function coordinateSystem() : CoordinateSystem
253
    {
254
        return $this->coordinateSystem;
27,824✔
255
    }
256

257
    /**
258
     * Returns a copy of this Geometry, with the SRID altered.
259
     *
260
     * Note that only the SRID value is changed, the coordinates are not reprojected.
261
     * Use GeometryEngine::transform() to reproject the Geometry to another SRID.
262
     *
263
     * @return static
264
     */
265
    public function withSrid(int $srid) : Geometry
266
    {
267
        if ($srid === $this->srid()) {
224✔
268
            return $this;
×
269
        }
270

271
        return $this->project(new SridProjector($srid));
224✔
272
    }
273

274
    /**
275
     * Returns a copy of this Geometry, with Z and M coordinates removed.
276
     *
277
     * @return static
278
     */
279
    public function toXy(): Geometry
280
    {
281
        if ($this->coordinateDimension() === 2) {
×
282
            return $this;
×
283
        }
284

285
        return $this->project(new RemoveZmProjector(removeZ: true, removeM: true));
×
286
    }
287

288
    /**
289
     * Returns a copy of this Geometry, with the Z coordinate removed.
290
     *
291
     * @return static
292
     */
293
    public function withoutZ() : Geometry
294
    {
295
        if (! $this->coordinateSystem->hasZ()) {
×
296
            return $this;
×
297
        }
298

299
        return $this->project(new RemoveZmProjector(removeZ: true));
×
300
    }
301

302
    /**
303
     * Returns a copy of this Geometry, with the M coordinate removed.
304
     *
305
     * @return static
306
     */
307
    public function withoutM() : Geometry
308
    {
309
        if (! $this->coordinateSystem->hasM()) {
472✔
310
            return $this;
464✔
311
        }
312

313
        return $this->project(new RemoveZmProjector(removeM: true));
8✔
314
    }
315

316
    /**
317
     * Returns a copy of this Geometry, with coordinates rounded to the given precision.
318
     *
319
     * @return static
320
     */
321
    public function withRoundedCoordinates(int $precision): Geometry
322
    {
323
        return $this->project(new RoundCoordinatesProjector($precision));
72✔
324
    }
325

326
    /**
327
     * Returns the bounding box of the Geometry.
328
     */
329
    abstract public function getBoundingBox() : BoundingBox;
330

331
    /**
332
     * Returns the raw coordinates of this geometry as an array.
333
     *
334
     * This returns potentially nested lists of floats.
335
     *
336
     * Examples:
337
     * - a Point will return list<float>
338
     * - a LineString will return list<list<float>>
339
     * - a Polygon will return list<list<list<float>>>
340
     *
341
     * Subclasses will narrow down the return type as appropriate.
342
     *
343
     * @return list<mixed>
344
     */
345
    abstract public function toArray() : array;
346

347
    /**
348
     * Returns a copy of this Geometry, with the X and Y coordinates swapped.
349
     *
350
     * @return static
351
     */
352
    public function swapXy() : Geometry
353
    {
UNCOV
354
        return $this->project(new SwapXyProjector());
14✔
355
    }
356

357
    /**
358
     * Projects this geometry to a different coordinate system.
359
     */
360
    abstract public function project(Projector $projector): Geometry;
361

362
    /**
363
     * Returns whether this Geometry is identical to another Geometry.
364
     *
365
     * This method will only return true if the geometries are of the same type, with the exact same coordinates,
366
     * in the same order, and with the same SRID.
367
     *
368
     * This is different from the concept of spatially equal; if you need to check for spatial equality,
369
     * please see `GeometryEngine::equals()` instead.
370
     */
371
    public function isIdenticalTo(Geometry $that) : bool
372
    {
373
        return $this->srid() === $that->srid() && $this->asText() === $that->asText();
224✔
374
    }
375

376
    /**
377
     * Returns a text representation of this geometry.
378
     */
379
    #[NoProxy, Override]
380
    final public function __toString() : string
381
    {
382
        return $this->asText();
32✔
383
    }
384
}
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