mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-06-27 03:29:16 +02:00
Move the DEM sources to the common folder now that we use them in map/data
This commit is contained in:
186
src/data/dem.cpp
186
src/data/dem.cpp
@ -1,186 +0,0 @@
|
||||
/*
|
||||
WARNING: This code uses internal Qt API - the QZipReader class for reading
|
||||
ZIP files - and things may break if Qt changes the API. For Qt5 this is not
|
||||
a problem as we can "see the future" now and there are no changes in all
|
||||
the supported Qt5 versions up to the last one (5.15). In Qt6 the class
|
||||
might change or even disappear in the future, but this is very unlikely
|
||||
as there were no changes for several years and The Qt Company's policy
|
||||
is: "do not invest any resources into any desktop related stuff unless
|
||||
absolutely necessary". There is an issue (QTBUG-3897) since the year 2009 to
|
||||
include the ZIP reader into the public API, which aptly illustrates the
|
||||
effort The Qt Company is willing to make about anything desktop related...
|
||||
*/
|
||||
|
||||
#include <QtEndian>
|
||||
#include <QtMath>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QRegularExpression>
|
||||
#include <QLocale>
|
||||
#include <private/qzipreader_p.h>
|
||||
#include "common/rectc.h"
|
||||
#include "dem.h"
|
||||
|
||||
#define SRTM3_SAMPLES 1201
|
||||
#define SRTM1_SAMPLES 3601
|
||||
#define SRTM05_SAMPLES 7201
|
||||
|
||||
#define SRTM_SIZE(samples) \
|
||||
((samples) * (samples) * 2)
|
||||
|
||||
static double interpolate(double dx, double dy, double p0, double p1, double p2,
|
||||
double p3)
|
||||
{
|
||||
return p0 * (1.0 - dx) * (1.0 - dy) + p1 * dx * (1.0 - dy)
|
||||
+ p2 * dy * (1.0 - dx) + p3 * dx * dy;
|
||||
}
|
||||
|
||||
static double value(int col, int row, int samples, const QByteArray *data)
|
||||
{
|
||||
int pos = ((samples - 1 - row) * samples + col) * 2;
|
||||
qint16 val = qFromBigEndian(*((const qint16*)(data->constData() + pos)));
|
||||
|
||||
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;
|
||||
|
||||
QString DEM::Tile::latStr() const
|
||||
{
|
||||
const char ns = (_lat >= 0) ? 'N' : 'S';
|
||||
return QString("%1%2").arg(ns).arg(qAbs(_lat), 2, 10, QChar('0'));
|
||||
}
|
||||
|
||||
QString DEM::Tile::lonStr() const
|
||||
{
|
||||
const char ew = (_lon >= 0) ? 'E' : 'W';
|
||||
return QString("%1%2").arg(ew).arg(qAbs(_lon), 3, 10, QChar('0'));
|
||||
}
|
||||
|
||||
QString DEM::Tile::baseName() const
|
||||
{
|
||||
return QString("%1%2.hgt").arg(latStr(), lonStr());
|
||||
}
|
||||
|
||||
QString DEM::_dir;
|
||||
DEM::TileCache DEM::_data;
|
||||
|
||||
void DEM::setCacheSize(int size)
|
||||
{
|
||||
_data.setMaxCost(size * 1024);
|
||||
}
|
||||
|
||||
void DEM::setDir(const QString &path)
|
||||
{
|
||||
_dir = path;
|
||||
}
|
||||
|
||||
void DEM::clearCache()
|
||||
{
|
||||
_data.clear();
|
||||
}
|
||||
|
||||
QByteArray *DEM::loadTile(const Tile &tile)
|
||||
{
|
||||
QString bn(tile.baseName());
|
||||
QString fn(QDir(_dir).absoluteFilePath(bn));
|
||||
QString zn(fn + ".zip");
|
||||
|
||||
if (QFileInfo::exists(zn)) {
|
||||
QZipReader zip(zn, QIODevice::ReadOnly);
|
||||
return new QByteArray(zip.fileData(bn));
|
||||
} else {
|
||||
QFile file(fn);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qWarning("%s: %s", qPrintable(file.fileName()),
|
||||
qPrintable(file.errorString()));
|
||||
return new QByteArray();
|
||||
} else
|
||||
return new QByteArray(file.readAll());
|
||||
}
|
||||
}
|
||||
|
||||
double DEM::elevation(const Coordinates &c)
|
||||
{
|
||||
if (_dir.isEmpty())
|
||||
return NAN;
|
||||
|
||||
Tile tile(qFloor(c.lon()), qFloor(c.lat()));
|
||||
QByteArray *ba = _data.object(tile);
|
||||
double ele;
|
||||
|
||||
if (!ba) {
|
||||
ba = loadTile(tile);
|
||||
ele = height(c, ba);
|
||||
_data.insert(tile, ba, ba->size());
|
||||
} else
|
||||
ele = height(c, ba);
|
||||
|
||||
return ele;
|
||||
}
|
||||
|
||||
QList<Area> DEM::tiles()
|
||||
{
|
||||
static const QRegularExpression re("([NS])([0-9]{2})([EW])([0-9]{3})");
|
||||
QDir dir(_dir);
|
||||
QFileInfoList files(dir.entryInfoList(QDir::Files | QDir::Readable));
|
||||
QLocale l(QLocale::system());
|
||||
QList<Area> list;
|
||||
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
QString basename(files.at(i).baseName());
|
||||
QRegularExpressionMatch match(re.match(basename));
|
||||
if (!match.hasMatch())
|
||||
continue;
|
||||
|
||||
int lat = match.captured(2).toInt();
|
||||
int lon = match.captured(4).toInt();
|
||||
if (match.captured(1) == "S")
|
||||
lat = -lat;
|
||||
if (match.captured(3) == "W")
|
||||
lon = -lon;
|
||||
|
||||
Area area(RectC(Coordinates(lon, lat + 1), Coordinates(lon + 1, lat)));
|
||||
area.setName(basename);
|
||||
area.setDescription(files.at(i).suffix().toUpper() + ", "
|
||||
+ l.formattedDataSize(files.at(i).size()));
|
||||
|
||||
list.append(area);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const DEM::Tile &tile)
|
||||
{
|
||||
dbg.nospace() << "Tile(" << tile.baseName() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
@ -1,65 +0,0 @@
|
||||
#ifndef DEM_H
|
||||
#define DEM_H
|
||||
|
||||
#include <QString>
|
||||
#include <QCache>
|
||||
#include <QByteArray>
|
||||
#include <QMutex>
|
||||
#include "common/hash.h"
|
||||
#include "area.h"
|
||||
|
||||
class Coordinates;
|
||||
|
||||
class DEM
|
||||
{
|
||||
public:
|
||||
class Tile {
|
||||
public:
|
||||
Tile(int lon, int lat) : _lon(lon), _lat(lat) {}
|
||||
|
||||
int lon() const {return _lon;}
|
||||
int lat() const {return _lat;}
|
||||
|
||||
QString lonStr() const;
|
||||
QString latStr() const;
|
||||
QString baseName() const;
|
||||
|
||||
bool operator==(const Tile &other) const
|
||||
{
|
||||
return (_lon == other._lon && _lat == other._lat);
|
||||
}
|
||||
|
||||
private:
|
||||
int _lon, _lat;
|
||||
};
|
||||
|
||||
static void setCacheSize(int size);
|
||||
static void setDir(const QString &path);
|
||||
static void clearCache();
|
||||
|
||||
static double elevation(const Coordinates &c);
|
||||
static void lock() {_lock.lock();}
|
||||
static void unlock() {_lock.unlock();}
|
||||
|
||||
static QList<Area> tiles();
|
||||
|
||||
private:
|
||||
typedef QCache<DEM::Tile, QByteArray> TileCache;
|
||||
|
||||
static QByteArray *loadTile(const Tile &tile);
|
||||
|
||||
static QString _dir;
|
||||
static TileCache _data;
|
||||
static QMutex _lock;
|
||||
};
|
||||
|
||||
inline HASH_T qHash(const DEM::Tile &tile)
|
||||
{
|
||||
return (qHash(tile.lon()) ^ qHash(tile.lat()));
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const DEM::Tile &tile);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // DEM_H
|
@ -4,7 +4,7 @@
|
||||
#include <QObject>
|
||||
#include <QDir>
|
||||
#include "common/downloader.h"
|
||||
#include "dem.h"
|
||||
#include "common/dem.h"
|
||||
|
||||
class RectC;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "dem.h"
|
||||
#include "common/dem.h"
|
||||
#include "route.h"
|
||||
|
||||
bool Route::_useDEM = false;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "dem.h"
|
||||
#include "common/dem.h"
|
||||
#include "track.h"
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include "dem.h"
|
||||
#include "common/dem.h"
|
||||
#include "waypoint.h"
|
||||
|
||||
bool Waypoint::_useDEM = false;
|
||||
|
Reference in New Issue
Block a user