node-hgt
Version:
Query hgt files (typically SRTM elevation data) with performance.
128 lines (116 loc) • 4.36 kB
JavaScript
var fs = require('fs'),
os = require('os'),
path = require('path'),
extend = require('extend'),
Promise = require('promise'),
request = require('request'),
yauzl = require('yauzl'),
_latLng = require('./latlng');
function ImagicoElevationDownloader(cacheDir, options) {
this.options = extend({}, options);
this._cacheDir = cacheDir;
this._downloads = {};
}
ImagicoElevationDownloader.prototype.download = function(tileKey, latLng, cb) {
var cleanup = function() {
delete this._downloads[tileKey];
fs.unlinkSync(tempPath);
}.bind(this),
download = this._downloads[tileKey],
tempPath,
stream;
if (!download) {
download = this.search(latLng)
.then(function(tileZips) {
if (!tileZips.length) {
throw new Error('No tiles found for latitude ' + latLng.lat + ', longitude ' + latLng.lng);
}
tempPath = path.join(os.tmpdir(), tileZips[0].name);
stream = fs.createWriteStream(tempPath);
return this._download(tileZips[0].link, stream);
}.bind(this))
.then(function() {
return this._unzip(tempPath, this._cacheDir);
}.bind(this))
.then(cleanup)
.catch(function(err) {
cleanup();
throw err;
});
this._downloads[tileKey] = download;
}
download.then(function() {
cb(undefined);
}).catch(function(err) {
cb(err);
});
};
ImagicoElevationDownloader.prototype.search = function(latLng) {
var ll = _latLng(latLng);
return new Promise(function(fulfill, reject) {
request('http://www.imagico.de/map/dem_json.php?date=&lon=' +
ll.lng + '&lat=' + ll.lat + '&lonE=' + ll.lng +
'&latE=' + ll.lat + '&vf=1', function(err, response, body) {
if (!err && response.statusCode === 200) {
try {
var data = JSON.parse(body);
fulfill(data);
} catch (e) {
reject('Could not parse response from imagico: ' + body);
}
} else {
reject(err || response);
}
});
});
};
ImagicoElevationDownloader.prototype._download = function(url, stream) {
return new Promise(function(fulfill, reject) {
request(url, function(err, response) {
if (!err && response.statusCode === 200) {
fulfill(stream);
} else {
reject(err || response);
}
}).pipe(stream);
});
};
ImagicoElevationDownloader.prototype._unzip = function(zipPath, targetPath) {
return new Promise(function(fulfill, reject) {
var unzips = [];
yauzl.open(zipPath, function(err, zipfile) {
if (err) {
reject(err);
return;
}
zipfile
.on('entry', function(entry) {
if (/\/$/.test(entry.fileName)) {
return;
}
zipfile.openReadStream(entry, function(err, readStream) {
var lastSlashIdx = entry.fileName.lastIndexOf('/'),
fileName = entry.fileName.substr(lastSlashIdx + 1),
filePath = path.join(targetPath, fileName);
if (err) {
reject(err);
return;
}
unzips.push(new Promise(function(fulfill, reject) {
readStream.on('end', fulfill);
readStream.on('error', reject);
}));
readStream.pipe(fs.createWriteStream(filePath));
});
});
zipfile.on('end', function() {
Promise.all(unzips)
.then(function() {
fulfill();
})
.catch(reject);
});
});
});
};
module.exports = ImagicoElevationDownloader;