Skip to content

Commit 95f1e02

Browse files
committed
Clean up wkb
1 parent 2eaa97f commit 95f1e02

File tree

1 file changed

+31
-64
lines changed

1 file changed

+31
-64
lines changed

src/wkb.js

Lines changed: 31 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -32,106 +32,68 @@ const geometryTypeCompoundSurface = 24
3232
* @returns {Geometry} GeoJSON geometry object
3333
*/
3434
export function decodeWKB(wkb) {
35+
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength)
3536
let offset = 0
3637

3738
// Byte order: 0 = big-endian, 1 = little-endian
3839
const byteOrder = wkb[offset]; offset += 1
3940
const isLittleEndian = byteOrder === 1
4041

41-
// Helper functions
42-
/**
43-
* Read a 32-bit unsigned integer from buffer at given offset
44-
* @param {Uint8Array} buf
45-
* @param {number} off
46-
*/
47-
function readUInt32(buf, off) {
48-
const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
49-
return dv.getUint32(off, isLittleEndian)
50-
}
51-
52-
/**
53-
* Read a 64-bit double from buffer at given offset
54-
* @param {Uint8Array} buf
55-
* @param {number} off
56-
*/
57-
function readDouble(buf, off) {
58-
const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
59-
return dv.getFloat64(off, isLittleEndian)
60-
}
61-
6242
// Read geometry type
63-
const geometryType = readUInt32(wkb, offset)
43+
const geometryType = dv.getUint32(offset, isLittleEndian)
6444
offset += 4
6545

6646
// WKB geometry types (OGC):
6747
if (geometryType === geometryTypePoint) {
6848
// Point
69-
const x = readDouble(wkb, offset); offset += 8
70-
const y = readDouble(wkb, offset); offset += 8
49+
const x = dv.getFloat64(offset, isLittleEndian); offset += 8
50+
const y = dv.getFloat64(offset, isLittleEndian); offset += 8
7151
return { type: 'Point', coordinates: [x, y] }
7252
} else if (geometryType === geometryTypeLineString) {
7353
// LineString
74-
const numPoints = readUInt32(wkb, offset); offset += 4
54+
const numPoints = dv.getUint32(offset, isLittleEndian); offset += 4
7555
const coords = []
7656
for (let i = 0; i < numPoints; i++) {
77-
const x = readDouble(wkb, offset); offset += 8
78-
const y = readDouble(wkb, offset); offset += 8
57+
const x = dv.getFloat64(offset, isLittleEndian); offset += 8
58+
const y = dv.getFloat64(offset, isLittleEndian); offset += 8
7959
coords.push([x, y])
8060
}
8161
return { type: 'LineString', coordinates: coords }
8262
} else if (geometryType === geometryTypePolygon) {
8363
// Polygon
84-
const numRings = readUInt32(wkb, offset); offset += 4
64+
const numRings = dv.getUint32(offset, isLittleEndian); offset += 4
8565
const coords = []
8666
for (let r = 0; r < numRings; r++) {
87-
const numPoints = readUInt32(wkb, offset); offset += 4
67+
const numPoints = dv.getUint32(offset, isLittleEndian); offset += 4
8868
const ring = []
8969
for (let p = 0; p < numPoints; p++) {
90-
const x = readDouble(wkb, offset); offset += 8
91-
const y = readDouble(wkb, offset); offset += 8
70+
const x = dv.getFloat64(offset, isLittleEndian); offset += 8
71+
const y = dv.getFloat64(offset, isLittleEndian); offset += 8
9272
ring.push([x, y])
9373
}
9474
coords.push(ring)
9575
}
9676
return { type: 'Polygon', coordinates: coords }
97-
9877
} else if (geometryType === geometryTypeMultiPolygon) {
9978
// MultiPolygon
100-
const numPolygons = readUInt32(wkb, offset); offset += 4
79+
const numPolygons = dv.getUint32(offset, isLittleEndian); offset += 4
10180
const polygons = []
10281
for (let i = 0; i < numPolygons; i++) {
10382
// Each polygon has its own byte order & geometry type
104-
const pgByteOrder = wkb[offset]; offset += 1
105-
const pgIsLittleEndian = pgByteOrder === 1
106-
const pgType = (function() {
107-
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength)
108-
const val = dv.getUint32(offset, pgIsLittleEndian)
109-
offset += 4
110-
return val
111-
})()
112-
113-
if (pgType !== 3) throw new Error(`Expected Polygon in MultiPolygon, got ${pgType}`)
114-
115-
const numRings = (function() {
116-
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength)
117-
const val = dv.getUint32(offset, pgIsLittleEndian)
118-
offset += 4
119-
return val
120-
})()
83+
const polyIsLittleEndian = wkb[offset] === 1; offset += 1
84+
const polyType = dv.getUint32(offset, polyIsLittleEndian); offset += 4
85+
if (polyType !== geometryTypePolygon) {
86+
throw new Error(`Expected Polygon in MultiPolygon, got ${polyType}`)
87+
}
88+
const numRings = dv.getUint32(offset, polyIsLittleEndian); offset += 4
12189

12290
const pgCoords = []
12391
for (let r = 0; r < numRings; r++) {
124-
const numPoints = (function() {
125-
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength)
126-
const val = dv.getUint32(offset, pgIsLittleEndian)
127-
offset += 4
128-
return val
129-
})()
92+
const numPoints = dv.getUint32(offset, polyIsLittleEndian); offset += 4
13093
const ring = []
13194
for (let p = 0; p < numPoints; p++) {
132-
const dv = new DataView(wkb.buffer, wkb.byteOffset, wkb.byteLength)
133-
const x = dv.getFloat64(offset, pgIsLittleEndian); offset += 8
134-
const y = dv.getFloat64(offset, pgIsLittleEndian); offset += 8
95+
const x = dv.getFloat64(offset, polyIsLittleEndian); offset += 8
96+
const y = dv.getFloat64(offset, polyIsLittleEndian); offset += 8
13597
ring.push([x, y])
13698
}
13799
pgCoords.push(ring)
@@ -144,15 +106,20 @@ export function decodeWKB(wkb) {
144106
throw new Error('Unsupported geometry type: MultiPoint')
145107
} else if (geometryType === geometryTypeMultiLineString) {
146108
// MultiLineString
147-
const numLineStrings = readUInt32(wkb, offset); offset += 4
109+
const numLineStrings = dv.getUint32(offset, isLittleEndian); offset += 4
148110
const lineStrings = []
149111
for (let i = 0; i < numLineStrings; i++) {
150-
offset += 5 // byte order and dimension?
151-
const numPoints = readUInt32(wkb, offset); offset += 4
112+
// Each line has its own byte order & geometry type
113+
const lineIsLittleEndian = wkb[offset] === 1; offset += 1
114+
const lineType = dv.getUint32(offset, lineIsLittleEndian); offset += 4
115+
if (lineType !== geometryTypeLineString) {
116+
throw new Error(`Expected LineString in MultiLineString, got ${lineType}`)
117+
}
118+
const numPoints = dv.getUint32(offset, isLittleEndian); offset += 4
152119
const coords = []
153120
for (let p = 0; p < numPoints; p++) {
154-
const x = readDouble(wkb, offset); offset += 8
155-
const y = readDouble(wkb, offset); offset += 8
121+
const x = dv.getFloat64(offset, lineIsLittleEndian); offset += 8
122+
const y = dv.getFloat64(offset, lineIsLittleEndian); offset += 8
156123
coords.push([x, y])
157124
}
158125
lineStrings.push(coords)

0 commit comments

Comments
 (0)