@@ -32,106 +32,68 @@ const geometryTypeCompoundSurface = 24
3232 * @returns {Geometry } GeoJSON geometry object
3333 */
3434export 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