From 0c97ad38d330e22efae796c38207e4df35b1ef35 Mon Sep 17 00:00:00 2001 From: Peter Johnson <738069+missinglink@users.noreply.github.com> Date: Tue, 11 Nov 2025 17:39:15 +0100 Subject: [PATCH] feat(geometry): convert 3d and 4d geometries to 2d --- import/format.js | 21 +++++++++- .../source/whosonfirst/map/geometries.test.js | 41 +++++++++++++++++++ package.json | 2 +- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/import/format.js b/import/format.js index 0bf906e..e532898 100644 --- a/import/format.js +++ b/import/format.js @@ -48,7 +48,26 @@ function from (type, format, geom) { throw new Error(`invalid format: ${format}`) } - return func(geom) + return castToXY(func(geom)) +} + +function to2D (coords) { + if (typeof coords[0] === 'number') { + return coords.slice(0, 2) + } + return coords.map(to2D) +} + +// Convert a geometry to 2D by stripping Z and M values +function castToXY (geom) { + if (!geom.hasZ && !geom.hasM) { + return geom + } + const gj = geom.toGeoJSON() + return wkx.Geometry.parseGeoJSON({ + type: gj.type, + coordinates: to2D(gj.coordinates) + }) } function to (geom, format) { diff --git a/import/source/whosonfirst/map/geometries.test.js b/import/source/whosonfirst/map/geometries.test.js index c1e192f..3b684ad 100644 --- a/import/source/whosonfirst/map/geometries.test.js +++ b/import/source/whosonfirst/map/geometries.test.js @@ -139,3 +139,44 @@ tap.test('mapper: mapshaper position', (t) => { t.equal(p.geometry[1].role, 'mapshaper_position') t.end() }) +tap.test('mapper: converts 3D geometries to 2D', (t) => { + let p = new Place() + map(p, { + geometry: { + 'type': 'Polygon', + 'coordinates': [ + [ + [ + 39.0234375, + 48.922499263758255, + 10 + ], + [ + 47.8125, + 39.639537564366684, + 20 + ], + [ + 61.17187499999999, + 49.83798245308484, + 30 + ], + [ + 39.0234375, + 48.922499263758255, + 40 + ] + ] + ] + } + }) + t.equal(p.geometry.length, 1) + t.ok(p.geometry[0] instanceof Geometry) + t.equal(p.geometry[0].geometry.constructor.name.toUpperCase(), 'POLYGON') + t.equal(p.geometry[0].role, 'boundary') + t.equal(p.geometry[0].geometry.hasZ, false) + t.equal(p.geometry[0].geometry.hasM, false) + t.same(p.geometry[0].geometry.toGeoJSON().coordinates[0][0], [39.0234375, 48.922499263758255]) + t.equal(p.geometry[0].geometry.toGeoJSON().coordinates[0].every(c => c.length === 2), true) + t.end() +}) diff --git a/package.json b/package.json index 92c05fe..f8ab782 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "split2": "^3.1.1", "through2": "^3.0.1", "turf-point": "^2.0.1", - "wkx": "^0.4.8", + "wkx": "^0.5.0", "yargs": "^13.3.0" }, "devDependencies": {