mmomtchev / node-gdal-async

Node.js bindings for GDAL (Geospatial Data Abstraction Library) with full async support
https://mmomtchev.github.io/node-gdal-async/
Apache License 2.0
129 stars 26 forks source link

gdal transform #71

Closed juneidy closed 1 year ago

juneidy commented 1 year ago

Hi there, I am seeing a weird result from transforming coordinates between 3857 and 4326. I am not sure if it's even related to node-gdal, but asking here anyway to see if you can tell me where I've done wrong.

My following code:

const gdal = require('gdal-async');

const bb = new gdal.Envelope({
        minX: -1000000,
        minY: 0,
        maxX: 0,
        maxY: 1000000
})
.toPolygon();

bb.transform(
        new gdal.CoordinateTransformation(
                gdal.SpatialReference.fromEPSG(3857),
                gdal.SpatialReference.fromEPSG(4326)
        )
);

console.log(bb.getEnvelope());

produces output:

Envelope {
  minX: 0,
  minY: -8.983152841195214,
  maxX: 8.946573850543423,
  maxY: 0
}

I am actually expecting:

Envelope {
  minX: -8.983152841195214,
  minY: 0,
  maxX: 0,
  maxY: 8.946573850543423
}

Edit: Gdal version: 3.2.2 OS version: Debian Bullseye 11.6 Node version: 18.14.2 Gdal-async version: 3.6.2

juneidy commented 1 year ago

Another curious behaviour:

const gdal = require('gdal-async');

const bb = new gdal.Envelope({
          minX: -180,
          minY: -85,
          maxX: 180,
          maxY: 85
})
.toPolygon();

bb.transform(
        new gdal.CoordinateTransformation(
                gdal.SpatialReference.fromEPSG(4326),
                gdal.SpatialReference.fromEPSG(3857)
        )
);

console.log(bb.getEnvelope());

Gives an error:

bb.transform(
   ^

Error
    at Object.<anonymous> (/tmp/etl/test-gdal.js:11:4)
    at Module._compile (node:internal/modules/cjs/loader:1254:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
    at Module.load (node:internal/modules/cjs/loader:1117:32)
    at Module._load (node:internal/modules/cjs/loader:958:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47

Node.js v18.14.2

whereas if I swap the x and y, it works:

const gdal = require('gdal-async');

const bb = new gdal.Envelope({
          minX: -85,
          minY: -180,
          maxX: 85,
          maxY: 180
})
.toPolygon();

bb.transform(
        new gdal.CoordinateTransformation(
                gdal.SpatialReference.fromEPSG(4326),
                gdal.SpatialReference.fromEPSG(3857)
        )
);

console.log(bb.getEnvelope());
Envelope {
  minX: -20037508.342789244,
  minY: -19971868.88040857,
  maxX: 20037508.342789244,
  maxY: 19971868.880408563
}
mmomtchev commented 1 year ago

This is GDAL behavior and it is absolutely correct, 3857 defines the coordinates as easting/northing while 4326 has latitude/longitude. GDAL and PROJ are smart enough to swap the coordinates.

https://epsg.io/3857 https://epsg.io/4326