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

brick / geo / 13655507172

04 Mar 2025 02:07PM UTC coverage: 84.44% (+0.04%) from 84.402%
13655507172

push

github

BenMorel
Restrict CompoundCurve to contain LineString|CircularString

It looks like nested CompoundCurves are, in fact, forbidden.

3 of 5 new or added lines in 3 files covered. (60.0%)

88 existing lines in 4 files now uncovered.

1552 of 1838 relevant lines covered (84.44%)

1985.26 hits per line

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

93.4
/src/IO/AbstractWKBReader.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Brick\Geo\IO;
6

7
use Brick\Geo\CircularString;
8
use Brick\Geo\CompoundCurve;
9
use Brick\Geo\CoordinateSystem;
10
use Brick\Geo\Curve;
11
use Brick\Geo\CurvePolygon;
12
use Brick\Geo\Geometry;
13
use Brick\Geo\GeometryCollection;
14
use Brick\Geo\LineString;
15
use Brick\Geo\MultiLineString;
16
use Brick\Geo\MultiPoint;
17
use Brick\Geo\MultiPolygon;
18
use Brick\Geo\Point;
19
use Brick\Geo\Polygon;
20
use Brick\Geo\PolyhedralSurface;
21
use Brick\Geo\TIN;
22
use Brick\Geo\Triangle;
23

24
use Brick\Geo\Exception\GeometryIOException;
25

26
/**
27
 * Base class for WKBReader and EWKBReader.
28
 */
