wkx icon indicating copy to clipboard operation
wkx copied to clipboard

Conversion for feature collections from TWKB to GeoJSON looks wrong

Open savv opened this issue 5 years ago • 1 comments

The following code sample includes a repro. I start with a TWKB string generated using PostGIS, then compare the outputs of two libraries, wkx and twkb.

twkb yields the expected result, with 5 vertices. wkx generates one polygon (instead of two), with 912 vertices (instead of 5).

var wkx = require('wkx');
var twkb = require('twkb');

/* NOTE: generated from the following query:
 * select encode(st_astwkb(
 *   ARRAY['POLYGON((25.9601817282581 48.0424439290235,25.9665092948186 48.0409189127411,25.9689305626008 48.0454493856918,25.9624693171852 48.046795992248,25.9601817282581 48.0424439290235))'::GEOMETRY, 'POLYGON((25.9601817282581 48.0424439290235,25.9665092948186 48.0409189127411,25.9689305626008 48.0454493856918,25.9624693171852 48.046795992248,25.9601817282581 48.0424439290235))'::GEOMETRY]::geometry[]
 *   , ARRAY[123, 456], 5
 *   ), 'base64');
 */
var base64 = 'pgQC9gGQBwEF5PK8Aqi6ygTyCa8C5AOKB4sKjgLJA+cGAQUAAPIJrwLkA4oHiwqOAskD5wY=';

var buf = Buffer.from(base64, 'base64');


console.log('====== twkb:');
var twkbRes = twkb.toGeoJSON(buf);
console.log('twkb num features:', twkbRes.features.length);
console.log('twkb feature ids:', twkbRes.features.map(x => x.id));
console.log('twkb coords per feature:', twkbRes.features.map(x => x.geometry.coordinates[0].length));
console.log(JSON.stringify(twkbRes, null, 2));

console.log('====== wkx:');
var wkxRes = wkx.Geometry.parseTwkb(buf);
console.log('wkx num features:', wkxRes.polygons.length);
console.log('wkx feature ids:', wkxRes.polygons.map(x => x.id));
console.log('wkx coords per feature (ext ring):', wkxRes.polygons.map(x => x.exteriorRing.length));
// console.log(JSON.stringify(wkxRes, null, 2));

savv avatar Mar 17 '20 09:03 savv

Also note, changing base64 to: pwQC9gGQB6MAAQXk8rwCqLrKBPIJrwLkA4oHiwqOAskD5wahAMCaDIC1GA== throws an exception:

internal/buffer.js:76
  throw new ERR_OUT_OF_RANGE(type || 'offset',
  ^

RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 42. Received 19995122
    at boundsError (internal/buffer.js:76:9)
    at Buffer.readUInt8 (internal/buffer.js:242:5)
    at BinaryReader.readUInt8 (/Users/savv/agro/common/node_modules/wkx/lib/binaryreader.js:16:28)
    at Function.Geometry.parseTwkb (/Users/savv/agro/common/node_modules/wkx/lib/geometry.js:153:29)
    at Function.GeometryCollection._parseTwkb (/Users/savv/agro/common/node_modules/wkx/lib/geometrycollection.js:87:53)
    at Function.Geometry.parseTwkb (/Users/savv/agro/common/node_modules/wkx/lib/geometry.js:212:39)
    at Object.<anonymous> (/Users/savv/agro/common/test.js:23:27)
    at Module._compile (internal/modules/cjs/loader.js:1158:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)
    at Module.load (internal/modules/cjs/loader.js:1002:32) {
  code: 'ERR_OUT_OF_RANGE'
}

That TWKB/base64 string was generated by:

select encode(st_astwkb(
    ARRAY['POLYGON((25.9601817282581 48.0424439290235,25.9665092948186 48.0409189127411,25.9689305626008 48.0454493856918,25.9624693171852 48.046795992248,25.9601817282581 48.0424439290235))'::GEOMETRY, 'POINT(1 2)'::GEOMETRY]::geometry[]
    , ARRAY[123, 456], 5
    ), 'base64');

savv avatar Mar 17 '20 10:03 savv