All files / application gdal_location_info.js

92.3% Statements 24/26
0% Branches 0/2
100% Functions 2/2
92.3% Lines 24/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95                                          3x 3x       3x 3x 3x         3x 3x   3x 3x   3x 3x   3x             3x     3x 3x   3x     3x         3x     3x       3x     3x       3x         3x           3x            
/* eslint-disable camelcase */
/* eslint-disable no-underscore-dangle */
import { GDALFunctions } from '../../allCFunctions';
 
/**
 * The gdal location info utility converts a latitude and longitude into a pixel and line in the dataset
 *
 * {@link https://gdal.org/programs/gdallocationinfo.html}
 *
 * @module a/gdal_location_info
 * @async
 * @param {TypeDefs.Dataset} dataset Dataset to be converted.
 * @param {Array<Array<number>>} coords Coordinates to be converted.
 * Example: [45.5,-108.5] lat/lon -wgs84 ie. this always acts as if -wgs84 was passed to gdalLocationinfo
 * @return {Promise<Array<Array<number>>>} "Promise" returns converted coordinates.
 * @example
 * const coords = [45.5,-108.5];
 * const pixelCoords = await Gdal.gdal_location_info(dataset,coords);
 * console.log(pixelCoords); // { "pixel": 3256, "line": 8664 }
 */
export default function gdal_location_info(dataset, coords) {
    return new Promise((resolve, reject) => {
        const hSrcSRS = GDALFunctions.OSRNewSpatialReference(
            'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]', // WKT for wgs84
        );
 
        GDALFunctions.OSRSetAxisMappingStrategy(hSrcSRS, 0); // TRADITIONAL_GIS_ORDER
        const hTrgSRS = GDALFunctions.GDALGetSpatialRef(dataset.pointer);
        const hct = GDALFunctions.OCTNewCoordinateTransformation(
            hSrcSRS,
            hTrgSRS,
        );
 
        const doubleLat = GDALFunctions.CPLAtof(String(coords[0]));
        const doubleLon = GDALFunctions.CPLAtof(String(coords[1]));
 
        const latPointer = GDALFunctions.Module._malloc(8); // double
        GDALFunctions.Module.setValue(latPointer, doubleLat, 'double');
 
        const lonPointer = GDALFunctions.Module._malloc(8); // double
        GDALFunctions.Module.setValue(lonPointer, doubleLon, 'double');
 
        const success = GDALFunctions.OCTTransform(
            hct,
            1,
            lonPointer,
            latPointer,
            null,
        );
        Iif (!success) {
            reject(new Error('Failed to perform OCTTransform'));
        }
        const dfGeoX = GDALFunctions.Module.getValue(lonPointer, 'double');
        const dfGeoY = GDALFunctions.Module.getValue(latPointer, 'double');
 
        const geoTransformByteOffset = GDALFunctions.Module._malloc(
            6 * Float64Array.BYTES_PER_ELEMENT,
        );
        GDALFunctions.GDALGetGeoTransform(
            dataset.pointer,
            geoTransformByteOffset,
        );
 
        const inverseGeoTransformByteOffset = GDALFunctions.Module._malloc(
            6 * Float64Array.BYTES_PER_ELEMENT,
        );
        const successfulInverseTransform = GDALFunctions.GDALInvGeoTransform(
            geoTransformByteOffset,
            inverseGeoTransformByteOffset,
        );
        Iif (!successfulInverseTransform) {
            reject(new Error('Failed to invert transform'));
        }
        const inverseGeoTransform = GDALFunctions.Module.HEAPF64.subarray(
            inverseGeoTransformByteOffset / Float64Array.BYTES_PER_ELEMENT,
            (inverseGeoTransformByteOffset / Float64Array.BYTES_PER_ELEMENT) + 6,
        );
        const iPixel = Math.floor(
            inverseGeoTransform[0]
                + (inverseGeoTransform[1] * dfGeoX)
                + (inverseGeoTransform[2] * dfGeoY),
        );
        const iLine = Math.floor(
            inverseGeoTransform[3]
                + (inverseGeoTransform[4] * dfGeoX)
                + (inverseGeoTransform[5] * dfGeoY),
        );
 
        resolve({
            pixel: iPixel,
            line: iLine,
        });
    });
}