geotiffjs / geotiff.js

geotiff.js is a small library to parse TIFF files for visualization or analysis. It is written in pure JavaScript, and is usable in both the browser and node.js applications.
https://geotiffjs.github.io/
MIT License
866 stars 182 forks source link

get elevation from geotiffs without `ModelPixelScale` or `ModelTiepoint`, but with `ModelTransformation` #393

Closed informatter closed 1 year ago

informatter commented 1 year ago

Hi guys

I think this is more of a question than a issue, but lets see...

I currently have a GeoTiff file am attempting to get the corresponding height from given a lat,lng coordinate. I am currently dealing with a file which does not have the ModelTiepoint tag, the optional ModelPixelScale tag, but it does have the ModelTransformation tag.

However when :

const { ModelPixelScale: s, ModelTiepoint: t } = dtmGeoTiff.fileDirectory; is called s and t will be undefined, as its expected. Is there a way to use the ModelTransformation in order to sucessfully continue with the rest of the below logic?

    let [sx, sy, sz] = s;
    let [px, py, k, gx, gy, gz] = t;

    const gpsToPixel = [-gx / sx, 1 / sx, 0, -gy / sy, 0, 1 / sy];
    const pixelToGPS = [gx, sx, 0, gy, 0, sy];
    sy = -sy;
    const cartographicPt= samplingGrid[0]
    const [x, y] = this._transform(cartographicPt.longitude, cartographicPt.latitude, gpsToPixel, true);
    console.log(`Corresponding tile pixel coordinate: [${x}][${y}]`);

    // Finally, retrieve the elevation associated with this pixel's geographic area:
    const rasters = await this.dtmGeoTiff.readRasters();
    const { width, [0]: raster } = rasters;
    const elevation = raster[x + y * width];
    console.log(`The elevation at (${cartographicPt.latitude.toFixed(6)},${cartographicPt.longitude.toFixed(6)}) is ${elevation}m`);

Would this be a valid approach?

    const origin = this.dtmGeoTiff.getOrigin();
    const resolution = this.dtmGeoTiff.getResolution();

    //const { ModelPixelScale: s, ModelTiepoint: t } = this.dtmGeoTiff.fileDirectory;

    let [sx, sy, sz] = resolution;
    let [px, py, k, gx, gy, gz] = [0,0,0,...origin]

    const gpsToPixel = [-gx / sx, 1 / sx, 0, -gy / sy, 0, 1 / sy];
    const pixelToGPS = [gx, sx, 0, gy, 0, sy];

Any pointers will be greatly appreciated.

Thank you,

Nicholas

constantinius commented 1 year ago

Yes, I believe it is possible. The gpsToPixel and pixelToGPS matrices use the origin and resolution of the image. To simply get the origin/resolution you can use image.getOrigin() and image.getResolution() respectively, which will work with both ModelTransformation as well as ModelTiePoint/ModelPixelScale.

I hope that helps!

informatter commented 1 year ago

@constantinius

Thank you for your quick reply. I can see what you are referring to in https://github.com/geotiffjs/geotiff.js/commit/5ab27ad7c4c2a0785e26c454b50ee567adccd845

So yes, my above approach


    const origin = this.dtmGeoTiff.getOrigin();
    const resolution = this.dtmGeoTiff.getResolution();

    let [sx, sy, sz] = resolution;
    let [px, py, k, gx, gy, gz] = [0,0,0,...origin]

    const gpsToPixel = [-gx / sx, 1 / sx, 0, -gy / sy, 0, 1 / sy];
    const pixelToGPS = [gx, sx, 0, gy, 0, sy];

Does seem to be correct, according to the linked PR. In addition in the section "GeoTIFF Tags for Coordinate Transformations" in http://geotiff.maptools.org/spec/geotiff2.6.html#2.6 , specifies that the I,J value is the point at location (I,J) in raster space, which i believe I can set to 0,0 and K its pixel value which according to the docs can be set to 0.

So let [px, py, k, gx, gy, gz] = [0,0,0,...origin] makes sense.

I hope I am correct?

Thank you

Nicholas

informatter commented 1 year ago

Just verified, and in terms of the pixel location, its at the expected x,y in the image 👍