mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-28 05:34:47 +01:00
Allow arbitrary HGT grid sizes
This commit is contained in:
parent
2026036015
commit
c33215565f
@ -20,12 +20,16 @@
|
|||||||
#include "rectc.h"
|
#include "rectc.h"
|
||||||
#include "dem.h"
|
#include "dem.h"
|
||||||
|
|
||||||
#define SRTM3_SAMPLES 1201
|
|
||||||
#define SRTM1_SAMPLES 3601
|
|
||||||
#define SRTM05_SAMPLES 7201
|
|
||||||
|
|
||||||
#define SRTM_SIZE(samples) \
|
static unsigned int isqrt(unsigned int x)
|
||||||
((samples) * (samples) * 2)
|
{
|
||||||
|
unsigned int r = 0;
|
||||||
|
|
||||||
|
while ((r + 1) * (r + 1) <= x)
|
||||||
|
r++;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static double interpolate(double dx, double dy, double p0, double p1, double p2,
|
static double interpolate(double dx, double dy, double p0, double p1, double p2,
|
||||||
double p3)
|
double p3)
|
||||||
@ -34,42 +38,21 @@ static double interpolate(double dx, double dy, double p0, double p1, double p2,
|
|||||||
+ p2 * dy * (1.0 - dx) + p3 * dx * dy;
|
+ p2 * dy * (1.0 - dx) + p3 * dx * dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double value(int col, int row, int samples, const QByteArray *data)
|
static double value(int col, int row, int samples, const QByteArray &data)
|
||||||
{
|
{
|
||||||
int pos = ((samples - 1 - row) * samples + col) * 2;
|
int pos = ((samples - 1 - row) * samples + col) * 2;
|
||||||
qint16 val = qFromBigEndian(*((const qint16*)(data->constData() + pos)));
|
qint16 val = qFromBigEndian(*((const qint16*)(data.constData() + pos)));
|
||||||
|
|
||||||
return (val == -32768) ? NAN : val;
|
return (val == -32768) ? NAN : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double height(const Coordinates &c, const QByteArray *data)
|
|
||||||
{
|
|
||||||
int samples;
|
|
||||||
|
|
||||||
if (data->size() == SRTM_SIZE(SRTM3_SAMPLES))
|
|
||||||
samples = SRTM3_SAMPLES;
|
|
||||||
else if (data->size() == SRTM_SIZE(SRTM1_SAMPLES))
|
|
||||||
samples = SRTM1_SAMPLES;
|
|
||||||
else if (data->size() == SRTM_SIZE(SRTM05_SAMPLES))
|
|
||||||
samples = SRTM05_SAMPLES;
|
|
||||||
else
|
|
||||||
return NAN;
|
|
||||||
|
|
||||||
double lat = (c.lat() - floor(c.lat())) * (samples - 1);
|
|
||||||
double lon = (c.lon() - floor(c.lon())) * (samples - 1);
|
|
||||||
int row = (int)lat;
|
|
||||||
int col = (int)lon;
|
|
||||||
|
|
||||||
double p0 = value(col, row, samples, data);
|
|
||||||
double p1 = value(col + 1, row, samples, data);
|
|
||||||
double p2 = value(col, row + 1, samples, data);
|
|
||||||
double p3 = value(col + 1, row + 1, samples, data);
|
|
||||||
|
|
||||||
return interpolate(lon - col, lat - row, p0, p1, p2, p3);
|
|
||||||
}
|
|
||||||
|
|
||||||
QMutex DEM::_lock;
|
QMutex DEM::_lock;
|
||||||
|
|
||||||
|
DEM::Entry::Entry(const QByteArray &data) : _data(data)
|
||||||
|
{
|
||||||
|
_samples = isqrt(_data.size() / 2);
|
||||||
|
}
|
||||||
|
|
||||||
QString DEM::Tile::latStr() const
|
QString DEM::Tile::latStr() const
|
||||||
{
|
{
|
||||||
const char ns = (_lat >= 0) ? 'N' : 'S';
|
const char ns = (_lat >= 0) ? 'N' : 'S';
|
||||||
@ -105,7 +88,25 @@ void DEM::clearCache()
|
|||||||
_data.clear();
|
_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray *DEM::loadTile(const Tile &tile)
|
double DEM::height(const Coordinates &c, const Entry *e)
|
||||||
|
{
|
||||||
|
if (!e->samples())
|
||||||
|
return NAN;
|
||||||
|
|
||||||
|
double lat = (c.lat() - floor(c.lat())) * (e->samples() - 1);
|
||||||
|
double lon = (c.lon() - floor(c.lon())) * (e->samples() - 1);
|
||||||
|
int row = (int)lat;
|
||||||
|
int col = (int)lon;
|
||||||
|
|
||||||
|
double p0 = value(col, row, e->samples(), e->data());
|
||||||
|
double p1 = value(col + 1, row, e->samples(), e->data());
|
||||||
|
double p2 = value(col, row + 1, e->samples(), e->data());
|
||||||
|
double p3 = value(col + 1, row + 1, e->samples(), e->data());
|
||||||
|
|
||||||
|
return interpolate(lon - col, lat - row, p0, p1, p2, p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEM::Entry *DEM::loadTile(const Tile &tile)
|
||||||
{
|
{
|
||||||
QString bn(tile.baseName());
|
QString bn(tile.baseName());
|
||||||
QString fn(QDir(_dir).absoluteFilePath(bn));
|
QString fn(QDir(_dir).absoluteFilePath(bn));
|
||||||
@ -113,15 +114,15 @@ QByteArray *DEM::loadTile(const Tile &tile)
|
|||||||
|
|
||||||
if (QFileInfo::exists(zn)) {
|
if (QFileInfo::exists(zn)) {
|
||||||
QZipReader zip(zn, QIODevice::ReadOnly);
|
QZipReader zip(zn, QIODevice::ReadOnly);
|
||||||
return new QByteArray(zip.fileData(bn));
|
return new Entry(zip.fileData(bn));
|
||||||
} else {
|
} else {
|
||||||
QFile file(fn);
|
QFile file(fn);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
qWarning("%s: %s", qPrintable(file.fileName()),
|
qWarning("%s: %s", qPrintable(file.fileName()),
|
||||||
qPrintable(file.errorString()));
|
qPrintable(file.errorString()));
|
||||||
return new QByteArray();
|
return new Entry();
|
||||||
} else
|
} else
|
||||||
return new QByteArray(file.readAll());
|
return new Entry(file.readAll());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,15 +132,15 @@ double DEM::elevation(const Coordinates &c)
|
|||||||
return NAN;
|
return NAN;
|
||||||
|
|
||||||
Tile tile(floor(c.lon()), floor(c.lat()));
|
Tile tile(floor(c.lon()), floor(c.lat()));
|
||||||
QByteArray *ba = _data.object(tile);
|
Entry *e = _data.object(tile);
|
||||||
double ele;
|
double ele;
|
||||||
|
|
||||||
if (!ba) {
|
if (!e) {
|
||||||
ba = loadTile(tile);
|
e = loadTile(tile);
|
||||||
ele = height(c, ba);
|
ele = height(c, e);
|
||||||
_data.insert(tile, ba, ba->size());
|
_data.insert(tile, e, e->data().size());
|
||||||
} else
|
} else
|
||||||
ele = height(c, ba);
|
ele = height(c, e);
|
||||||
|
|
||||||
return ele;
|
return ele;
|
||||||
}
|
}
|
||||||
|
@ -44,9 +44,23 @@ public:
|
|||||||
static QList<Area> tiles();
|
static QList<Area> tiles();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef QCache<DEM::Tile, QByteArray> TileCache;
|
class Entry {
|
||||||
|
public:
|
||||||
|
Entry() : _samples(0) {}
|
||||||
|
Entry(const QByteArray &data);
|
||||||
|
|
||||||
static QByteArray *loadTile(const Tile &tile);
|
const QByteArray &data() const {return _data;}
|
||||||
|
int samples() const {return _samples;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int _samples;
|
||||||
|
QByteArray _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QCache<DEM::Tile, Entry> TileCache;
|
||||||
|
|
||||||
|
static double height(const Coordinates &c, const Entry *e);
|
||||||
|
static Entry *loadTile(const Tile &tile);
|
||||||
|
|
||||||
static QString _dir;
|
static QString _dir;
|
||||||
static TileCache _data;
|
static TileCache _data;
|
||||||
|
Loading…
Reference in New Issue
Block a user