Unverified Commit 05db03a5 authored by Gus Grubba's avatar Gus Grubba Committed by GitHub

Merge pull request #7818 from Aeronavics/MapProviders

Terrain Provider step 1 : Generic MapProviders
parents 0d1bb484 bab4a3d2
......@@ -681,7 +681,7 @@ Item {
visible: !QGroundControl.airspaceManager.flightPlan.loadingFlightList && _flightList.count > 0 && tableView.currentRow >= 0
function updateActiveMapType() {
var settings = QGroundControl.settingsManager.flightMapSettings
var fullMapName = settings.mapProvider.enumStringValue + " " + settings.mapType.enumStringValue
var fullMapName = settings.mapProvider.value + " " + settings.mapType.value
for (var i = 0; i < map.supportedMapTypes.length; i++) {
if (fullMapName === map.supportedMapTypes[i].name) {
map.activeMapType = map.supportedMapTypes[i]
......
......@@ -95,7 +95,8 @@ Map {
function updateActiveMapType() {
var settings = QGroundControl.settingsManager.flightMapSettings
var fullMapName = settings.mapProvider.enumStringValue + " " + settings.mapType.enumStringValue
var fullMapName = settings.mapProvider.value + " " + settings.mapType.value
for (var i = 0; i < _map.supportedMapTypes.length; i++) {
if (fullMapName === _map.supportedMapTypes[i].name) {
_map.activeMapType = _map.supportedMapTypes[i]
......
#include "BingMapProvider.h"
#if defined(DEBUG_GOOGLE_MAPS)
#include <QFile>
#include <QStandardPaths>
#endif
#include "QGCMapEngine.h"
BingMapProvider::BingMapProvider(QString imageFormat, quint32 averageSize,
QGeoMapType::MapStyle mapType, QObject* parent)
: MapProvider(QString("https://www.bing.com/maps/"), imageFormat,
averageSize, mapType, parent) {}
BingMapProvider::~BingMapProvider() {}
QString BingRoadMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
QString key = _tileXYToQuadKey(x, y, zoom);
return QString("http://ecn.t%1.tiles.virtualearth.net/tiles/"
"r%2.png?g=%3&mkt=%4")
.arg(_getServerNum(x, y, 4))
.arg(key)
.arg(_versionBingMaps)
.arg(_language);
}
QString
BingSatelliteMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
QString key = _tileXYToQuadKey(x, y, zoom);
return QString("http://ecn.t%1.tiles.virtualearth.net/tiles/"
"a%2.jpeg?g=%3&mkt=%4")
.arg(_getServerNum(x, y, 4))
.arg(key)
.arg(_versionBingMaps)
.arg(_language);
}
QString BingHybridMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
QString key = _tileXYToQuadKey(x, y, zoom);
return QString("http://ecn.t%1.tiles.virtualearth.net/tiles/"
"h%2.jpeg?g=%3&mkt=%4")
.arg(_getServerNum(x, y, 4))
.arg(key)
.arg(_versionBingMaps)
.arg(_language);
}
#pragma once
#include "MapProvider.h"
#include <QByteArray>
#include <QMutex>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QPoint>
#include <QString>
class BingMapProvider : public MapProvider {
Q_OBJECT
public:
BingMapProvider(QString imageFormat, quint32 averageSize,
QGeoMapType::MapStyle mapType, QObject* parent);
~BingMapProvider();
protected:
// Define the url to Request
virtual QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) = 0;
const QString _versionBingMaps = "563";
};
const quint32 AVERAGE_BING_STREET_MAP = 1297;
const quint32 AVERAGE_BING_SAT_MAP = 19597;
// -----------------------------------------------------------
// Bing Road Map
class BingRoadMapProvider : public BingMapProvider {
Q_OBJECT
public:
BingRoadMapProvider(QObject* parent)
: BingMapProvider(QString("png"), AVERAGE_BING_STREET_MAP, QGeoMapType::StreetMap,
parent) {}
protected:
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
// -----------------------------------------------------------
// Bing Satellite Map
class BingSatelliteMapProvider : public BingMapProvider {
Q_OBJECT
public:
BingSatelliteMapProvider(QObject* parent)
: BingMapProvider(QString("jpg"), AVERAGE_BING_SAT_MAP, QGeoMapType::SatelliteMapDay,
parent) {}
protected:
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
// -----------------------------------------------------------
// Bing Hybrid Map
class BingHybridMapProvider : public BingMapProvider {
Q_OBJECT
public:
BingHybridMapProvider(QObject* parent)
: BingMapProvider(QString("jpg"),AVERAGE_BING_SAT_MAP, QGeoMapType::HybridMap,
parent) {}
protected:
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
#include "ElevationMapProvider.h"
#if defined(DEBUG_GOOGLE_MAPS)
#include <QFile>
#include <QStandardPaths>
#endif
#include "QGCMapEngine.h"
ElevationProvider::ElevationProvider(QString imageFormat, quint32 averageSize,
QGeoMapType::MapStyle mapType,
QObject* parent)
: MapProvider(QString("https://api.airmap.com/"), imageFormat, averageSize,
mapType, parent) {}
ElevationProvider::~ElevationProvider() {}
//-----------------------------------------------------------------------------
int AirmapElevationProvider::long2tileX(double lon, int z) {
Q_UNUSED(z);
return static_cast<int>(floor((lon + 180.0) / srtm1TileSize));
}
//-----------------------------------------------------------------------------
int AirmapElevationProvider::lat2tileY(double lat, int z) {
Q_UNUSED(z);
return static_cast<int>(floor((lat + 90.0) / srtm1TileSize));
}
QString
AirmapElevationProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
Q_UNUSED(zoom);
return QString("https://api.airmap.com/elevation/v1/ele/"
"carpet?points=%1,%2,%3,%4")
.arg(static_cast<double>(y) * srtm1TileSize - 90.0)
.arg(static_cast<double>(x) * srtm1TileSize - 180.0)
.arg(static_cast<double>(y + 1) * srtm1TileSize - 90.0)
.arg(static_cast<double>(x + 1) * srtm1TileSize - 180.0);
}
QGCTileSet AirmapElevationProvider::getTileCount(int zoom, double topleftLon,
double topleftLat,
double bottomRightLon,
double bottomRightLat) {
QGCTileSet set;
set.tileX0 = long2tileX(topleftLon, zoom);
set.tileY0 = lat2tileY(bottomRightLat, zoom);
set.tileX1 = long2tileX(bottomRightLon, zoom);
set.tileY1 = lat2tileY(topleftLat, zoom);
set.tileCount = (static_cast<quint64>(set.tileX1) -
static_cast<quint64>(set.tileX0) + 1) *
(static_cast<quint64>(set.tileY1) -
static_cast<quint64>(set.tileY0) + 1);
set.tileSize = getAverageSize() * set.tileCount;
return set;
}
#pragma once
#include "MapProvider.h"
#include <cmath>
#include <QByteArray>
#include <QMutex>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QPoint>
#include <QString>
const quint32 AVERAGE_AIRMAP_ELEV_SIZE = 2786;
//-----------------------------------------------------------------------------
const double srtm1TileSize = 0.01;
class ElevationProvider : public MapProvider {
Q_OBJECT
public:
ElevationProvider(QString imageFormat, quint32 averageSize,
QGeoMapType::MapStyle mapType, QObject* parent);
~ElevationProvider();
bool _isElevationProvider(){return true;}
protected:
// Define the url to Request
virtual QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) = 0;
};
// -----------------------------------------------------------
// Airmap Elevation
class AirmapElevationProvider : public ElevationProvider {
Q_OBJECT
public:
AirmapElevationProvider(QObject* parent)
: ElevationProvider(QString("bin"), AVERAGE_AIRMAP_ELEV_SIZE,
QGeoMapType::StreetMap, parent) {}
int long2tileX(double lon, int z);
int lat2tileY(double lat, int z);
QGCTileSet getTileCount(int zoom, double topleftLon,
double topleftLat, double bottomRightLon,
double bottomRightLat);
protected:
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
#include "EsriMapProvider.h"
#include "QGCApplication.h"
#include "QGCMapEngine.h"
#include "SettingsManager.h"
QNetworkRequest
EsriMapProvider::getTileURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
//-- Build URL
QNetworkRequest request;
QString url = _getURL(x, y, zoom, networkManager);
if (url.isEmpty()) {
return request;
}
request.setUrl(QUrl(url));
request.setRawHeader("Accept", "*/*");
QByteArray token = qgcApp()
->toolbox()
->settingsManager()
->appSettings()
->esriToken()
->rawValue()
.toString()
.toLatin1();
request.setRawHeader("User-Agent",
QByteArrayLiteral("Qt Location based application"));
request.setRawHeader("User-Token", token);
return request;
}
QString
EsriWorldStreetMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
return QString("http://services.arcgisonline.com/ArcGIS/rest/services/"
"World_Street_Map/MapServer/tile/%1/%2/%3")
.arg(zoom)
.arg(y)
.arg(x);
}
QString
EsriWorldSatelliteMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
return QString("http://server.arcgisonline.com/ArcGIS/rest/"
"services/World_Imagery/MapServer/tile/%1/%2/%3")
.arg(zoom)
.arg(y)
.arg(x);
}
QString EsriTerrainMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
return QString("http://server.arcgisonline.com/ArcGIS/rest/services/"
"World_Terrain_Base/MapServer/tile/%1/%2/%3")
.arg(zoom)
.arg(y)
.arg(x);
}
#pragma once
#include "MapProvider.h"
#include <QByteArray>
#include <QMutex>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QPoint>
#include <QString>
class EsriMapProvider : public MapProvider {
Q_OBJECT
public:
using MapProvider::MapProvider;
QNetworkRequest getTileURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
class EsriWorldStreetMapProvider : public EsriMapProvider {
Q_OBJECT
public:
EsriWorldStreetMapProvider(QObject* parent)
: EsriMapProvider(QString(""), QString(""), AVERAGE_TILE_SIZE,
QGeoMapType::StreetMap, parent) {}
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
class EsriWorldSatelliteMapProvider : public EsriMapProvider {
Q_OBJECT
public:
EsriWorldSatelliteMapProvider(QObject* parent)
: EsriMapProvider(QString(""), QString(""), AVERAGE_TILE_SIZE,
QGeoMapType::SatelliteMapDay, parent) {}
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
class EsriTerrainMapProvider : public EsriMapProvider {
Q_OBJECT
public:
EsriTerrainMapProvider(QObject* parent)
: EsriMapProvider(QString(""), QString(""), AVERAGE_TILE_SIZE,
QGeoMapType::TerrainMap, parent) {}
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
#include "GenericMapProvider.h"
#include "QGCMapEngine.h"
QString StatkartMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
return QString("http://opencache.statkart.no/gatekeeper/gk/"
"gk.open_gmaps?layers=topo4&zoom=%1&x=%2&y=%3")
.arg(zoom)
.arg(x)
.arg(y);
}
QString EniroMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
return QString("http://map.eniro.com/geowebcache/service/tms1.0.0/map/%1/"
"%2/%3.png")
.arg(zoom)
.arg(x)
.arg((1 << zoom) - 1 - y);
}
QString MapQuestMapMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
char letter = "1234"[_getServerNum(x, y, 4)];
return QString("http://otile%1.mqcdn.com/tiles/1.0.0/map/%2/%3/%4.jpg")
.arg(letter)
.arg(zoom)
.arg(x)
.arg(y);
}
QString MapQuestSatMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
char letter = "1234"[_getServerNum(x, y, 4)];
return QString("http://otile%1.mqcdn.com/tiles/1.0.0/sat/%2/%3/%4.jpg")
.arg(letter)
.arg(zoom)
.arg(x)
.arg(y);
}
QString
VWorldStreetMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
int gap = zoom - 6;
int x_min = 53 * pow(2, gap);
int x_max = 55 * pow(2, gap) + (2 * gap - 1);
int y_min = 22 * pow(2, gap);
int y_max = 26 * pow(2, gap) + (2 * gap - 1);
if (zoom > 19) {
return {};
} else if (zoom > 5 && x >= x_min && x <= x_max && y >= y_min &&
y <= y_max) {
return QString(
"http://xdworld.vworld.kr:8080/2d/Base/service/%1/%2/%3.png")
.arg(zoom)
.arg(x)
.arg(y);
} else {
QString key = _tileXYToQuadKey(x, y, zoom);
return QString("http://ecn.t%1.tiles.virtualearth.net/tiles/"
"r%2.png?g=%3&mkt=%4")
.arg(_getServerNum(x, y, 4))
.arg(key)
.arg(_versionBingMaps)
.arg(_language);
}
}
QString VWorldSatMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
int gap = zoom - 6;
int x_min = 53 * pow(2, gap);
int x_max = 55 * pow(2, gap) + (2 * gap - 1);
int y_min = 22 * pow(2, gap);
int y_max = 26 * pow(2, gap) + (2 * gap - 1);
if (zoom > 19) {
return {};
} else if (zoom > 5 && x >= x_min && x <= x_max && y >= y_min &&
y <= y_max) {
return QString("http://xdworld.vworld.kr:8080/2d/Satellite/service/%1/"
"%2/%3.jpeg")
.arg(zoom)
.arg(x)
.arg(y);
} else {
QString key = _tileXYToQuadKey(x, y, zoom);
return QString("http://ecn.t%1.tiles.virtualearth.net/tiles/"
"a%2.jpeg?g=%3&mkt=%4")
.arg(_getServerNum(x, y, 4))
.arg(key)
.arg(_versionBingMaps)
.arg(_language);
}
}
#pragma once
#include "MapProvider.h"
#include <cmath>
#include <QByteArray>
#include <QMutex>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QPoint>
#include <QString>
class StatkartMapProvider : public MapProvider {
Q_OBJECT
public:
StatkartMapProvider(QObject* parent)
: MapProvider(QString("https://www.norgeskart.no/"), QString("png"),
AVERAGE_TILE_SIZE, QGeoMapType::StreetMap, parent) {}
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
class EniroMapProvider : public MapProvider {
Q_OBJECT
public:
EniroMapProvider(QObject* parent)
: MapProvider(QString("https://www.eniro.se/"), QString("png"),
AVERAGE_TILE_SIZE, QGeoMapType::StreetMap, parent) {}
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
class MapQuestMapMapProvider : public MapProvider {
Q_OBJECT
public:
MapQuestMapMapProvider(QObject* parent)
: MapProvider(QString("https://mapquest.com"), QString("jpg"),
AVERAGE_TILE_SIZE, QGeoMapType::StreetMap, parent) {}
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
class MapQuestSatMapProvider : public MapProvider {
Q_OBJECT
public:
MapQuestSatMapProvider(QObject* parent)
: MapProvider(QString("https://mapquest.com"), QString("jpg"),
AVERAGE_TILE_SIZE, QGeoMapType::SatelliteMapDay, parent) {
}
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
class VWorldStreetMapProvider : public MapProvider {
Q_OBJECT
public:
VWorldStreetMapProvider(QObject* parent)
: MapProvider(QString("www.vworld.kr"), QString("png"),
AVERAGE_TILE_SIZE, QGeoMapType::StreetMap, parent) {}
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
private:
const QString _versionBingMaps = "563";
};
class VWorldSatMapProvider : public MapProvider {
Q_OBJECT
public:
VWorldSatMapProvider(QObject* parent)
: MapProvider(QString("www.vworld.kr"), QString("jpg"),
AVERAGE_TILE_SIZE, QGeoMapType::SatelliteMapDay, parent) {
}
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
private:
const QString _versionBingMaps = "563";
};
#include "GoogleMapProvider.h"
#if defined(DEBUG_GOOGLE_MAPS)
#include <QFile>
#include <QStandardPaths>
#endif
#include "QGCMapEngine.h"
GoogleMapProvider::GoogleMapProvider(QString imageFormat, quint32 averageSize,
QGeoMapType::MapStyle mapType,
QObject* parent)
: MapProvider(QString("https://www.google.com/maps/preview"), imageFormat,
averageSize, mapType, parent),
_googleVersionRetrieved(false), _googleReply(nullptr) {
// Google version strings
_versionGoogleMap = "m@354000000";
_versionGoogleSatellite = "692";
_versionGoogleLabels = "h@336";
_versionGoogleTerrain = "t@354,r@354000000";
_versionGoogleHybrid = "y";
_secGoogleWord = "Galileo";
}
GoogleMapProvider::~GoogleMapProvider() {
if (_googleReply)
_googleReply->deleteLater();
}
//-----------------------------------------------------------------------------
void GoogleMapProvider::_getSecGoogleWords(int x, int y, QString& sec1,
QString& sec2) {
sec1 = ""; // after &x=...
sec2 = ""; // after &zoom=...
int seclen = ((x * 3) + y) % 8;
sec2 = _secGoogleWord.left(seclen);
if (y >= 10000 && y < 100000) {
sec1 = "&s=";
}
}
//-----------------------------------------------------------------------------
void GoogleMapProvider::_networkReplyError(QNetworkReply::NetworkError error) {
qWarning() << "Could not connect to google maps. Error:" << error;
if (_googleReply) {
_googleReply->deleteLater();
_googleReply = nullptr;
}
}
//-----------------------------------------------------------------------------
void GoogleMapProvider::_replyDestroyed() { _googleReply = nullptr; }
void GoogleMapProvider::_googleVersionCompleted() {
if (!_googleReply || (_googleReply->error() != QNetworkReply::NoError)) {
qDebug() << "Error collecting Google maps version info";
return;
}
QString html = QString(_googleReply->readAll());
#if defined(DEBUG_GOOGLE_MAPS)
QString filename =
QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
filename += "/google.output";
QFile file(filename);
if (file.open(QIODevice::ReadWrite)) {
QTextStream stream(&file);
stream << html << endl;
}
#endif
QRegExp reg("\"*https?://mt\\D?\\d..*/vt\\?lyrs=m@(\\d*)",
Qt::CaseInsensitive);
if (reg.indexIn(html) != -1) {
QStringList gc = reg.capturedTexts();
_versionGoogleMap = QString("m@%1").arg(gc[1]);
}
reg = QRegExp("\"*https?://khm\\D?\\d.googleapis.com/kh\\?v=(\\d*)",
Qt::CaseInsensitive);
if (reg.indexIn(html) != -1) {
QStringList gc = reg.capturedTexts();
_versionGoogleSatellite = gc[1];
}
reg = QRegExp("\"*https?://mt\\D?\\d..*/vt\\?lyrs=t@(\\d*),r@(\\d*)",
Qt::CaseInsensitive);
if (reg.indexIn(html) != -1) {
QStringList gc = reg.capturedTexts();
_versionGoogleTerrain = QString("t@%1,r@%2").arg(gc[1]).arg(gc[2]);
}
_googleReply->deleteLater();
_googleReply = nullptr;
}
void GoogleMapProvider::_tryCorrectGoogleVersions(
QNetworkAccessManager* networkManager) {
QMutexLocker locker(&_googleVersionMutex);
if (_googleVersionRetrieved) {
return;
}
_googleVersionRetrieved = true;
if (networkManager) {
QNetworkRequest qheader;
QNetworkProxy proxy = networkManager->proxy();
QNetworkProxy tProxy;
tProxy.setType(QNetworkProxy::DefaultProxy);
networkManager->setProxy(tProxy);
QSslConfiguration conf = qheader.sslConfiguration();
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
qheader.setSslConfiguration(conf);
QString url = "http://maps.google.com/maps/api/js?v=3.2&sensor=false";
qheader.setUrl(QUrl(url));
QByteArray ua;
ua.append(getQGCMapEngine()->userAgent());
qheader.setRawHeader("User-Agent", ua);
_googleReply = networkManager->get(qheader);
connect(_googleReply, &QNetworkReply::finished, this,
&GoogleMapProvider::_googleVersionCompleted);
connect(_googleReply, &QNetworkReply::destroyed, this,
&GoogleMapProvider::_replyDestroyed);
connect(
_googleReply,
static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(
&QNetworkReply::error),
this, &GoogleMapProvider::_networkReplyError);
networkManager->setProxy(proxy);
}
}
QString
GoogleStreetMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
// http://mt1.google.com/vt/lyrs=m
QString server = "mt";
QString request = "vt";
QString sec1 = ""; // after &x=...
QString sec2 = ""; // after &zoom=...
_getSecGoogleWords(x, y, sec1, sec2);
_tryCorrectGoogleVersions(networkManager);
return QString(
"http://%1%2.google.com/%3/lyrs=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10")
.arg(server)
.arg(_getServerNum(x, y, 4))
.arg(request)
.arg(_versionGoogleMap)
.arg(_language)
.arg(x)
.arg(sec1)
.arg(y)
.arg(zoom)
.arg(sec2);
}
QString
GoogleSatelliteMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
// http://mt1.google.com/vt/lyrs=s
QString server = "khm";
QString request = "kh";
QString sec1 = ""; // after &x=...
QString sec2 = ""; // after &zoom=...
_getSecGoogleWords(x, y, sec1, sec2);
_tryCorrectGoogleVersions(networkManager);
return QString(
"http://%1%2.google.com/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10")
.arg(server)
.arg(_getServerNum(x, y, 4))
.arg(request)
.arg(_versionGoogleSatellite)
.arg(_language)
.arg(x)
.arg(sec1)
.arg(y)
.arg(zoom)
.arg(sec2);
}
QString
GoogleLabelsMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
QString server = "mts";
QString request = "vt";
QString sec1 = ""; // after &x=...
QString sec2 = ""; // after &zoom=...
_getSecGoogleWords(x, y, sec1, sec2);
_tryCorrectGoogleVersions(networkManager);
return QString(
"http://%1%2.google.com/%3/lyrs=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10")
.arg(server)
.arg(_getServerNum(x, y, 4))
.arg(request)
.arg(_versionGoogleLabels)
.arg(_language)
.arg(x)
.arg(sec1)
.arg(y)
.arg(zoom)
.arg(sec2);
}
QString
GoogleTerrainMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
QString server = "mt";
QString request = "vt";
QString sec1 = ""; // after &x=...
QString sec2 = ""; // after &zoom=...
_getSecGoogleWords(x, y, sec1, sec2);
_tryCorrectGoogleVersions(networkManager);
return QString(
"http://%1%2.google.com/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10")
.arg(server)
.arg(_getServerNum(x, y, 4))
.arg(request)
.arg(_versionGoogleTerrain)
.arg(_language)
.arg(x)
.arg(sec1)
.arg(y)
.arg(zoom)
.arg(sec2);
}
QString
GoogleHybridMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
QString server = "mt";
QString request = "vt";
QString sec1 = ""; // after &x=...
QString sec2 = ""; // after &zoom=...
_getSecGoogleWords(x, y, sec1, sec2);
_tryCorrectGoogleVersions(networkManager);
return QString(
"http://%1%2.google.com/%3/lyrs=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10")
.arg(server)
.arg(_getServerNum(x, y, 4))
.arg(request)
.arg(_versionGoogleHybrid)
.arg(_language)
.arg(x)
.arg(sec1)
.arg(y)
.arg(zoom)
.arg(sec2);
}
#pragma once
#include "MapProvider.h"
#include <QByteArray>
#include <QMutex>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QPoint>
#include <QString>
class GoogleMapProvider : public MapProvider {
Q_OBJECT
public:
GoogleMapProvider(QString imageFormat, quint32 averageSize,
QGeoMapType::MapStyle mapType, QObject* parent);
~GoogleMapProvider();
// Google Specific private slots
private slots:
void _networkReplyError(QNetworkReply::NetworkError error);
void _googleVersionCompleted();
void _replyDestroyed();
protected:
// Define the url to Request
virtual QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) = 0;
// Google Specific private methods
void _getSecGoogleWords(int x, int y, QString& sec1, QString& sec2);
void _tryCorrectGoogleVersions(QNetworkAccessManager* networkManager);
// Google Specific attributes
bool _googleVersionRetrieved;
QNetworkReply* _googleReply;
QMutex _googleVersionMutex;
QString _versionGoogleMap;
QString _versionGoogleSatellite;
QString _versionGoogleLabels;
QString _versionGoogleTerrain;
QString _versionGoogleHybrid;
QString _secGoogleWord;
};
// NoMap = 0,
// StreetMap,
// SatelliteMapDay,
// SatelliteMapNight,
// TerrainMap,
// HybridMap,
// TransitMap,
// GrayStreetMap,
// PedestrianMap,
// CarNavigationMap,
// CycleMap,
// CustomMap = 100
const quint32 AVERAGE_GOOGLE_STREET_MAP = 4913;
const quint32 AVERAGE_GOOGLE_SAT_MAP = 56887;
const quint32 AVERAGE_GOOGLE_TERRAIN_MAP = 19391;
// -----------------------------------------------------------
// Google Street Map
class GoogleStreetMapProvider : public GoogleMapProvider {
Q_OBJECT
public:
GoogleStreetMapProvider(QObject* parent)
: GoogleMapProvider(QString("png"), AVERAGE_GOOGLE_STREET_MAP,
QGeoMapType::StreetMap, parent) {}
protected:
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
// -----------------------------------------------------------
// Google Street Map
class GoogleSatelliteMapProvider : public GoogleMapProvider {
Q_OBJECT
public:
GoogleSatelliteMapProvider(QObject* parent)
: GoogleMapProvider(QString("jpg"), AVERAGE_GOOGLE_SAT_MAP,
QGeoMapType::SatelliteMapDay, parent) {}
protected:
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
// -----------------------------------------------------------
// Google Labels Map
class GoogleLabelsMapProvider : public GoogleMapProvider {
Q_OBJECT
public:
GoogleLabelsMapProvider(QObject* parent)
: GoogleMapProvider(QString("png"), AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
protected:
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
// -----------------------------------------------------------
// Google Terrain Map
class GoogleTerrainMapProvider : public GoogleMapProvider {
Q_OBJECT
public:
GoogleTerrainMapProvider(QObject* parent)
: GoogleMapProvider(QString("png"), AVERAGE_GOOGLE_TERRAIN_MAP,
QGeoMapType::TerrainMap, parent) {}
protected:
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
// -----------------------------------------------------------
// Google Hybrid Map
class GoogleHybridMapProvider : public GoogleMapProvider {
Q_OBJECT
public:
GoogleHybridMapProvider(QObject* parent)
: GoogleMapProvider(QString("png"), AVERAGE_GOOGLE_SAT_MAP,
QGeoMapType::HybridMap, parent) {}
protected:
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
};
#include "MapProvider.h"
MapProvider::MapProvider(QString referrer, QString imageFormat,
quint32 averageSize, QGeoMapType::MapStyle mapType,QObject* parent)
: QObject(parent), _referrer(referrer), _imageFormat(imageFormat),
_averageSize(averageSize), _mapType(mapType) {
QStringList langs = QLocale::system().uiLanguages();
if (langs.length() > 0) {
_language = langs[0];
}
}
QNetworkRequest MapProvider::getTileURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
//-- Build URL
QNetworkRequest request;
QString url = _getURL(x, y, zoom, networkManager);
if (url.isEmpty()) {
return request;
}
request.setUrl(QUrl(url));
request.setRawHeader("Accept", "*/*");
request.setRawHeader("Referrer", _referrer.toUtf8());
request.setRawHeader("User-Agent", _userAgent);
return request;
}
QString MapProvider::getImageFormat(const QByteArray& image) {
QString format;
if (image.size() > 2) {
if (image.startsWith(reinterpret_cast<const char*>(pngSignature)))
format = "png";
else if (image.startsWith(reinterpret_cast<const char*>(jpegSignature)))
format = "jpg";
else if (image.startsWith(reinterpret_cast<const char*>(gifSignature)))
format = "gif";
else {
return _imageFormat;
}
}
return format;
}
QString MapProvider::_tileXYToQuadKey(int tileX, int tileY, int levelOfDetail) {
QString quadKey;
for (int i = levelOfDetail; i > 0; i--) {
char digit = '0';
int mask = 1 << (i - 1);
if ((tileX & mask) != 0) {
digit++;
}
if ((tileY & mask) != 0) {
digit++;
digit++;
}
quadKey.append(digit);
}
return quadKey;
}
int MapProvider::_getServerNum(int x, int y, int max) {
return (x + 2 * y) % max;
}
int MapProvider::long2tileX(double lon, int z) {
return static_cast<int>(floor((lon + 180.0) / 360.0 * pow(2.0, z)));
}
//-----------------------------------------------------------------------------
int MapProvider::lat2tileY(double lat, int z) {
return static_cast<int>(floor(
(1.0 -
log(tan(lat * M_PI / 180.0) + 1.0 / cos(lat * M_PI / 180.0)) / M_PI) /
2.0 * pow(2.0, z)));
}
bool MapProvider::_isElevationProvider() { return false; }
QGCTileSet MapProvider::getTileCount(int zoom, double topleftLon,
double topleftLat, double bottomRightLon,
double bottomRightLat) {
QGCTileSet set;
set.tileX0 = long2tileX(topleftLon, zoom);
set.tileY0 = lat2tileY(topleftLat, zoom);
set.tileX1 = long2tileX(bottomRightLon, zoom);
set.tileY1 = lat2tileY(bottomRightLat, zoom);
set.tileCount = (static_cast<quint64>(set.tileX1) -
static_cast<quint64>(set.tileX0) + 1) *
(static_cast<quint64>(set.tileY1) -
static_cast<quint64>(set.tileY0) + 1);
set.tileSize = getAverageSize() * set.tileCount;
return set;
}
#pragma once
#include <cmath>
#include "QGCTileSet.h"
#include <QByteArray>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QString>
#include <QtLocation/private/qgeomaptype_p.h>
static const unsigned char pngSignature[] = {0x89, 0x50, 0x4E, 0x47, 0x0D,
0x0A, 0x1A, 0x0A, 0x00};
static const unsigned char jpegSignature[] = {0xFF, 0xD8, 0xFF, 0x00};
static const unsigned char gifSignature[] = {0x47, 0x49, 0x46, 0x38, 0x00};
const quint32 AVERAGE_TILE_SIZE = 13652;
class MapProvider : public QObject {
Q_OBJECT
public:
MapProvider(
QString referrer, QString imageFormat, quint32 averageSize,
QGeoMapType::MapStyle _mapType = QGeoMapType::CustomMap, QObject* parent = nullptr);
QNetworkRequest getTileURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
QString getImageFormat(const QByteArray& image);
quint32 getAverageSize(){return _averageSize;}
QGeoMapType::MapStyle getMapStyle(){return _mapType;}
virtual int long2tileX(double lon, int z);
virtual int lat2tileY(double lat, int z);
virtual bool _isElevationProvider();
virtual QGCTileSet getTileCount(int zoom, double topleftLon,
double topleftLat, double bottomRightLon,
double bottomRightLat);
protected:
QString _tileXYToQuadKey(int tileX, int tileY, int levelOfDetail);
int _getServerNum(int x, int y, int max);
// Define Referrer for Request RawHeader
QString _referrer;
QString _imageFormat;
quint32 _averageSize;
QByteArray _userAgent;
QString _language;
QGeoMapType::MapStyle _mapType;
// Define the url to Request
virtual QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) = 0;
};
#include "MapboxMapProvider.h"
#include "QGCApplication.h"
#include "QGCMapEngine.h"
#include "SettingsManager.h"
MapboxMapProvider::MapboxMapProvider(QString mapName, quint32 averageSize,
QGeoMapType::MapStyle mapType,
QObject* parent)
: MapProvider(QString("https://www.mapbox.com/"), QString("jpg"),
averageSize, mapType, parent), mapboxName(mapName) {
}
QString
MapboxMapProvider::_getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager) {
Q_UNUSED(networkManager);
QString mapBoxToken = qgcApp()
->toolbox()
->settingsManager()
->appSettings()
->mapboxToken()
->rawValue()
.toString();
if (!mapBoxToken.isEmpty()) {
QString server = "https://api.mapbox.com/v4/";
server += mapboxName;
server += QString("/%1/%2/%3.jpg80?access_token=%4")
.arg(zoom)
.arg(x)
.arg(y)
.arg(mapBoxToken);
return server;
}
return QString("");
}
#pragma once
#include "MapProvider.h"
#include <QByteArray>
#include <QMutex>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QPoint>
#include <QString>
const quint32 AVERAGE_MAPBOX_SAT_MAP = 15739;
const quint32 AVERAGE_MAPBOX_STREET_MAP = 5648;
class MapboxMapProvider : public MapProvider {
Q_OBJECT
public:
MapboxMapProvider(QString mapName, quint32 averageSize,
QGeoMapType::MapStyle mapType, QObject* parent);
QString _getURL(int x, int y, int zoom,
QNetworkAccessManager* networkManager);
protected:
QString mapboxName;
};
class MapboxStreetMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxStreetMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.streets", AVERAGE_MAPBOX_STREET_MAP,
QGeoMapType::StreetMap, parent) {}
};
class MapboxLightMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxLightMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.light", AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
};
class MapboxDarkMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxDarkMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.dark", AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
};
class MapboxSatelliteMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxSatelliteMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.satellite", AVERAGE_MAPBOX_SAT_MAP,
QGeoMapType::SatelliteMapDay, parent) {}
};
class MapboxHybridMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxHybridMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.hybrid", AVERAGE_MAPBOX_SAT_MAP,
QGeoMapType::HybridMap, parent) {}
};
class MapboxWheatPasteMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxWheatPasteMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.wheatpaste", AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
};
class MapboxStreetsBasicMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxStreetsBasicMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.streets-basic", AVERAGE_TILE_SIZE,
QGeoMapType::StreetMap, parent) {}
};
class MapboxComicMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxComicMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.comic", AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
};
class MapboxOutdoorsMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxOutdoorsMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.outdoors", AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
};
class MapboxRunBikeHikeMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxRunBikeHikeMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.run-bike-hike", AVERAGE_MAPBOX_STREET_MAP,
QGeoMapType::CycleMap, parent) {}
};
class MapboxPencilMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxPencilMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.pencil", AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
};
class MapboxPiratesMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxPiratesMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.pirates", AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
};
class MapboxEmeraldMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxEmeraldMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.emerald", AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
};
class MapboxHighContrastMapProvider : public MapboxMapProvider {
Q_OBJECT
public:
MapboxHighContrastMapProvider(QObject* parent)
: MapboxMapProvider("mapbox.high-contrast", AVERAGE_TILE_SIZE,
QGeoMapType::CustomMap, parent) {}
};
......@@ -22,6 +22,15 @@ HEADERS += \
$$PWD/QGeoServiceProviderPluginQGC.h \
$$PWD/QGeoTileFetcherQGC.h \
$$PWD/QGeoTiledMappingManagerEngineQGC.h \
$$PWD/MapProvider.h \
$$PWD/ElevationMapProvider.h \
$$PWD/GoogleMapProvider.h \
$$PWD/BingMapProvider.h \
$$PWD/GenericMapProvider.h \
$$PWD/EsriMapProvider.h \
$$PWD/MapboxMapProvider.h \
$$PWD/QGCTileSet.h \
SOURCES += \
$$PWD/QGCMapEngine.cpp \
......@@ -34,6 +43,13 @@ SOURCES += \
$$PWD/QGeoServiceProviderPluginQGC.cpp \
$$PWD/QGeoTileFetcherQGC.cpp \
$$PWD/QGeoTiledMappingManagerEngineQGC.cpp \
$$PWD/MapProvider.cpp \
$$PWD/ElevationMapProvider.cpp \
$$PWD/GoogleMapProvider.cpp \
$$PWD/BingMapProvider.cpp \
$$PWD/GenericMapProvider.cpp \
$$PWD/EsriMapProvider.cpp \
$$PWD/MapboxMapProvider.cpp \
OTHER_FILES += \
$$PWD/qgc_maps_plugin.json
This diff is collapsed.
......@@ -25,41 +25,6 @@
#include "QGCMapEngineData.h"
#include "QGCTileCacheWorker.h"
//-----------------------------------------------------------------------------
class QGCTileSet
{
public:
QGCTileSet()
{
clear();
}
QGCTileSet& operator += (QGCTileSet& other)
{
tileX0 += other.tileX0;
tileX1 += other.tileX1;
tileY0 += other.tileY0;
tileY1 += other.tileY1;
tileCount += other.tileCount;
tileSize += other.tileSize;
return *this;
}
void clear()
{
tileX0 = 0;
tileX1 = 0;
tileY0 = 0;
tileY1 = 0;
tileCount = 0;
tileSize = 0;
}
int tileX0;
int tileX1;
int tileY0;
int tileY1;
quint64 tileCount;
quint64 tileSize;
};
//-----------------------------------------------------------------------------
class QGCMapEngine : public QObject
......@@ -71,13 +36,13 @@ public:
void init ();
void addTask (QGCMapTask *task);
void cacheTile (UrlFactory::MapType type, int x, int y, int z, const QByteArray& image, const QString& format, qulonglong set = UINT64_MAX);
void cacheTile (UrlFactory::MapType type, const QString& hash, const QByteArray& image, const QString& format, qulonglong set = UINT64_MAX);
QGCFetchTileTask* createFetchTileTask (UrlFactory::MapType type, int x, int y, int z);
void cacheTile (QString type, int x, int y, int z, const QByteArray& image, const QString& format, qulonglong set = UINT64_MAX);
void cacheTile (QString type, const QString& hash, const QByteArray& image, const QString& format, qulonglong set = UINT64_MAX);
QGCFetchTileTask* createFetchTileTask (QString type, int x, int y, int z);
QStringList getMapNameList ();
const QString userAgent () { return _userAgent; }
void setUserAgent (const QString& ua) { _userAgent = ua; }
UrlFactory::MapType hashToType (const QString& hash);
QString hashToType (const QString& hash);
quint32 getMaxDiskCache ();
void setMaxDiskCache (quint32 size);
quint32 getMaxMemCache ();
......@@ -91,20 +56,13 @@ public:
UrlFactory* urlFactory () { return _urlFactory; }
//-- Tile Math
static QGCTileSet getTileCount (int zoom, double topleftLon, double topleftLat, double bottomRightLon, double bottomRightLat, UrlFactory::MapType mapType);
static int long2tileX (double lon, int z);
static int lat2tileY (double lat, int z);
static int long2elevationTileX (double lon, int z);
static int lat2elevationTileY (double lat, int z);
static QString getTileHash (UrlFactory::MapType type, int x, int y, int z);
static UrlFactory::MapType getTypeFromName (const QString &name);
static QGCTileSet getTileCount (int zoom, double topleftLon, double topleftLat, double bottomRightLon, double bottomRightLat, QString mapType);
static QString getTileHash (QString type, int x, int y, int z);
static QString getTypeFromName (const QString &name);
static QString bigSizeToString (quint64 size);
static QString storageFreeSizeToString(quint64 size_MB);
static QString numberToString (quint64 number);
static int concurrentDownloads (UrlFactory::MapType type);
/// size of an elevation tile in degree
static const double srtm1TileSize;
static int concurrentDownloads (QString type);
private slots:
void _updateTotals (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize);
......
......@@ -37,7 +37,7 @@ public:
, _y(0)
, _z(0)
, _set(UINT64_MAX)
, _type(UrlFactory::Invalid)
, _type("Invalid")
{
}
......@@ -53,14 +53,14 @@ public:
int z () const { return _z; }
qulonglong set () const { return _set; }
const QString hash () const { return _hash; }
UrlFactory::MapType type () const { return _type; }
QString type () const { return _type; }
void setX (int x) { _x = x; }
void setY (int y) { _y = y; }
void setZ (int z) { _z = z; }
void setTileSet (qulonglong set) { _set = set; }
void setHash (const QString& hash) { _hash = hash; }
void setType (UrlFactory::MapType type) { _type = type; }
void setType (QString type) { _type = type; }
private:
int _x;
......@@ -68,7 +68,7 @@ private:
int _z;
qulonglong _set;
QString _hash;
UrlFactory::MapType _type;
QString _type;
};
//-----------------------------------------------------------------------------
......@@ -76,7 +76,7 @@ class QGCCacheTile : public QObject
{
Q_OBJECT
public:
QGCCacheTile (const QString hash, const QByteArray img, const QString format, UrlFactory::MapType type, qulonglong set = UINT64_MAX)
QGCCacheTile (const QString hash, const QByteArray img, const QString format, QString type, qulonglong set = UINT64_MAX)
: _set(set)
, _hash(hash)
, _img(img)
......@@ -93,13 +93,13 @@ public:
QString hash () { return _hash; }
QByteArray img () { return _img; }
QString format () { return _format;}
UrlFactory::MapType type () { return _type; }
QString type () { return _type; }
private:
qulonglong _set;
QString _hash;
QByteArray _img;
QString _format;
UrlFactory::MapType _type;
QString _type;
};
//-----------------------------------------------------------------------------
......
......@@ -47,7 +47,7 @@ QGCCachedTileSet::QGCCachedTileSet(const QString& name)
, _deleting(false)
, _downloading(false)
, _id(0)
, _type(UrlFactory::Invalid)
, _type("Invalid")
, _networkManager(nullptr)
, _errorCount(0)
, _noMoreTiles(false)
......@@ -201,7 +201,15 @@ void QGCCachedTileSet::_doneWithDownload()
_totalTileCount = _savedTileCount;
_totalTileSize = _savedTileSize;
//-- Too expensive to compute the real size now. Estimate it for the time being.
quint32 avg = _savedTileSize / _savedTileCount;
quint32 avg;
if(_savedTileSize != 0){
avg = _savedTileSize / _savedTileCount;
}
else{
qWarning() << "QGCMapEngineManager::_doneWithDownload _savedTileSize=0 !";
avg = 0;
}
_uniqueTileSize = _uniqueTileCount * avg;
}
emit totalTileCountChanged();
......@@ -279,8 +287,8 @@ QGCCachedTileSet::_networkReplyFinished()
}
qCDebug(QGCCachedTileSetLog) << "Tile fetched" << hash;
QByteArray image = reply->readAll();
UrlFactory::MapType type = getQGCMapEngine()->hashToType(hash);
if (type == UrlFactory::MapType::AirmapElevation) {
QString type = getQGCMapEngine()->hashToType(hash);
if (type == "Airmap Elevation" ) {
image = TerrainTile::serialize(image);
}
QString format = getQGCMapEngine()->urlFactory()->getImageFormat(type, image);
......
......@@ -103,7 +103,7 @@ public:
int maxZoom () { return _maxZoom; }
QDateTime creationDate () { return _creationDate; }
quint64 id () { return _id; }
UrlFactory::MapType type () { return _type; }
QString type () { return _type; }
bool complete () { return _defaultSet || (_totalTileCount <= _savedTileCount); }
bool defaultSet () { return _defaultSet; }
quint64 setID () { return _id; }
......@@ -130,7 +130,7 @@ public:
void setMaxZoom (int zoom) { _maxZoom = zoom; }
void setCreationDate (QDateTime date) { _creationDate = date; }
void setId (quint64 id) { _id = id; }
void setType (UrlFactory::MapType type) { _type = type; }
void setType (QString type) { _type = type; }
void setDefaultSet (bool def) { _defaultSet = def; }
void setDeleting (bool del) { _deleting = del; emit deletingChanged(); }
void setDownloading (bool down) { _downloading = down; }
......@@ -178,7 +178,7 @@ private:
bool _downloading;
QDateTime _creationDate;
quint64 _id;
UrlFactory::MapType _type;
QString _type;
QNetworkAccessManager* _networkManager;
QHash<QString, QNetworkReply*> _replies;
quint32 _errorCount;
......
This diff is collapsed.
......@@ -16,12 +16,13 @@
#ifndef QGC_MAP_URL_ENGINE_H
#define QGC_MAP_URL_ENGINE_H
#include <QString>
#include <QPoint>
#include <QByteArray>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QMutex>
#include "GoogleMapProvider.h"
#include "BingMapProvider.h"
#include "GenericMapProvider.h"
#include "EsriMapProvider.h"
#include "MapboxMapProvider.h"
#include "ElevationMapProvider.h"
#define MAX_MAP_ZOOM (20.0)
......@@ -29,103 +30,35 @@ class UrlFactory : public QObject {
Q_OBJECT
public:
enum MapType
{
Invalid = -1,
GoogleMap = 1,
GoogleSatellite = 4,
GoogleLabels = 8,
GoogleTerrain = 16,
GoogleHybrid = 20,
OpenStreetMap = 32,
OpenStreetOsm = 33,
OpenStreetMapSurfer = 34,
OpenStreetMapSurferTerrain=35,
StatkartTopo = 100,
EniroTopo = 110,
BingMap = 444,
BingSatellite = 555,
BingHybrid = 666,
/*
MapQuestMap = 700,
MapQuestSat = 701,
*/
VWorldMap = 800,
VWorldSatellite = 801,
VWorldStreet = 802,
MapboxStreets = 6000,
MapboxLight = 6001,
MapboxDark = 6002,
MapboxSatellite = 6003,
MapboxHybrid = 6004,
MapboxWheatPaste = 6005,
MapboxStreetsBasic = 6006,
MapboxComic = 6007,
MapboxOutdoors = 6008,
MapboxRunBikeHike = 6009,
MapboxPencil = 6010,
MapboxPirates = 6011,
MapboxEmerald = 6012,
MapboxHighContrast = 6013,
EsriWorldStreet = 7000,
EsriWorldSatellite = 7001,
EsriTerrain = 7002,
AirmapElevation = 8001
};
UrlFactory ();
~UrlFactory ();
QNetworkRequest getTileURL (MapType type, int x, int y, int zoom, QNetworkAccessManager* networkManager);
QString getImageFormat (MapType type, const QByteArray& image);
QNetworkRequest getTileURL (QString type, int x, int y, int zoom, QNetworkAccessManager* networkManager);
QNetworkRequest getTileURL (int id, int x, int y, int zoom, QNetworkAccessManager* networkManager);
static quint32 averageSizeForType (MapType type);
QString getImageFormat (QString type, const QByteArray& image);
QString getImageFormat (int id , const QByteArray& image);
private slots:
#ifndef QGC_NO_GOOGLE_MAPS
void _networkReplyError (QNetworkReply::NetworkError error);
void _googleVersionCompleted ();
void _replyDestroyed ();
#endif
quint32 averageSizeForType (QString type);
private:
QString _getURL (MapType type, int x, int y, int zoom, QNetworkAccessManager* networkManager);
QString _tileXYToQuadKey (int tileX, int tileY, int levelOfDetail);
int _getServerNum (int x, int y, int max);
#ifndef QGC_NO_GOOGLE_MAPS
void _getSecGoogleWords (int x, int y, QString& sec1, QString& sec2);
void _tryCorrectGoogleVersions (QNetworkAccessManager* networkManager);
#endif
int long2tileX(QString mapType, double lon, int z);
int lat2tileY(QString mapType, double lat, int z);
private:
int _timeout;
QByteArray _userAgent;
QString _language;
// Google version strings
#ifndef QGC_NO_GOOGLE_MAPS
bool _googleVersionRetrieved;
QNetworkReply* _googleReply;
QMutex _googleVersionMutex;
QString _versionGoogleMap;
QString _versionGoogleSatellite;
QString _versionGoogleLabels;
QString _versionGoogleTerrain;
QString _versionGoogleHybrid;
QString _secGoogleWord;
#endif
QHash<QString, MapProvider*> getProviderTable(){return _providersTable;}
int getIdFromType(QString type);
QString getTypeFromId(int id);
QGCTileSet getTileCount(int zoom, double topleftLon, double topleftLat,
double bottomRightLon, double bottomRightLat,
QString mapType);
// BingMaps
QString _versionBingMaps;
bool isElevation(int mapId);
private:
int _timeout;
QHash<QString, MapProvider*> _providersTable;
void registerProvider(QString Name, MapProvider* provider);
};
......
......@@ -282,7 +282,7 @@ QGCCacheWorker::_getTile(QGCMapTask* mtask)
if(query.next()) {
QByteArray ar = query.value(0).toByteArray();
QString format = query.value(1).toString();
UrlFactory::MapType type = static_cast<UrlFactory::MapType>(query.value(2).toInt());
QString type = getQGCMapEngine()->urlFactory()->getTypeFromId(query.value(2).toInt());
qCDebug(QGCTileCacheLog) << "_getTile() (Found in DB) HASH:" << task->hash();
QGCCacheTile* tile = new QGCCacheTile(task->hash(), ar, format, type);
task->setTileFetched(tile);
......@@ -318,7 +318,7 @@ QGCCacheWorker::_getTileSets(QGCMapTask* mtask)
set->setBottomRightLon(query.value("bottomRightLon").toDouble());
set->setMinZoom(query.value("minZoom").toInt());
set->setMaxZoom(query.value("maxZoom").toInt());
set->setType(static_cast<UrlFactory::MapType>(query.value("type").toInt()));
set->setType(getQGCMapEngine()->urlFactory()->getTypeFromId(query.value("type").toInt()));
set->setTotalTileCount(query.value("numTiles").toUInt());
set->setDefaultSet(query.value("defaultSet").toInt() != 0);
set->setCreationDate(QDateTime::fromTime_t(query.value("date").toUInt()));
......@@ -353,7 +353,7 @@ QGCCacheWorker::_updateSetTotals(QGCCachedTileSet* set)
set->setSavedTileSize(subquery.value(1).toULongLong());
qCDebug(QGCTileCacheLog) << "Set" << set->id() << "Totals:" << set->savedTileCount() << " " << set->savedTileSize() << "Expected: " << set->totalTileCount() << " " << set->totalTilesSize();
//-- Update (estimated) size
quint64 avg = UrlFactory::averageSizeForType(set->type());
quint64 avg = getQGCMapEngine()->urlFactory()->averageSizeForType(set->type());
if(set->totalTileCount() <= set->savedTileCount()) {
//-- We're done so the saved size is the total size
set->setTotalTileSize(set->savedTileSize());
......@@ -448,7 +448,7 @@ QGCCacheWorker::_createTileSet(QGCMapTask *mtask)
query.addBindValue(task->tileSet()->bottomRightLon());
query.addBindValue(task->tileSet()->minZoom());
query.addBindValue(task->tileSet()->maxZoom());
query.addBindValue(task->tileSet()->type());
query.addBindValue(getQGCMapEngine()->urlFactory()->getIdFromType(task->tileSet()->type()));
query.addBindValue(task->tileSet()->totalTileCount());
query.addBindValue(QDateTime::currentDateTime().toTime_t());
if(!query.exec()) {
......@@ -465,7 +465,7 @@ QGCCacheWorker::_createTileSet(QGCMapTask *mtask)
task->tileSet()->topleftLon(), task->tileSet()->topleftLat(),
task->tileSet()->bottomRightLon(), task->tileSet()->bottomRightLat(), task->tileSet()->type());
tileCount += set.tileCount;
UrlFactory::MapType type = task->tileSet()->type();
QString type = task->tileSet()->type();
for(int x = set.tileX0; x <= set.tileX1; x++) {
for(int y = set.tileY0; y <= set.tileY1; y++) {
//-- See if tile is already downloaded
......@@ -476,7 +476,7 @@ QGCCacheWorker::_createTileSet(QGCMapTask *mtask)
query.prepare("INSERT OR IGNORE INTO TilesDownload(setID, hash, type, x, y, z, state) VALUES(?, ?, ?, ?, ? ,? ,?)");
query.addBindValue(setID);
query.addBindValue(hash);
query.addBindValue(type);
query.addBindValue(getQGCMapEngine()->urlFactory()->getIdFromType(type));
query.addBindValue(x);
query.addBindValue(y);
query.addBindValue(z);
......@@ -524,7 +524,7 @@ QGCCacheWorker::_getTileDownloadList(QGCMapTask* mtask)
while(query.next()) {
QGCTile* tile = new QGCTile;
tile->setHash(query.value("hash").toString());
tile->setType(static_cast<UrlFactory::MapType>(query.value("type").toInt()));
tile->setType(getQGCMapEngine()->urlFactory()->getTypeFromId(query.value("type").toInt()));
tile->setX(query.value("x").toInt());
tile->setY(query.value("y").toInt());
tile->setZ(query.value("z").toInt());
......@@ -897,7 +897,7 @@ QGCCacheWorker::_exportSets(QGCMapTask* mtask)
exportQuery.addBindValue(set->bottomRightLon());
exportQuery.addBindValue(set->minZoom());
exportQuery.addBindValue(set->maxZoom());
exportQuery.addBindValue(set->type());
exportQuery.addBindValue(getQGCMapEngine()->urlFactory()->getIdFromType(set->type()));
exportQuery.addBindValue(set->totalTileCount());
exportQuery.addBindValue(set->defaultSet());
exportQuery.addBindValue(QDateTime::currentDateTime().toTime_t());
......
#pragma once
#include <QString>
//-----------------------------------------------------------------------------
class QGCTileSet
{
public:
QGCTileSet()
{
clear();
}
QGCTileSet& operator += (QGCTileSet& other)
{
tileX0 += other.tileX0;
tileX1 += other.tileX1;
tileY0 += other.tileY0;
tileY1 += other.tileY1;
tileCount += other.tileCount;
tileSize += other.tileSize;
return *this;
}
void clear()
{
tileX0 = 0;
tileX1 = 0;
tileY0 = 0;
tileY1 = 0;
tileCount = 0;
tileSize = 0;
}
int tileX0;
int tileX1;
int tileY0;
int tileY1;
quint64 tileCount;
quint64 tileSize;
};
......@@ -73,7 +73,7 @@ QGeoTiledMapReplyQGC::QGeoTiledMapReplyQGC(QNetworkAccessManager *networkManager
setFinished(true);
setCached(false);
} else {
QGCFetchTileTask* task = getQGCMapEngine()->createFetchTileTask(static_cast<UrlFactory::MapType>(spec.mapId()), spec.x(), spec.y(), spec.zoom());
QGCFetchTileTask* task = getQGCMapEngine()->createFetchTileTask(getQGCMapEngine()->urlFactory()->getTypeFromId(spec.mapId()), spec.x(), spec.y(), spec.zoom());
connect(task, &QGCFetchTileTask::tileFetched, this, &QGeoTiledMapReplyQGC::cacheReply);
connect(task, &QGCMapTask::error, this, &QGeoTiledMapReplyQGC::cacheError);
getQGCMapEngine()->addTask(task);
......@@ -122,13 +122,16 @@ QGeoTiledMapReplyQGC::networkReplyFinished()
return;
}
QByteArray a = _reply->readAll();
QString format = getQGCMapEngine()->urlFactory()->getImageFormat(static_cast<UrlFactory::MapType>(tileSpec().mapId()), a);
QString format = getQGCMapEngine()->urlFactory()->getImageFormat(tileSpec().mapId(), a);
//-- Test for a specialized, elevation data (not map tile)
if (static_cast<UrlFactory::MapType>(tileSpec().mapId()) == UrlFactory::MapType::AirmapElevation) {
if( getQGCMapEngine()->urlFactory()->isElevation(tileSpec().mapId())){
a = TerrainTile::serialize(a);
//-- Cache it if valid
if(!a.isEmpty()) {
getQGCMapEngine()->cacheTile(UrlFactory::MapType::AirmapElevation, tileSpec().x(), tileSpec().y(), tileSpec().zoom(), a, format);
getQGCMapEngine()->cacheTile(
getQGCMapEngine()->urlFactory()->getTypeFromId(
tileSpec().mapId()),
tileSpec().x(), tileSpec().y(), tileSpec().zoom(), a, format);
}
emit terrainDone(a, QNetworkReply::NoError);
} else {
......@@ -136,7 +139,7 @@ QGeoTiledMapReplyQGC::networkReplyFinished()
setMapImageData(a);
if(!format.isEmpty()) {
setMapImageFormat(format);
getQGCMapEngine()->cacheTile(static_cast<UrlFactory::MapType>(tileSpec().mapId()), tileSpec().x(), tileSpec().y(), tileSpec().zoom(), a, format);
getQGCMapEngine()->cacheTile(getQGCMapEngine()->urlFactory()->getTypeFromId(tileSpec().mapId()), tileSpec().x(), tileSpec().y(), tileSpec().zoom(), a, format);
}
setFinished(true);
}
......@@ -152,7 +155,7 @@ QGeoTiledMapReplyQGC::networkReplyError(QNetworkReply::NetworkError error)
return;
}
//-- Test for a specialized, elevation data (not map tile)
if (static_cast<UrlFactory::MapType>(tileSpec().mapId()) == UrlFactory::MapType::AirmapElevation) {
if( getQGCMapEngine()->urlFactory()->isElevation(tileSpec().mapId())){
emit terrainDone(QByteArray(), error);
} else {
//-- Regular map tile
......@@ -170,7 +173,7 @@ void
QGeoTiledMapReplyQGC::cacheError(QGCMapTask::TaskType type, QString /*errorString*/)
{
if(!getQGCMapEngine()->isInternetActive()) {
if (static_cast<UrlFactory::MapType>(tileSpec().mapId()) == UrlFactory::MapType::AirmapElevation) {
if( getQGCMapEngine()->urlFactory()->isElevation(tileSpec().mapId())){
emit terrainDone(QByteArray(), QNetworkReply::NetworkSessionFailedError);
} else {
setError(QGeoTiledMapReply::CommunicationError, "Network not available");
......@@ -207,7 +210,7 @@ void
QGeoTiledMapReplyQGC::cacheReply(QGCCacheTile* tile)
{
//-- Test for a specialized, elevation data (not map tile)
if (static_cast<UrlFactory::MapType>(tileSpec().mapId()) == UrlFactory::MapType::AirmapElevation) {
if( getQGCMapEngine()->urlFactory()->isElevation(tileSpec().mapId())){
emit terrainDone(tile->img(), QNetworkReply::NoError);
} else {
//-- Regular map tile
......
......@@ -74,7 +74,7 @@ QGeoTiledMapReply*
QGeoTileFetcherQGC::getTileImage(const QGeoTileSpec &spec)
{
//-- Build URL
QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL((UrlFactory::MapType)spec.mapId(), spec.x(), spec.y(), spec.zoom(), _networkManager);
QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL(spec.mapId(), spec.x(), spec.y(), spec.zoom(), _networkManager);
if ( ! request.url().isEmpty() ) {
return new QGeoTiledMapReplyQGC(_networkManager, request, spec);
}
......
......@@ -100,65 +100,17 @@ QGeoTiledMappingManagerEngineQGC::QGeoTiledMappingManagerEngineQGC(const QVarian
* Google and Bing don't seem kosher at all. This was based on original code from OpenPilot and heavily modified to be used in QGC.
*/
//-- IMPORTANT
// Changes here must reflect those in QGCMapEngine.cpp
QList<QGeoMapType> mapList;
QHashIterator<QString, MapProvider*> i(getQGCMapEngine()->urlFactory()->getProviderTable());
setSupportedMapTypes({
#ifndef QGC_NO_GOOGLE_MAPS
QGCGEOMAPTYPE(QGeoMapType::StreetMap, "Google Street Map", "Google street map", false, false, UrlFactory::GoogleMap),
QGCGEOMAPTYPE(QGeoMapType::SatelliteMapDay, "Google Satellite Map", "Google satellite map", false, false, UrlFactory::GoogleSatellite),
QGCGEOMAPTYPE(QGeoMapType::TerrainMap, "Google Terrain Map", "Google terrain map", false, false, UrlFactory::GoogleTerrain),
QGCGEOMAPTYPE(QGeoMapType::HybridMap, "Google Hybrid Map", "Google hybrid map", false, false, UrlFactory::GoogleHybrid),
#endif
// Bing
QGCGEOMAPTYPE(QGeoMapType::StreetMap, "Bing Street Map", "Bing street map", false, false, UrlFactory::BingMap),
QGCGEOMAPTYPE(QGeoMapType::SatelliteMapDay, "Bing Satellite Map", "Bing satellite map", false, false, UrlFactory::BingSatellite),
QGCGEOMAPTYPE(QGeoMapType::HybridMap, "Bing Hybrid Map", "Bing hybrid map", false, false, UrlFactory::BingHybrid),
// Statkart
QGCGEOMAPTYPE(QGeoMapType::TerrainMap, "Statkart Terrain Map", "Statkart Terrain Map", false, false, UrlFactory::StatkartTopo),
// Eniro
QGCGEOMAPTYPE(QGeoMapType::TerrainMap, "Eniro Terrain Map", "Eniro Terrain Map", false, false, UrlFactory::EniroTopo),
// Esri
QGCGEOMAPTYPE(QGeoMapType::StreetMap, "Esri Street Map", "ArcGIS Online World Street Map", true, false, UrlFactory::EsriWorldStreet),
QGCGEOMAPTYPE(QGeoMapType::SatelliteMapDay, "Esri Satellite Map", "ArcGIS Online World Imagery", true, false, UrlFactory::EsriWorldSatellite),
QGCGEOMAPTYPE(QGeoMapType::TerrainMap, "Esri Terrain Map", "World Terrain Base", false, false, UrlFactory::EsriTerrain),
// VWorld
QGCGEOMAPTYPE(QGeoMapType::SatelliteMapDay, "VWorld Satellite Map", "VWorld Satellite Map", false, false, UrlFactory::VWorldSatellite),
QGCGEOMAPTYPE(QGeoMapType::StreetMap, "VWorld Street Map", "VWorld Street Map", false, false, UrlFactory::VWorldStreet),
/* See: https://wiki.openstreetmap.org/wiki/Tile_usage_policy
QGCGEOMAPTYPE(QGeoMapType::StreetMap, "Open Street Map", "Open Street map", false, false, UrlFactory::OpenStreetMap),
*/
while(i.hasNext()){
i.next();
// MapQuest
/*
QGCGEOMAPTYPE(QGeoMapType::StreetMap, "MapQuest Street Map", "MapQuest street map", false, false, UrlFactory::MapQuestMap),
QGCGEOMAPTYPE(QGeoMapType::SatelliteMapDay, "MapQuest Satellite Map", "MapQuest satellite map", false, false, UrlFactory::MapQuestSat),
*/
/*
* These are OK as you need your own token for accessing it. Out-of-the box, QGC does not even offer these unless you enter a proper Mapbox token.
*/
QGCGEOMAPTYPE(QGeoMapType::StreetMap, "Mapbox Street Map", "Mapbox Street Map", false, false, UrlFactory::MapboxStreets),
QGCGEOMAPTYPE(QGeoMapType::SatelliteMapDay, "Mapbox Satellite Map", "Mapbox Satellite Map", false, false, UrlFactory::MapboxSatellite),
QGCGEOMAPTYPE(QGeoMapType::CustomMap, "Mapbox High Contrast Map", "Mapbox High Contrast Map", false, false, UrlFactory::MapboxHighContrast),
QGCGEOMAPTYPE(QGeoMapType::CustomMap, "Mapbox Light Map", "Mapbox Light Map", false, false, UrlFactory::MapboxLight),
QGCGEOMAPTYPE(QGeoMapType::CustomMap, "Mapbox Dark Map", "Mapbox Dark Map", false, false, UrlFactory::MapboxDark),
QGCGEOMAPTYPE(QGeoMapType::HybridMap, "Mapbox Hybrid Map", "Mapbox Hybrid Map", false, false, UrlFactory::MapboxHybrid),
QGCGEOMAPTYPE(QGeoMapType::CustomMap, "Mapbox Wheat Paste Map", "Mapbox Wheat Paste Map", false, false, UrlFactory::MapboxWheatPaste),
QGCGEOMAPTYPE(QGeoMapType::StreetMap, "Mapbox Streets Basic Map", "Mapbox Streets Basic Map", false, false, UrlFactory::MapboxStreetsBasic),
QGCGEOMAPTYPE(QGeoMapType::CustomMap, "Mapbox Comic Map", "Mapbox Comic Map", false, false, UrlFactory::MapboxComic),
QGCGEOMAPTYPE(QGeoMapType::CustomMap, "Mapbox Outdoors Map", "Mapbox Outdoors Map", false, false, UrlFactory::MapboxOutdoors),
QGCGEOMAPTYPE(QGeoMapType::CycleMap, "Mapbox Run, Byke and Hike Map", "Mapbox Run, Byke and Hike Map", false, false, UrlFactory::MapboxRunBikeHike),
QGCGEOMAPTYPE(QGeoMapType::CustomMap, "Mapbox Pencil Map", "Mapbox Pencil Map", false, false, UrlFactory::MapboxPencil),
QGCGEOMAPTYPE(QGeoMapType::CustomMap, "Mapbox Pirates Map", "Mapbox Pirates Map", false, false, UrlFactory::MapboxPirates),
QGCGEOMAPTYPE(QGeoMapType::CustomMap, "Mapbox Emerald Map", "Mapbox Emerald Map", false, false, UrlFactory::MapboxEmerald),
});
if(!i.value()->_isElevationProvider()){
mapList.append(QGCGEOMAPTYPE(i.value()->getMapStyle(), i.key(), i.key(), false, false, getQGCMapEngine()->urlFactory()->getIdFromType(i.key()) ));
}
}
setSupportedMapTypes(mapList);
//-- Users (QML code) can define a different user agent
if (parameters.contains(QStringLiteral("useragent"))) {
......
......@@ -38,7 +38,7 @@ Item {
property Fact _mapboxFact: _settingsManager ? _settingsManager.appSettings.mapboxToken : null
property Fact _esriFact: _settingsManager ? _settingsManager.appSettings.esriToken : null
property string mapType: _fmSettings ? (_fmSettings.mapProvider.enumStringValue + " " + _fmSettings.mapType.enumStringValue) : ""
property string mapType: _fmSettings ? (_fmSettings.mapProvider.value + " " + _fmSettings.mapType.value) : ""
property bool isMapInteractive: false
property var savedCenter: undefined
property real savedZoom: 3
......@@ -93,10 +93,8 @@ Item {
function updateMap() {
for (var i = 0; i < _map.supportedMapTypes.length; i++) {
//console.log(_map.supportedMapTypes[i].name)
if (mapType === _map.supportedMapTypes[i].name) {
_map.activeMapType = _map.supportedMapTypes[i]
//console.log("Update Map:" + " " + _map.activeMapType)
handleChanges()
return
}
......@@ -105,7 +103,7 @@ Item {
function addNewSet() {
isMapInteractive = true
mapType = _fmSettings.mapProvider.enumStringValue + " " + _fmSettings.mapType.enumStringValue
mapType = _fmSettings.mapProvider.value + " " + _fmSettings.mapType.value
resetMapToDefaults()
handleChanges()
_map.visible = true
......@@ -465,7 +463,7 @@ Item {
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: !_defaultSet && mapType !== "Airmap Elevation Data"
visible: !_defaultSet && mapType !== "Airmap Elevation"
QGCLabel { text: qsTr("Zoom Levels:"); width: infoView._labelWidth; }
QGCLabel { text: offlineMapView._currentSelection ? (offlineMapView._currentSelection.minZoom + " - " + offlineMapView._currentSelection.maxZoom) : ""; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; }
}
......
......@@ -69,8 +69,6 @@ QGCMapEngineManager::setToolbox(QGCToolbox *toolbox)
void
QGCMapEngineManager::updateForCurrentView(double lon0, double lat0, double lon1, double lat1, int minZoom, int maxZoom, const QString& mapName)
{
UrlFactory::MapType mapType = QGCMapEngine::getTypeFromName(mapName);
_topleftLat = lat0;
_topleftLon = lon0;
_bottomRightLat = lat1;
......@@ -82,11 +80,11 @@ QGCMapEngineManager::updateForCurrentView(double lon0, double lat0, double lon1,
_elevationSet.clear();
for(int z = minZoom; z <= maxZoom; z++) {
QGCTileSet set = QGCMapEngine::getTileCount(z, lon0, lat0, lon1, lat1, mapType);
QGCTileSet set = QGCMapEngine::getTileCount(z, lon0, lat0, lon1, lat1, mapName);
_imageSet += set;
}
if (_fetchElevation) {
QGCTileSet set = QGCMapEngine::getTileCount(1, lon0, lat0, lon1, lat1, UrlFactory::AirmapElevation);
QGCTileSet set = QGCMapEngine::getTileCount(1, lon0, lat0, lon1, lat1, "Airmap Elevation");
_elevationSet += set;
}
......@@ -129,7 +127,7 @@ void
QGCMapEngineManager::_tileSetFetched(QGCCachedTileSet* tileSet)
{
//-- A blank (default) type means it uses various types and not just one
if(tileSet->type() == UrlFactory::Invalid) {
if(tileSet->type() == "Invalid") {
tileSet->setMapTypeStr("Various");
}
_tileSets.append(tileSet);
......@@ -152,7 +150,7 @@ QGCMapEngineManager::startDownload(const QString& name, const QString& mapType)
set->setMaxZoom(_maxZoom);
set->setTotalTileSize(_imageSet.tileSize);
set->setTotalTileCount(static_cast<quint32>(_imageSet.tileCount));
set->setType(QGCMapEngine::getTypeFromName(mapType));
set->setType(mapType);
QGCCreateTileSetTask* task = new QGCCreateTileSetTask(set);
//-- Create Tile Set (it will also create a list of tiles to download)
connect(task, &QGCCreateTileSetTask::tileSetSaved, this, &QGCMapEngineManager::_tileSetSaved);
......@@ -161,9 +159,9 @@ QGCMapEngineManager::startDownload(const QString& name, const QString& mapType)
} else {
qWarning() << "QGCMapEngineManager::startDownload() No Tiles to save";
}
if (mapType != "Airmap Elevation Data" && _fetchElevation) {
if (mapType != "Airmap Elevation" && _fetchElevation) {
QGCCachedTileSet* set = new QGCCachedTileSet(name + " Elevation");
set->setMapTypeStr("Airmap Elevation Data");
set->setMapTypeStr("Airmap Elevation");
set->setTopleftLat(_topleftLat);
set->setTopleftLon(_topleftLon);
set->setBottomRightLat(_bottomRightLat);
......@@ -172,7 +170,7 @@ QGCMapEngineManager::startDownload(const QString& name, const QString& mapType)
set->setMaxZoom(1);
set->setTotalTileSize(_elevationSet.tileSize);
set->setTotalTileCount(static_cast<quint32>(_elevationSet.tileCount));
set->setType(QGCMapEngine::getTypeFromName("Airmap Elevation Data"));
set->setType("Airmap Elevation");
QGCCreateTileSetTask* task = new QGCCreateTileSetTask(set);
//-- Create Tile Set (it will also create a list of tiles to download)
connect(task, &QGCCreateTileSetTask::tileSetSaved, this, &QGCMapEngineManager::_tileSetSaved);
......@@ -218,6 +216,28 @@ QGCMapEngineManager::mapList()
{
return getQGCMapEngine()->getMapNameList();
}
//-----------------------------------------------------------------------------
QStringList
QGCMapEngineManager::mapProviderList()
{
// Extract Provider name from MapName ( format : "Provider Type")
QStringList mapList = getQGCMapEngine()->getMapNameList();
mapList.replaceInStrings(QRegExp("^([^\\ ]*) (.*)$"),"\\1");
mapList.removeDuplicates();
return mapList;
}
//-----------------------------------------------------------------------------
QStringList
QGCMapEngineManager::mapTypeList(QString provider)
{
// Extract type name from MapName ( format : "Provider Type")
QStringList mapList = getQGCMapEngine()->getMapNameList();
mapList = mapList.filter(QRegularExpression(provider));
mapList.replaceInStrings(QRegExp("^([^\\ ]*) (.*)$"),"\\2");
mapList.removeDuplicates();
return mapList;
}
//-----------------------------------------------------------------------------
quint32
......
......@@ -43,6 +43,7 @@ public:
Q_PROPERTY(QString tileSizeStr READ tileSizeStr NOTIFY tileSizeChanged)
Q_PROPERTY(QmlObjectListModel* tileSets READ tileSets NOTIFY tileSetsChanged)
Q_PROPERTY(QStringList mapList READ mapList CONSTANT)
Q_PROPERTY(QStringList mapProviderList READ mapProviderList CONSTANT)
Q_PROPERTY(quint32 maxMemCache READ maxMemCache WRITE setMaxMemCache NOTIFY maxMemCacheChanged)
Q_PROPERTY(quint32 maxDiskCache READ maxDiskCache WRITE setMaxDiskCache NOTIFY maxDiskCacheChanged)
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
......@@ -77,6 +78,8 @@ public:
quint64 tileSize () { return _imageSet.tileSize + _elevationSet.tileSize; }
QString tileSizeStr ();
QStringList mapList ();
QStringList mapProviderList ();
Q_INVOKABLE QStringList mapTypeList (QString provider);
QmlObjectListModel* tileSets () { return &_tileSets; }
quint32 maxMemCache ();
quint32 maxDiskCache ();
......
......@@ -2,17 +2,12 @@
{
"name": "mapProvider",
"shortDescription": "Currently selected map provider for flight maps",
"type": "uint32",
"enumStrings": "Bing,Google,Statkart,Mapbox,Esri,Eniro,VWorld",
"enumValues": "0,1,2,3,4,5,6",
"defaultValue": 0
"type": "string"
},
{
"name": "mapType",
"shortDescription": "Currently selected map type for flight maps",
"type": "uint32",
"enumStrings": "Street Map,Satellite Map,Hybrid Map,Terrain Map",
"enumValues": "0,1,2,3",
"defaultValue": 2
"type": "string",
"default": ""
}
]
......@@ -19,105 +19,7 @@
DECLARE_SETTINGGROUP(FlightMap, "FlightMap")
{
qmlRegisterUncreatableType<FlightMapSettings>("QGroundControl.SettingsManager", 1, 0, "FlightMapSettings", "Reference only");
// Save the original version since we modify based on map provider
_savedMapTypeStrings = _nameToMetaDataMap[mapTypeName]->enumStrings();
_savedMapTypeValues = _nameToMetaDataMap[mapTypeName]->enumValues();
#ifdef QGC_NO_GOOGLE_MAPS
//-- Remove Google
_excludeProvider(mapProviderGoogle);
#endif
if(qgcApp()->toolbox()->settingsManager()->appSettings()->mapboxToken()->rawValue().toString().isEmpty()) {
_excludeProvider(mapProviderMapbox);
}
if(qgcApp()->toolbox()->settingsManager()->appSettings()->esriToken()->rawValue().toString().isEmpty()) {
_excludeProvider(mapProviderEsri);
}
_newMapProvider(mapProvider()->rawValue());
}
DECLARE_SETTINGSFACT(FlightMapSettings, mapProvider)
DECLARE_SETTINGSFACT(FlightMapSettings, mapType)
DECLARE_SETTINGSFACT_NO_FUNC(FlightMapSettings, mapProvider)
{
if (!_mapProviderFact) {
_mapProviderFact = _createSettingsFact(mapProviderName);
connect(_mapProviderFact, &Fact::rawValueChanged, this, &FlightMapSettings::_newMapProvider);
}
return _mapProviderFact;
}
void FlightMapSettings::_excludeProvider(MapProvider_t provider)
{
FactMetaData* metaData = _nameToMetaDataMap[mapProviderName];
QVariantList enumValues = metaData->enumValues();
QStringList enumStrings = metaData->enumStrings();
_removeEnumValue(provider, enumStrings, enumValues);
metaData->setEnumInfo(enumStrings, enumValues);
}
void FlightMapSettings::_removeEnumValue(int value, QStringList& enumStrings, QVariantList& enumValues)
{
bool found = false;
int removeIndex;
for (removeIndex=0; removeIndex<enumValues.count(); removeIndex++) {
if (enumValues[removeIndex].toInt() == value) {
found = true;
break;
}
}
if (found) {
enumValues.removeAt(removeIndex);
enumStrings.removeAt(removeIndex);
}
}
void FlightMapSettings::_newMapProvider(QVariant value)
{
FactMetaData* metaData = _nameToMetaDataMap[mapTypeName];
QStringList enumStrings = _savedMapTypeStrings;
QVariantList enumValues = _savedMapTypeValues;
switch (value.toInt()) {
case mapProviderBing:
_removeEnumValue(mapTypeTerrain, enumStrings, enumValues);
break;
case mapProviderGoogle:
break;
case mapProviderStarkart:
_removeEnumValue(mapTypeStreet, enumStrings, enumValues);
_removeEnumValue(mapTypeSatellite, enumStrings, enumValues);
_removeEnumValue(mapTypeHybrid, enumStrings, enumValues);
break;
case mapProviderEniro:
_removeEnumValue(mapTypeStreet, enumStrings, enumValues);
_removeEnumValue(mapTypeSatellite, enumStrings, enumValues);
_removeEnumValue(mapTypeHybrid, enumStrings, enumValues);
break;
case mapProviderEsri:
_removeEnumValue(mapTypeHybrid, enumStrings, enumValues);
break;
case mapProviderVWorld:
_removeEnumValue(mapTypeHybrid, enumStrings, enumValues);
_removeEnumValue(mapTypeTerrain, enumStrings, enumValues);
}
metaData->setEnumInfo(enumStrings, enumValues);
emit mapTypeChanged();
// Check that map type is still valid for this new map provider
bool found = false;
int currentMapType = mapType()->rawValue().toInt();
for (int i=0; i<enumValues.count(); i++) {
if (currentMapType == enumValues[i].toInt()) {
found = true;
break;
}
}
if (!found) {
mapType()->setRawValue(0);
}
}
......@@ -18,39 +18,9 @@ class FlightMapSettings : public SettingsGroup
public:
FlightMapSettings(QObject* parent = nullptr);
// This enum must match the json meta data
typedef enum {
mapProviderBing,
mapProviderGoogle,
mapProviderStarkart,
mapProviderMapbox,
mapProviderEsri,
mapProviderEniro,
mapProviderVWorld
} MapProvider_t;
// This enum must match the json meta data
typedef enum {
mapTypeStreet,
mapTypeSatellite,
mapTypeHybrid,
mapTypeTerrain
} MapType_t;
DEFINE_SETTING_NAME_GROUP()
DEFINE_SETTINGFACT(mapProvider)
DEFINE_SETTINGFACT(mapType)
signals:
void mapTypeChanged(void);
private slots:
void _newMapProvider(QVariant value);
private:
void _removeEnumValue(int value, QStringList& enumStrings, QVariantList& enumValues);
void _excludeProvider(MapProvider_t provider);
QStringList _savedMapTypeStrings;
QVariantList _savedMapTypeValues;
};
......@@ -426,13 +426,13 @@ bool TerrainTileManager::_getAltitudesForCoordinates(const QList<QGeoCoordinate>
}
} else {
if (_state != State::Downloading) {
QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL(UrlFactory::AirmapElevation, QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1), QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1), 1, &_networkManager);
QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL("Airmap Elevation", getQGCMapEngine()->urlFactory()->long2tileX("Airmap Elevation",coordinate.longitude(), 1), getQGCMapEngine()->urlFactory()->lat2tileY("Airmap Elevation", coordinate.latitude(), 1), 1, &_networkManager);
qCDebug(TerrainQueryLog) << "TerrainTileManager::_getAltitudesForCoordinates query from database" << request.url();
QGeoTileSpec spec;
spec.setX(QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1));
spec.setY(QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1));
spec.setX(getQGCMapEngine()->urlFactory()->long2tileX("Airmap Elevation", coordinate.longitude(), 1));
spec.setY(getQGCMapEngine()->urlFactory()->lat2tileY("Airmap Elevation", coordinate.latitude(), 1));
spec.setZoom(1);
spec.setMapId(UrlFactory::AirmapElevation);
spec.setMapId(getQGCMapEngine()->urlFactory()->getIdFromType("Airmap Elevation"));
QGeoTiledMapReplyQGC* reply = new QGeoTiledMapReplyQGC(&_networkManager, request, spec);
connect(reply, &QGeoTiledMapReplyQGC::terrainDone, this, &TerrainTileManager::_terrainDone);
_state = State::Downloading;
......@@ -473,7 +473,7 @@ void TerrainTileManager::_terrainDone(QByteArray responseBytes, QNetworkReply::N
// remove from download queue
QGeoTileSpec spec = reply->tileSpec();
QString hash = QGCMapEngine::getTileHash(UrlFactory::AirmapElevation, spec.x(), spec.y(), spec.zoom());
QString hash = QGCMapEngine::getTileHash("Airmap Elevation", spec.x(), spec.y(), spec.zoom());
// handle potential errors
if (error != QNetworkReply::NoError) {
......@@ -539,7 +539,11 @@ void TerrainTileManager::_terrainDone(QByteArray responseBytes, QNetworkReply::N
QString TerrainTileManager::_getTileHash(const QGeoCoordinate& coordinate)
{
QString ret = QGCMapEngine::getTileHash(UrlFactory::AirmapElevation, QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1), QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1), 1);
QString ret = QGCMapEngine::getTileHash(
"Airmap Elevation",
getQGCMapEngine()->urlFactory()->long2tileX("Airmap Elevation", coordinate.longitude(), 1),
getQGCMapEngine()->urlFactory()->lat2tileY("Airmap Elevation", coordinate.latitude(), 1),
1);
qCDebug(TerrainQueryVerboseLog) << "Computing unique tile hash for " << coordinate << ret;
return ret;
......
diff --git a/libs/mavlink/include/mavlink/v2.0 b/libs/mavlink/include/mavlink/v2.0
--- a/libs/mavlink/include/mavlink/v2.0
+++ b/libs/mavlink/include/mavlink/v2.0
@@ -1 +1 @@
-Subproject commit 68869da6575d4ca61b92e9081b7c81587f157ed6
+Subproject commit 68869da6575d4ca61b92e9081b7c81587f157ed6-dirty
diff --git a/src/Terrain/TerrainQueryManager.cc b/src/Terrain/TerrainQueryManager.cc
index 59ec2d4..c38a870 100644
--- a/src/Terrain/TerrainQueryManager.cc
+++ b/src/Terrain/TerrainQueryManager.cc
@@ -3,17 +3,20 @@
TerrainQueryManager::TerrainQueryManager(QObject* parent)
: TerrainQueryInterface(parent)
{
- _providerAirMap = new TerrainOfflineAirMapQuery(parent);
+ connect(&_providerAirMap, &TerrainQueryInterface::coordinateHeightsReceived, this, &TerrainQueryInterface::coordinateHeightsReceived);
+ connect(&_providerAirMap, &TerrainQueryInterface::pathHeightsReceived, this, &TerrainQueryInterface::pathHeightsReceived);
+ connect(&_providerAirMap, &TerrainQueryInterface::carpetHeightsReceived, this, &TerrainQueryInterface::carpetHeightsReceived);
}
void TerrainQueryManager::requestCoordinateHeights(const QList<QGeoCoordinate>& coordinates){
- _providerAirMap->requestCoordinateHeights(coordinates);
+ _providerAirMap.requestCoordinateHeights(coordinates);
}
void TerrainQueryManager::requestPathHeights(const QGeoCoordinate& fromCoord, const QGeoCoordinate& toCoord){
- _providerAirMap->requestPathHeights(fromCoord,toCoord);
+ _providerAirMap.requestPathHeights(fromCoord,toCoord);
}
void TerrainQueryManager::requestCarpetHeights(const QGeoCoordinate& swCoord, const QGeoCoordinate& neCoord, bool statsOnly){
- _providerAirMap->requestCarpetHeights(swCoord,neCoord,statsOnly);
+ _providerAirMap.requestCarpetHeights(swCoord,neCoord,statsOnly);
}
+
diff --git a/src/Terrain/TerrainQueryManager.h b/src/Terrain/TerrainQueryManager.h
index 2921679..9b4494c 100644
--- a/src/Terrain/TerrainQueryManager.h
+++ b/src/Terrain/TerrainQueryManager.h
@@ -27,12 +27,12 @@ public:
/// @param neCoord North-East bound of rectangular area to query
/// @param statsOnly true: Return only stats, no carpet data
void requestCarpetHeights(const QGeoCoordinate& swCoord, const QGeoCoordinate& neCoord, bool statsOnly);
-
+
signals:
void coordinateHeightsReceived(bool success, QList<double> heights);
void pathHeightsReceived(bool success, double latStep, double lonStep, const QList<double>& heights);
void carpetHeightsReceived(bool success, double minHeight, double maxHeight, const QList<QList<double>>& carpet);
private:
- TerrainOfflineAirMapQuery * _providerAirMap;
+ TerrainOfflineAirMapQuery _providerAirMap;
};
......@@ -38,8 +38,8 @@ Rectangle {
property real _labelWidth: ScreenTools.defaultFontPixelWidth * 20
property real _comboFieldWidth: ScreenTools.defaultFontPixelWidth * 28
property real _valueFieldWidth: ScreenTools.defaultFontPixelWidth * 10
property Fact _mapProvider: QGroundControl.settingsManager.flightMapSettings.mapProvider
property Fact _mapType: QGroundControl.settingsManager.flightMapSettings.mapType
property string _mapProvider: QGroundControl.settingsManager.flightMapSettings.mapProvider.value
property string _mapType: QGroundControl.settingsManager.flightMapSettings.mapType.value
property Fact _followTarget: QGroundControl.settingsManager.appSettings.followTarget
property real _panelWidth: _root.width * _internalWidthRatio
property real _margins: ScreenTools.defaultFontPixelWidth
......@@ -160,30 +160,37 @@ Rectangle {
QGCLabel {
text: qsTr("Map Provider")
width: _labelWidth
visible: _mapProvider.visible
}
FactComboBox {
QGCComboBox {
id: mapCombo
model: QGroundControl.mapEngineManager.mapProviderList
Layout.preferredWidth: _comboFieldWidth
fact: _mapProvider
indexModel: false
visible: _mapProvider.visible
onActivated: {
_mapProvider = textAt(index)
QGroundControl.settingsManager.flightMapSettings.mapProvider.value=textAt(index)
QGroundControl.settingsManager.flightMapSettings.mapType.value=QGroundControl.mapEngineManager.mapTypeList(textAt(index))[0]
}
Component.onCompleted: {
var index = mapCombo.find(_mapProvider)
mapCombo.currentIndex = index
}
}
QGCLabel {
text: qsTr("Map Type")
visible: _mapType && _mapType.visible
width: _labelWidth
}
FactComboBox {
id: mapTypes
QGCComboBox {
id: mapTypeCombo
model: QGroundControl.mapEngineManager.mapTypeList(_mapProvider)
Layout.preferredWidth: _comboFieldWidth
fact: _mapType
indexModel: false
visible: _mapType && _mapType.visible
Connections {
target: QGroundControl.settingsManager.flightMapSettings
onMapTypeChanged: {
mapTypes.model = _mapType.enumStrings
}
onActivated: {
_mapType = textAt(index)
QGroundControl.settingsManager.flightMapSettings.mapType.value=textAt(index)
}
Component.onCompleted: {
var index = mapTypeCombo.find(_mapType)
mapTypeCombo.currentIndex = index
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment