From 89c00ca5e9315a83a6aa3d004e6ce263d611bbfc Mon Sep 17 00:00:00 2001 From: DanielJDufour Date: Fri, 5 May 2023 17:39:36 -0400 Subject: [PATCH] improved getBoundingBox support for skewed/rotated images --- src/geotiffimage.js | 54 ++++++++++++++++++++++++++++++++--------- test/data/setup_data.sh | 2 +- test/geotiff.spec.js | 7 ++++++ 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/geotiffimage.js b/src/geotiffimage.js index 233afc3d..21994643 100644 --- a/src/geotiffimage.js +++ b/src/geotiffimage.js @@ -889,21 +889,51 @@ class GeoTIFFImage { * @returns {Array} The bounding box */ getBoundingBox() { - const origin = this.getOrigin(); - const resolution = this.getResolution(); + const height = this.getHeight(); + const width = this.getWidth(); + + if (this.fileDirectory.ModelTransformation) { + // eslint-disable-next-line no-unused-vars + const [a, b, c, d, e, f, g, h] = this.fileDirectory.ModelTransformation; + + const corners = [ + [0, 0], + [0, height], + [width, 0], + [width, height], + ]; + + const projected = corners.map(([I, J]) => [ + d + (a * I) + (b * J), + h + (e * I) + (f * J), + ]); + + const xs = projected.map((pt) => pt[0]); + const ys = projected.map((pt) => pt[1]); + + return [ + Math.min(...xs), + Math.min(...ys), + Math.max(...xs), + Math.max(...ys), + ]; + } else { + const origin = this.getOrigin(); + const resolution = this.getResolution(); - const x1 = origin[0]; - const y1 = origin[1]; + const x1 = origin[0]; + const y1 = origin[1]; - const x2 = x1 + (resolution[0] * this.getWidth()); - const y2 = y1 + (resolution[1] * this.getHeight()); + const x2 = x1 + (resolution[0] * this.getWidth()); + const y2 = y1 + (resolution[1] * this.getHeight()); - return [ - Math.min(x1, x2), - Math.min(y1, y2), - Math.max(x1, x2), - Math.max(y1, y2), - ]; + return [ + Math.min(x1, x2), + Math.min(y1, y2), + Math.max(x1, x2), + Math.max(y1, y2), + ]; + } } } diff --git a/test/data/setup_data.sh b/test/data/setup_data.sh index 0be375a0..22ddcb32 100755 --- a/test/data/setup_data.sh +++ b/test/data/setup_data.sh @@ -81,7 +81,7 @@ gdal_translate -of GTiff -co NBITS=16 -ot Float32 -co TILED=YES initial.tiff flo gdal_translate -of GTiff -co NBITS=16 -ot Float32 -co INTERLEAVE=BAND initial.tiff float_n_bit_interleave_16.tiff || true # GDAL_METADATA support -wget https://github.com/GeoTIFF/test-data/archive/8ac198032d8b02160049ca161e8108e3d38176f3.zip -O geotiff-test-data.zip +wget https://github.com/GeoTIFF/test-data/archive/6ec42abc044a6884037c148d67a87a5d28228ce5.zip -O geotiff-test-data.zip unzip -j -o geotiff-test-data.zip "test-data-*/files/*" -d . rm geotiff-test-data.zip diff --git a/test/geotiff.spec.js b/test/geotiff.spec.js index 4cd30d10..641bf2b1 100644 --- a/test/geotiff.spec.js +++ b/test/geotiff.spec.js @@ -538,6 +538,13 @@ describe('Geo metadata tests', async () => { expect(image.getGeoKeys()).to.have.property('GeographicTypeGeoKey'); expect(image.getGeoKeys().GeographicTypeGeoKey).to.equal(4326); }); + + it('should be able to get the bounding box of skewed images', async () => { + const tiff = await GeoTIFF.fromSource(createSource('umbra_mount_yasur.tiff')); + const image = await tiff.getImage(); + expect(image.getBoundingBox()).to.be.an('array'); + expect(image.getBoundingBox()).to.be.deep.equal([336494.9320674397, 7839364.913043569, 337934.4836350695, 7840804.464611199]); + }); }); describe('GDAL_METADATA tests', async () => {