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

brick / geo / 13753277563

09 Mar 2025 10:43PM UTC coverage: 49.787% (+2.5%) from 47.295%
13753277563

push

github

BenMorel
Prepare for release

1749 of 3513 relevant lines covered (49.79%)

975.53 hits per line

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

96.83
/src/IO/AbstractWKBWriter.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Brick\Geo\IO;
6

7
use Brick\Geo\Exception\GeometryIOException;
8
use Brick\Geo\CircularString;
9
use Brick\Geo\CompoundCurve;
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\Point;
16
use Brick\Geo\Polygon;
17
use Brick\Geo\PolyhedralSurface;
18

19
/**
20
 * Base class for WKBWriter and EWKBWriter.
21
 *
22
 * @internal
23
 */
24
abstract class AbstractWKBWriter
25
{
26
    private WKBByteOrder $byteOrder;
27

28
    private WKBByteOrder $machineByteOrder;
29

30
    /**
31
     * @throws GeometryIOException
32
     */
33
    public function __construct()
34
    {
35
        $this->byteOrder = $this->machineByteOrder = WKBTools::getMachineByteOrder();
4,767✔
36
    }
37

38
    public function setByteOrder(WKBByteOrder $byteOrder) : void
39
    {
40
        $this->byteOrder = $byteOrder;
4,704✔
41
    }
42

43
    /**
44
     * @param Geometry $geometry The geometry to export as WKB.
45
     *
46
     * @return string The WKB representation of the given geometry.
47
     *
48
     * @throws GeometryIOException If the given geometry cannot be exported as WKB.
49
     */
50
    public function write(Geometry $geometry) : string
51
    {
52
        return $this->doWrite($geometry, true);
6,535✔
53
    }
54

55
    /**
56
     * @param Geometry $geometry The geometry export as WKB write.
57
     * @param bool     $outer    False if the geometry is nested in another geometry, true otherwise.
58
     *
59
     * @return string The WKB representation of the given geometry.
60
     *
61
     * @throws GeometryIOException If the given geometry cannot be exported as WKT.
62
     */
63
    protected function doWrite(Geometry $geometry, bool $outer) : string
64
    {
65
        if ($geometry instanceof Point) {
6,535✔
66
            return $this->writePoint($geometry, $outer);
1,049✔
67
        }
68

69
        if ($geometry instanceof LineString) {
6,077✔
70
            return $this->writeCurve($geometry, $outer);
2,105✔
71
        }
72

73
        if ($geometry instanceof CircularString) {
5,049✔
74
            return $this->writeCurve($geometry, $outer);
743✔
75
        }
76

77
        if ($geometry instanceof Polygon) {
4,677✔
78
            return $this->writePolygon($geometry, $outer);
2,028✔
79
        }
80

81
        if ($geometry instanceof CompoundCurve) {
3,457✔
82
            return $this->writeComposedGeometry($geometry, $outer);
448✔
83
        }
84

85
        if ($geometry instanceof CurvePolygon) {
3,093✔
86
            return $this->writeComposedGeometry($geometry, $outer);
350✔
87
        }
88

89
        if ($geometry instanceof GeometryCollection) {
2,743✔
90
            return $this->writeComposedGeometry($geometry, $outer);
2,064✔
91
        }
92

93
        if ($geometry instanceof PolyhedralSurface) {
679✔
94
            return $this->writeComposedGeometry($geometry, $outer);
679✔
95
        }
96

97
        throw GeometryIOException::unsupportedGeometryType($geometry->geometryType());
×
98
    }
99

100
    private function packByteOrder() : string
101
    {
102
        return pack('C', $this->byteOrder->value);
6,535✔
103
    }
104

105
    protected function packUnsignedInteger(int $uint) : string
106
    {
107
        return pack(match ($this->byteOrder) {
6,535✔
108
            WKBByteOrder::BIG_ENDIAN => 'N',
6,535✔
109
            WKBByteOrder::LITTLE_ENDIAN => 'V'
6,535✔
110
        }, $uint);
6,535✔
111
    }
112

113
    private function packDouble(float $double) : string
114
    {
115
        $binary = pack('d', $double);
4,442✔
116

117
        if ($this->byteOrder !== $this->machineByteOrder) {
4,442✔
118
            return strrev($binary);
1,344✔
119
        }
120

121
        return $binary;
3,098✔
122
    }
123

124
    /**
125
     * @throws GeometryIOException
126
     */
127
    private function packPoint(Point $point) : string
128
    {
129
        if ($point->isEmpty()) {
4,498✔
130
            throw new GeometryIOException('Empty points have no WKB representation.');
56✔
131
        }
132

133
        /** @psalm-suppress PossiblyNullArgument */
134
        $binary = $this->packDouble($point->x()) . $this->packDouble($point->y());
4,442✔
135

136
        if (null !== $z = $point->z()) {
4,442✔
137
            $binary .= $this->packDouble($z);
1,485✔
138
        }
139
        if (null !== $m = $point->m()) {
4,442✔
140
            $binary .= $this->packDouble($m);
1,440✔
141
        }
142

143
        return $binary;
4,442✔
144
    }
145

146
    /**
147
     * @throws GeometryIOException
148
     */
149
    private function packCurve(Curve $curve) : string
150
    {
151
        if (! $curve instanceof LineString && ! $curve instanceof CircularString) {
4,099✔
152
            // CompoundCurve is not a list of Points, not sure if WKB supports it!
153
            // For now, let's just not support it ourselves.
154
            throw new GeometryIOException(sprintf('Writing a %s as WKB is not supported.', $curve->geometryType()));
×
155
        }
156

157
        $wkb = $this->packUnsignedInteger($curve->count());
4,099✔
158

159
        foreach ($curve as $point) {
4,099✔
160
            $wkb .= $this->packPoint($point);
3,756✔
161
        }
162

163
        return $wkb;
4,099✔
164
    }
165

166
    private function writePoint(Point $point, bool $outer) : string
167
    {
168
        $wkb = $this->packByteOrder();
1,049✔
169
        $wkb.= $this->packHeader($point, $outer);
1,049✔
170
        $wkb.= $this->packPoint($point);
1,049✔
171

172
        return $wkb;
993✔
173
    }
174

175
    private function writeCurve(Curve $curve, bool $outer) : string
176
    {
177
        $wkb = $this->packByteOrder();
2,484✔
178
        $wkb.= $this->packHeader($curve, $outer);
2,484✔
179
        $wkb.= $this->packCurve($curve);
2,484✔
180

181
        return $wkb;
2,484✔
182
    }
183

184
    private function writePolygon(Polygon $polygon, bool $outer) : string
185
    {
186
        $wkb = $this->packByteOrder();
2,028✔
187
        $wkb.= $this->packHeader($polygon, $outer);
2,028✔
188
        $wkb.= $this->packUnsignedInteger($polygon->count());
2,028✔
189

190
        foreach ($polygon as $ring) {
2,028✔
191
            $wkb .= $this->packCurve($ring);
1,692✔
192
        }
193

194
        return $wkb;
2,028✔
195
    }
196

197
    private function writeComposedGeometry(CompoundCurve|CurvePolygon|GeometryCollection|PolyhedralSurface $collection, bool $outer) : string
198
    {
199
        $wkb = $this->packByteOrder();
3,457✔
200
        $wkb.= $this->packHeader($collection, $outer);
3,457✔
201
        $wkb.= $this->packUnsignedInteger($collection->count());
3,457✔
202

203
        foreach ($collection as $geometry) {
3,457✔
204
            $wkb .= $this->doWrite($geometry, false);
2,099✔
205
        }
206

207
        return $wkb;
3,457✔
208
    }
209

210
    abstract protected function packHeader(Geometry $geometry, bool $outer) : string;
211
}
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