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

brick / geo / 13896561332

17 Mar 2025 09:58AM UTC coverage: 82.525% (-4.8%) from 87.282%
13896561332

push

github

BenMorel
Add Point::isEqualTo() (WIP: finish? keep?)

8 of 8 new or added lines in 2 files covered. (100.0%)

15 existing lines in 2 files now uncovered.

1667 of 2020 relevant lines covered (82.52%)

1899.11 hits per line

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

80.85
/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\RoundCoordinatesProjector;
18
use Brick\Geo\Projector\SridProjector;
19
use Brick\Geo\Projector\SwapXyProjector;
20
use Override;
21

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

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

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

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

66
    /**
67
     * Builds a Geometry from a WKT representation.
68
     *
69
     * If the resulting geometry is valid but is not an instance of the class this method is called on,
70
     * for example passing a Polygon WKT to Point::fromText(), an exception is thrown.
71
     *
72
     * @param string $wkt  The Well-Known Text representation.
73
     * @param int    $srid The optional SRID to use.
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) : static
81
    {
82
        /** @var WktReader|null $wktReader */
83
        static $wktReader;
7,773✔
84

85
        if ($wktReader === null) {
7,773✔
86
            $wktReader = new WktReader();
7✔
87
        }
88

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

91
        if ($geometry instanceof static) {
7,724✔
92
            return $geometry;
7,661✔
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
     * @throws GeometryIoException         If the given string is not a valid WKB representation.
108
     * @throws CoordinateSystemException   If the WKB contains mixed coordinate systems.
109
     * @throws InvalidGeometryException    If the WKB represents an invalid geometry.
110
     * @throws UnexpectedGeometryException If the resulting geometry is not an instance of the current class.
111
     */
112
    public static function fromBinary(string $wkb, int $srid = 0) : static
113
    {
114
        /** @var WkbReader|null $wkbReader */
115
        static $wkbReader;
98✔
116

117
        if ($wkbReader === null) {
98✔
118
            $wkbReader = new WkbReader();
7✔
119
        }
120

121
        $geometry = $wkbReader->read($wkb, $srid);
98✔
122

123
        if ($geometry instanceof static) {
98✔
124
            return $geometry;
28✔
125
        }
126

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

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

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

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

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

173
    abstract public function geometryTypeBinary() : int;
174

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

185
    /**
186
     * Returns the WKT representation of this geometry.
187
     */
188
    public function asText() : string
189
    {
190
        /** @var WktWriter|null $wktWriter */
191
        static $wktWriter;
5,710✔
192

193
        if ($wktWriter === null) {
5,710✔
194
            $wktWriter = new WktWriter();
7✔
195
        }
196

197
        return $wktWriter->write($this);
5,710✔
198
    }
199

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

208
        if ($wkbWriter === null) {
1,679✔
209
            $wkbWriter = new WkbWriter();
7✔
210
        }
211

212
        return $wkbWriter->write($this);
1,679✔
213
    }
214

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

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

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

241
    /**
242
     * Returns the coordinate system of this geometry.
243
     *
244
     * @deprecated Use $coordinateSystem property instead.
245
     */
246
    public function coordinateSystem() : CoordinateSystem
247
    {
UNCOV
248
        return $this->coordinateSystem;
×
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
    public function withSrid(int $srid) : static
258
    {
259
        if ($srid === $this->srid()) {
196✔
UNCOV
260
            return $this;
×
261
        }
262

263
        return $this->project(new SridProjector($srid));
196✔
264
    }
265

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

UNCOV
275
        return $this->project(new RemoveZmProjector(removeZ: true, removeM: true));
×
276
    }
277

278
    /**
279
     * Returns a copy of this Geometry, with the Z coordinate removed.
280
     */
281
    public function withoutZ() : static
282
    {
283
        if (! $this->coordinateSystem->hasZ) {
×
UNCOV
284
            return $this;
×
285
        }
286

UNCOV
287
        return $this->project(new RemoveZmProjector(removeZ: true));
×
288
    }
289

290
    /**
291
     * Returns a copy of this Geometry, with the M coordinate removed.
292
     */
293
    public function withoutM() : static
294
    {
295
        if (! $this->coordinateSystem->hasM) {
693✔
296
            return $this;
567✔
297
        }
298

299
        return $this->project(new RemoveZmProjector(removeM: true));
182✔
300
    }
301

302
    /**
303
     * Returns a copy of this Geometry, with coordinates rounded to the given precision.
304
     *
305
     * @return static
306
     */
307
    public function withRoundedCoordinates(int $precision): Geometry
308
    {
309
        return $this->project(new RoundCoordinatesProjector($precision));
63✔
310
    }
311

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

317
    /**
318
     * Returns the raw coordinates of this geometry as an array.
319
     *
320
     * This returns potentially nested lists of floats.
321
     *
322
     * Examples:
323
     * - a Point will return list<float>
324
     * - a LineString will return list<list<float>>
325
     * - a Polygon will return list<list<list<float>>>
326
     *
327
     * Subclasses will narrow down the return type as appropriate.
328
     *
329
     * @return list<mixed>
330
     */
331
    abstract public function toArray() : array;
332

333
    /**
334
     * Returns a copy of this Geometry, with the X and Y coordinates swapped.
335
     */
336
    public function swapXy() : static
337
    {
338
        return $this->project(new SwapXyProjector());
14✔
339
    }
340

341
    /**
342
     * Projects this geometry to a different coordinate system.
343
     */
344
    abstract public function project(Projector $projector): static;
345

346
    /**
347
     * Returns whether this Geometry is identical to another Geometry.
348
     *
349
     * This method will only return true if the geometries are of the same type, with the exact same coordinates,
350
     * in the same order, and with the same SRID.
351
     *
352
     * This is different from the concept of spatially equal; if you need to check for spatial equality,
353
     * please see `GeometryEngine::equals()` instead.
354
     */
355
    public function isIdenticalTo(Geometry $that) : bool
356
    {
357
        return $this->srid() === $that->srid() && $this->asText() === $that->asText();
196✔
358
    }
359

360
    /**
361
     * Returns a text representation of this geometry.
362
     */
363
    #[Override]
364
    final public function __toString() : string
365
    {
UNCOV
366
        return $this->asText();
×
367
    }
368
}
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