UNPKG

node-hgt

Version:

Query hgt files (typically SRTM elevation data) with performance.

98 lines (81 loc) 2.88 kB
var fs = require('fs'), extend = require('extend'), _latLng = require('./latlng'); function Hgt(path, swLatLng, options) { var fd = fs.openSync(path, 'r'), stat; try { stat = fs.fstatSync(fd); this.options = extend({}, { interpolation: Hgt.bilinear }, options); if (stat.size === 12967201 * 2) { this._resolution = 1; this._size = 3601; } else if (stat.size === 1442401 * 2) { this._resolution = 3; this._size = 1201; } else { throw new Error('Unknown tile format (1 arcsecond and 3 arcsecond supported).'); } this._buffer = fs.readFileSync(fd); this._swLatLng = _latLng(swLatLng); } finally { fs.closeSync(fd); } } Hgt.nearestNeighbour = function(row, col) { return this._rowCol(Math.round(row), Math.round(col)); }; Hgt.bilinear = function(row, col) { var avg = function(v1, v2, f) { return v1 + (v2 - v1) * f; }, rowLow = Math.floor(row), rowHi = rowLow + 1, rowFrac = row - rowLow, colLow = Math.floor(col), colHi = colLow + 1, colFrac = col - colLow, v00 = this._rowCol(rowLow, colLow), v10 = this._rowCol(rowLow, colHi), v11 = this._rowCol(rowHi, colHi), v01 = this._rowCol(rowHi, colLow), v1 = avg(v00, v10, colFrac), v2 = avg(v01, v11, colFrac); // console.log('row = ' + row); // console.log('col = ' + col); // console.log('rowLow = ' + rowLow); // console.log('rowHi = ' + rowHi); // console.log('rowFrac = ' + rowFrac); // console.log('colLow = ' + colLow); // console.log('colHi = ' + colHi); // console.log('colFrac = ' + colFrac); // console.log('v00 = ' + v00); // console.log('v10 = ' + v10); // console.log('v11 = ' + v11); // console.log('v01 = ' + v01); // console.log('v1 = ' + v1); // console.log('v2 = ' + v2); return avg(v1, v2, rowFrac); }; Hgt.prototype.destroy = function() { delete this._buffer; }; Hgt.prototype.getElevation = function(latLng) { var size = this._size - 1, ll = _latLng(latLng), row = (ll.lat - this._swLatLng.lat) * size, col = (ll.lng - this._swLatLng.lng) * size; if (row < 0 || col < 0 || row > size || col > size) { throw new Error('Latitude/longitude is outside tile bounds (row=' + row + ', col=' + col + '; size=' + size); } return this.options.interpolation.call(this, row, col); }; Hgt.prototype._rowCol = function(row, col) { var size = this._size, offset = ((size - row - 1) * size + col) * 2; return this._buffer.readInt16BE(offset); }; module.exports = Hgt;