29
abstract class AbstractWKBReader
30
{
31
    /**
32
     * @throws GeometryIOException
33
     */
34
    abstract protected function readGeometryHeader(WKBBuffer $buffer) : WKBGeometryHeader;
35

36
    /**
37
     * @throws GeometryIOException
38
     */
39
    protected function readGeometry(WKBBuffer $buffer, int $srid) : Geometry
40
    {
41
        $buffer->readByteOrder();
8,202✔
42

43
        $geometryHeader = $this->readGeometryHeader($buffer);
8,202✔
44

45
        $cs = new CoordinateSystem(
8,202✔
46
            $geometryHeader->hasZ,
8,202✔
47
            $geometryHeader->hasM,
8,202✔
48
            $geometryHeader->srid ?? $srid
8,202✔
49
        );
8,202✔
50

51
        return match ($geometryHeader->geometryType) {
8,202✔
52
            Geometry::POINT => $this->readPoint($buffer, $cs),
2,012✔
53
            Geometry::LINESTRING => $this->readLineString($buffer, $cs),
2,822✔
54
            Geometry::CIRCULARSTRING => $this->readCircularString($buffer, $cs),
1,988✔
55
            Geometry::COMPOUNDCURVE => $this->readCompoundCurve($buffer, $cs),
1,548✔
56
            Geometry::POLYGON => $this->readPolygon($buffer, $cs),
2,418✔
57
            Geometry::CURVEPOLYGON => $this->readCurvePolygon($buffer, $cs),
1,213✔
58
            Geometry::MULTIPOINT => $this->readMultiPoint($buffer, $cs),
1,157✔
59
            Geometry::MULTILINESTRING => $this->readMultiLineString($buffer, $cs),
1,298✔
60
            Geometry::MULTIPOLYGON => $this->readMultiPolygon($buffer, $cs),
1,201✔
61
            Geometry::GEOMETRYCOLLECTION => $this->readGeometryCollection($buffer, $cs),
823✔
62
            Geometry::POLYHEDRALSURFACE => $this->readPolyhedralSurface($buffer, $cs),
741✔
63
            Geometry::TIN => $this->readTIN($buffer, $cs),
640✔
64
            Geometry::TRIANGLE => $this->readTriangle($buffer, $cs),
840✔
65
            default => throw GeometryIOException::unsupportedWKBType($geometryHeader->geometryType),
8,202✔
66
        };
8,202✔
67
    }
68

69
    private function readPoint(WKBBuffer $buffer, CoordinateSystem $cs) : Point
70
    {
71
        $coords = $buffer->readDoubles($cs->coordinateDimension());
4,749✔
72

73
        return new Point($cs, ...$coords);
4,749✔
74
    }
75

76
    private function readLineString(WKBBuffer $buffer, CoordinateSystem $cs) : LineString
77
    {
78
        $numPoints = $buffer->readUnsignedLong();
4,067✔
79

80
        $points = [];
4,067✔
81

82
        for ($i = 0; $i < $numPoints; $i++) {
4,067✔
83
            $points[] = $this->readPoint($buffer, $cs);
3,766✔
84
        }
85

86
        return new LineString($cs, ...$points);
4,067✔
87
    }
88

89
    private function readCircularString(WKBBuffer $buffer, CoordinateSystem $cs) : CircularString
90
    {
91
        $numPoints = $buffer->readUnsignedLong();
1,120✔
92

93
        $points = [];
1,120✔
94

95
        for ($i = 0; $i < $numPoints; $i++) {
1,120✔
96
            $points[] = $this->readPoint($buffer, $cs);
840✔
97
        }
98

99
        return new CircularString($cs, ...$points);
1,120✔
100
    }
101

102
    /**
103
     * @throws GeometryIOException
104
     */
105
    private function readCompoundCurve(WKBBuffer $buffer, CoordinateSystem $cs) : CompoundCurve
106
    {
107
        $numCurves = $buffer->readUnsignedLong();
700✔
108
        $curves = [];
700✔
109

110
        for ($i = 0; $i < $numCurves; $i++) {
700✔
111
            $curve = $this->readGeometry($buffer, $cs->SRID());
420✔
112

113
            if (! $curve instanceof LineString && ! $curve instanceof CircularString) {
420✔
NEW
114
                throw new GeometryIOException('Expected LineString|CircularString, got ' . $curve->geometryType());
×
115
            }
116

117
            $curves[] = $curve;
420✔
118
        }
119

120
        return new CompoundCurve($cs, ...$curves);
700✔
121
    }
122

123
    private function readPolygon(WKBBuffer $buffer, CoordinateSystem $cs) : Polygon
124
    {
125
        $numRings = $buffer->readUnsignedLong();
1,807✔
126

127
        $rings = [];
1,807✔
128

129
        for ($i = 0; $i < $numRings; $i++) {
1,807✔
130
            $rings[] = $this->readLineString($buffer, $cs);
1,513✔
131
        }
132

133
        return new Polygon($cs, ...$rings);
1,807✔
134
    }
135

136
    /**
137
     * @throws GeometryIOException
138
     */
139
    private function readCurvePolygon(WKBBuffer $buffer, CoordinateSystem $cs) : CurvePolygon
140
    {
141
        $numRings = $buffer->readUnsignedLong();
560✔
142

143
        $rings = [];
560✔
144

145
        for ($i = 0; $i < $numRings; $i++) {
560✔
146
            $ring = $this->readGeometry($buffer, $cs->SRID());
280✔
147

148
            if (! $ring instanceof Curve) {
280✔
149
                throw new GeometryIOException('Expected Curve, got ' . $ring->geometryType());
×
150
            }
151

152
            $rings[] = $ring;
280✔
153
        }
154

155
        return new CurvePolygon($cs, ...$rings);
560✔
156
    }
157

158
    /**
159
     * @throws GeometryIOException
160
     */
161
    private function readMultiPoint(WKBBuffer $buffer, CoordinateSystem $cs) : MultiPoint
162
    {
163
        $numPoints = $buffer->readUnsignedLong();
587✔
164
        $points = [];
587✔
165

166
        for ($i = 0; $i < $numPoints; $i++) {
587✔
167
            $point = $this->readGeometry($buffer, $cs->SRID());
307✔
168

169
            if (! $point instanceof Point) {
307✔
170
                throw new GeometryIOException('Expected Point, got ' . $point->geometryType());
×
171
            }
172

173
            $points[] = $point;
307✔
174
        }
175

176
        return new MultiPoint($cs, ...$points);
587✔
177
    }
178

179
    /**
180
     * @throws GeometryIOException
181
     */
182
    private function readMultiLineString(WKBBuffer $buffer, CoordinateSystem $cs) : MultiLineString
183
    {
184
        $numLineStrings = $buffer->readUnsignedLong();
849✔
185
        $lineStrings = [];
849✔
186

187
        for ($i = 0; $i < $numLineStrings; $i++) {
849✔
188
            $lineString = $this->readGeometry($buffer, $cs->SRID());
562✔
189

190
            if (! $lineString instanceof LineString) {
562✔
191
                throw new GeometryIOException('Expected LineString, got ' . $lineString->geometryType());
×
192
            }
193

194
            $lineStrings[] = $lineString;
562✔
195
        }
196

197
        return new MultiLineString($cs, ...$lineStrings);
849✔
198
    }
199

200
    /**
201
     * @throws GeometryIOException
202
     */
203
    private function readMultiPolygon(WKBBuffer $buffer, CoordinateSystem $cs) : MultiPolygon
204
    {
205
        $numPolygons = $buffer->readUnsignedLong();
876✔
206
        $polygons = [];
876✔
207

208
        for ($i = 0; $i < $numPolygons; $i++) {
876✔
209
            $polygon = $this->readGeometry($buffer, $cs->SRID());
582✔
210

211
            if (! $polygon instanceof Polygon) {
582✔
212
                throw new GeometryIOException('Expected Polygon, got ' . $polygon->geometryType());
×
213
            }
214

215
            $polygons[] = $polygon;
582✔
216
        }
217

218
        return new MultiPolygon($cs, ...$polygons);
876✔
219
    }
220

221
    private function readGeometryCollection(WKBBuffer $buffer, CoordinateSystem $cs) : GeometryCollection
222
    {
223
        $numGeometries = $buffer->readUnsignedLong();
580✔
224
        $geometries = [];
580✔
225

226
        for ($i = 0; $i < $numGeometries; $i++) {
580✔
227
            $geometries[] = $this->readGeometry($buffer, $cs->SRID());
284✔
228
        }
229

230
        return new GeometryCollection($cs, ...$geometries);
580✔
231
    }
232

233
    /**
234
     * @throws GeometryIOException
235
     */
236
    private function readPolyhedralSurface(WKBBuffer $buffer, CoordinateSystem $cs) : PolyhedralSurface
237
    {
238
        $numPatches = $buffer->readUnsignedLong();
581✔
239
        $patches = [];
581✔
240

241
        for ($i = 0; $i < $numPatches; $i++) {
581✔
242
            $patch = $this->readGeometry($buffer, $cs->SRID());
280✔
243

244
            if (! $patch instanceof Polygon) {
280✔
245
                throw new GeometryIOException('Expected Polygon, got ' . $patch->geometryType());
×
246
            }
247

248
            $patches[] = $patch;
280✔
249
        }
250

251
        return new PolyhedralSurface($cs, ...$patches);
581✔
252
    }
253

254
    /**
255
     * @throws GeometryIOException
256
     */
257
    private function readTIN(WKBBuffer $buffer, CoordinateSystem $cs) : TIN
258
    {
259
        $numPatches = $buffer->readUnsignedLong();
560✔
260
        $patches = [];
560✔
261

262
        for ($i = 0; $i < $numPatches; $i++) {
560✔
263
            $patch = $this->readGeometry($buffer, $cs->SRID());
280✔
264

265
            if (! $patch instanceof Triangle) {
280✔
266
                throw new GeometryIOException('Expected Triangle, got ' . $patch->geometryType());
×
267
            }
268

269
            $patches[] = $patch;
280✔
270
        }
271

272
        return new TIN($cs, ...$patches);
560✔
273
    }
274

275
    private function readTriangle(WKBBuffer $buffer, CoordinateSystem $cs) : Triangle
276
    {
277
        $numRings = $buffer->readUnsignedLong();
840✔
278

279
        $rings = [];
840✔
280

281
        for ($i = 0; $i < $numRings; $i++) {
840✔
282
            $rings[] = $this->readLineString($buffer, $cs);
560✔
283
        }
284

285
        return new Triangle($cs, ...$rings);
840✔
286
    }
287
}
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