diff --git a/src/Viewer3D/OsmParser.cc b/src/Viewer3D/OsmParser.cc index c262c36977b..41edcc6598c 100644 --- a/src/Viewer3D/OsmParser.cc +++ b/src/Viewer3D/OsmParser.cc @@ -1,6 +1,5 @@ #include "OsmParser.h" #include "earcut.hpp" -#include "Viewer3DUtils.h" #include "QGCApplication.h" #include "SettingsManager.h" diff --git a/src/Viewer3D/Viewer3DQml/Models3D/Viewer3DVehicleItems.qml b/src/Viewer3D/Viewer3DQml/Models3D/Viewer3DVehicleItems.qml index 8f3adcfc55e..823a1e8988b 100644 --- a/src/Viewer3D/Viewer3DQml/Models3D/Viewer3DVehicleItems.qml +++ b/src/Viewer3D/Viewer3DQml/Models3D/Viewer3DVehicleItems.qml @@ -34,6 +34,7 @@ Node { 20, // Return To Launch 22, //Takeoff 195, // ROI + 201, // ROI DEPRECATED ]; // based on MavCmdInfoCommon.json file return acceptableCmdIds.includes(missionItem.command); } @@ -52,6 +53,10 @@ Node { return qsTr("L"); } + if(missionItem.isTakeoffItem){ + return qsTr("T"); //Takeoff + } + if(missionItem.specifiesCoordinate){ switch(missionItem.command){ case 16: @@ -60,6 +65,8 @@ Node { return qsTr("T"); //Takeoff case 195: return qsTr("R"); //ROI + case 201: + return qsTr("R"); //ROI DEPRECATED } } return qsTr("null") diff --git a/src/Viewer3D/Viewer3DQmlBackend.cc b/src/Viewer3D/Viewer3DQmlBackend.cc index e0f0fd2a685..7089f79ba60 100644 --- a/src/Viewer3D/Viewer3DQmlBackend.cc +++ b/src/Viewer3D/Viewer3DQmlBackend.cc @@ -36,6 +36,7 @@ void Viewer3DQmlBackend::_activeVehicleChangedEvent(Vehicle *vehicle) _gpsRefSet = GPS_REF_NOT_SET; } }else{ + _activeVehicleCoordinateChanged(_activeVehicle->coordinate()); connect(_activeVehicle, &Vehicle::coordinateChanged, this, &Viewer3DQmlBackend::_activeVehicleCoordinateChanged); } } diff --git a/src/Viewer3D/Viewer3DTerrainTexture.cc b/src/Viewer3D/Viewer3DTerrainTexture.cc index b174c271263..d7200f6af24 100644 --- a/src/Viewer3D/Viewer3DTerrainTexture.cc +++ b/src/Viewer3D/Viewer3DTerrainTexture.cc @@ -13,7 +13,7 @@ Viewer3DTerrainTexture::Viewer3DTerrainTexture() setTextureGeometryDone(false); setTextureLoaded(false); - setTextureDownloadProgress(0.0); + setTextureDownloadProgress(100.0); // connect(_flightMapSettings->mapProvider(), &Fact::rawValueChanged, this, &Viewer3DTerrainTexture::mapTypeChangedEvent); connect(_flightMapSettings->mapType(), &Fact::rawValueChanged, this, &Viewer3DTerrainTexture::mapTypeChangedEvent); @@ -34,13 +34,11 @@ void Viewer3DTerrainTexture::loadTexture() if(!_terrainTileLoader){ _terrainTileLoader = new MapTileQuery(this); connect(_terrainTileLoader, &MapTileQuery::loadingMapCompleted, this, &Viewer3DTerrainTexture::updateTexture); + connect(_terrainTileLoader, &MapTileQuery::textureGeometryReady, this, &Viewer3DTerrainTexture::setTextureGeometry); } - MapTileQuery::TileStatistics_t tileInfo = _terrainTileLoader->adaptiveMapTilesLoader(_mapType, _mapId, - _osmParser->getMapBoundingBoxCoordinate().first, - _osmParser->getMapBoundingBoxCoordinate().second); - setRoiMinCoordinate(tileInfo.coordinateMin); - setRoiMaxCoordinate(tileInfo.coordinateMax); - setTileCount(tileInfo.tileCounts); + _terrainTileLoader->adaptiveMapTilesLoader(_mapType, _mapId, + _osmParser->getMapBoundingBoxCoordinate().first, + _osmParser->getMapBoundingBoxCoordinate().second); connect(_terrainTileLoader, &MapTileQuery::mapTileDownloaded, this, &Viewer3DTerrainTexture::setTextureDownloadProgress); } } @@ -172,3 +170,10 @@ void Viewer3DTerrainTexture::setTextureDownloadProgress(float newTextureDownload _textureDownloadProgress = newTextureDownloadProgress; emit textureDownloadProgressChanged(); } + +void Viewer3DTerrainTexture::setTextureGeometry(MapTileQuery::TileStatistics_t tileInfo) +{ + setRoiMinCoordinate(tileInfo.coordinateMin); + setRoiMaxCoordinate(tileInfo.coordinateMax); + setTileCount(tileInfo.tileCounts); +} diff --git a/src/Viewer3D/Viewer3DTerrainTexture.h b/src/Viewer3D/Viewer3DTerrainTexture.h index a75bf2f6a04..b63a5a453fc 100644 --- a/src/Viewer3D/Viewer3DTerrainTexture.h +++ b/src/Viewer3D/Viewer3DTerrainTexture.h @@ -54,6 +54,7 @@ class Viewer3DTerrainTexture : public QQuick3DTextureData float textureDownloadProgress() const; void setTextureDownloadProgress(float newTextureDownloadProgress); + void setTextureGeometry(MapTileQuery::TileStatistics_t tileInfo); private: diff --git a/src/Viewer3D/Viewer3DTileQuery.cc b/src/Viewer3D/Viewer3DTileQuery.cc index 61dafe3b458..2e65214d484 100644 --- a/src/Viewer3D/Viewer3DTileQuery.cc +++ b/src/Viewer3D/Viewer3DTileQuery.cc @@ -6,7 +6,7 @@ #define DEG_TO_RAD PI/180.0f #define RAD_TO_DEG 180.0f/PI #define MAX_TILE_COUNTS 200 -#define MAX_ZOOM_LEVEL 20 +#define MAX_ZOOM_LEVEL 23 enum RequestStat{ @@ -37,6 +37,7 @@ void MapTileQuery::loadMapTiles(int zoomLevel, QPoint tileMinIndex, QPoint tileM Viewer3DTileReply* _reply = new Viewer3DTileReply(zoomLevel, x, y, _mapId, this); connect(_reply, &Viewer3DTileReply::tileDone, this, &MapTileQuery::tileDone); connect(_reply, &Viewer3DTileReply::tileGiveUp, this, &MapTileQuery::tileGiveUp); + connect(_reply, &Viewer3DTileReply::tileEmpty, this, &MapTileQuery::tileEmpty); } } totalTilesCount = _mapToBeLoaded.tileList.size(); @@ -79,17 +80,19 @@ MapTileQuery::TileStatistics_t MapTileQuery::findAndLoadMapTiles(int zoomLevel, return _output; } -MapTileQuery::TileStatistics_t MapTileQuery::adaptiveMapTilesLoader(QString mapType, int mapId, QGeoCoordinate coordinate_1, QGeoCoordinate coordinate_2) +void MapTileQuery::adaptiveMapTilesLoader(QString mapType, int mapId, QGeoCoordinate coordinate_1, QGeoCoordinate coordinate_2) { - int zoomLevel; _mapId = mapId; _mapType = mapType; - for(zoomLevel=MAX_ZOOM_LEVEL; zoomLevel>0; zoomLevel--){ - if(maxTileCount(zoomLevel, coordinate_1, coordinate_2) < MAX_TILE_COUNTS){ + for(_zoomLevel=MAX_ZOOM_LEVEL; _zoomLevel>0; _zoomLevel--){ + if(maxTileCount(_zoomLevel, coordinate_1, coordinate_2) < MAX_TILE_COUNTS){ break; } } - return findAndLoadMapTiles(zoomLevel, coordinate_1, coordinate_2); + + _textureCoordinateMin = coordinate_1; + _textureCoordinateMax = coordinate_2; + emit textureGeometryReady(findAndLoadMapTiles(_zoomLevel, coordinate_1, coordinate_2)); } int MapTileQuery::maxTileCount(int zoomLevel, QGeoCoordinate coordinateMin, QGeoCoordinate coordinateMax) @@ -191,6 +194,7 @@ void MapTileQuery::tileDone(Viewer3DTileReply::tileInfo_t _tileData) } disconnect(reply, &Viewer3DTileReply::tileDone, this, &MapTileQuery::tileDone); disconnect(reply, &Viewer3DTileReply::tileGiveUp, this, &MapTileQuery::tileGiveUp); + disconnect(reply, &Viewer3DTileReply::tileEmpty, this, &MapTileQuery::tileEmpty); reply->deleteLater(); } @@ -199,7 +203,20 @@ void MapTileQuery::tileGiveUp(Viewer3DTileReply::tileInfo_t _tileData) Viewer3DTileReply* reply = qobject_cast(QObject::sender()); disconnect(reply, &Viewer3DTileReply::tileDone, this, &MapTileQuery::tileDone); disconnect(reply, &Viewer3DTileReply::tileGiveUp, this, &MapTileQuery::tileGiveUp); + disconnect(reply, &Viewer3DTileReply::tileEmpty, this, &MapTileQuery::tileEmpty); + reply->deleteLater(); +} + +void MapTileQuery::tileEmpty(Viewer3DTileReply::tileInfo_t _tileData) +{ + Viewer3DTileReply* reply = qobject_cast(QObject::sender()); + disconnect(reply, &Viewer3DTileReply::tileDone, this, &MapTileQuery::tileDone); + disconnect(reply, &Viewer3DTileReply::tileEmpty, this, &MapTileQuery::tileEmpty); reply->deleteLater(); + if(_tileData.zoomLevel > 0 && _tileData.zoomLevel == _zoomLevel){ + _zoomLevel -= 1; + emit textureGeometryReady(findAndLoadMapTiles(_zoomLevel, _textureCoordinateMin, _textureCoordinateMax)); + } } QString MapTileQuery::getTileKey(int mapId, int x, int y, int zoomLevel) diff --git a/src/Viewer3D/Viewer3DTileQuery.h b/src/Viewer3D/Viewer3DTileQuery.h index 5c566c4cc0e..2e35e277727 100644 --- a/src/Viewer3D/Viewer3DTileQuery.h +++ b/src/Viewer3D/Viewer3DTileQuery.h @@ -104,7 +104,7 @@ class MapTileQuery : public QObject Q_OBJECT public: explicit MapTileQuery(QObject *parent = nullptr); - TileStatistics_t adaptiveMapTilesLoader(QString mapType, int mapId, QGeoCoordinate coordinate_1, QGeoCoordinate coordinate_2); + void adaptiveMapTilesLoader(QString mapType, int mapId, QGeoCoordinate coordinate_1, QGeoCoordinate coordinate_2); int maxTileCount(int zoomLevel, QGeoCoordinate coordinateMin, QGeoCoordinate coordinateMax); QByteArray getMapData(){ return _mapToBeLoaded.getMapData();} QSize getMapSize(){ return QSize(_mapToBeLoaded.mapWidth, _mapToBeLoaded.mapHeight);} @@ -114,8 +114,9 @@ class MapTileQuery : public QObject MapTileContainer_t _mapToBeLoaded; int totalTilesCount, downloadedTilesCount; int _mapId; + int _zoomLevel; QString _mapType; - + QGeoCoordinate _textureCoordinateMin, _textureCoordinateMax; void loadMapTiles(int zoomLevel, QPoint tileMinIndex, QPoint tileMaxIndex); TileStatistics_t findAndLoadMapTiles(int zoomLevel, QGeoCoordinate coordinate_1, QGeoCoordinate coordinate_2); @@ -126,12 +127,14 @@ class MapTileQuery : public QObject QGeoCoordinate pixelXYToLatLong(QPoint pixel, int zoomLevel); void tileDone(Viewer3DTileReply::tileInfo_t _tileData); void tileGiveUp(Viewer3DTileReply::tileInfo_t _tileData); + void tileEmpty(Viewer3DTileReply::tileInfo_t _tileData); void httpReadyRead(); QString getTileKey(int mapId, int x, int y, int zoomLevel); signals: void loadingMapCompleted(); void mapTileDownloaded(float progress); + void textureGeometryReady(TileStatistics_t tileInfo); }; #endif // VIEWER3DTILEQUERY_H diff --git a/src/Viewer3D/Viewer3DTileReply.cc b/src/Viewer3D/Viewer3DTileReply.cc index 4cce742914c..827c55756ef 100644 --- a/src/Viewer3D/Viewer3DTileReply.cc +++ b/src/Viewer3D/Viewer3DTileReply.cc @@ -1,11 +1,20 @@ #include "Viewer3DTileReply.h" #include "QGCMapEngine.h" +#include +QByteArray Viewer3DTileReply::_bingNoTileImage; Viewer3DTileReply::Viewer3DTileReply(int zoomLevel, int tileX, int tileY, int mapId, QObject *parent) : QObject{parent} { + if (_bingNoTileImage.length() == 0) { + QFile file(":/res/BingNoTileBytes.dat"); + file.open(QFile::ReadOnly); + _bingNoTileImage = file.readAll(); + file.close(); + } + _timeoutCounter = 0; _timeoutTimer = new QTimer(this); _networkManager = new QNetworkAccessManager(this); @@ -41,11 +50,24 @@ void Viewer3DTileReply::prepareDownload() void Viewer3DTileReply::requestFinished() { _tile.data = _reply->readAll(); + UrlFactory* urlFactory = getQGCMapEngine()->urlFactory(); + MapProvider* mapProvider = urlFactory->getMapProviderFromQtMapId(_tile.mapId); // disconnect(_networkManager, &QNetworkAccessManager::finished, this, &Viewer3DTileReply::requestFinished); _timeoutTimer->stop(); disconnect(_reply, &QNetworkReply::finished, this, &Viewer3DTileReply::requestFinished); disconnect(_reply, &QNetworkReply::errorOccurred, this, &Viewer3DTileReply::requestError); disconnect(_timeoutTimer, &QTimer::timeout, this, &Viewer3DTileReply::timeoutTimerEvent); + + if(mapProvider && mapProvider->_isBingProvider() && _tile.data.size() && _tile.data == _bingNoTileImage){ + // Bing doesn't return an error if you request a tile above supported zoom level + // It instead returns an image of a missing tile graphic. We need to detect that + // and error out so 3D View will deal with zooming correctly even if it doesn't have the tile. + // This allows us to zoom up to level 23 even though the tiles don't actually exist + // so we clear the data to imdicate it is not a valid tile + _tile.data.clear(); + emit tileEmpty(_tile); + return; + } emit tileDone(_tile); } @@ -59,15 +81,15 @@ void Viewer3DTileReply::requestError() void Viewer3DTileReply::timeoutTimerEvent() { if(_timeoutCounter > 5){ - _timeoutCounter = 0; - _networkManager->setTransferTimeout(14000); - _timeoutTimer->stop(); - _timeoutTimer->start(15000); - // disconnect(_reply, &QNetworkReply::finished, this, &Viewer3DTileReply::requestFinished); - // disconnect(_reply, &QNetworkReply::errorOccurred, this, &Viewer3DTileReply::requestError); - // disconnect(_timeoutTimer, &QTimer::timeout, this, &Viewer3DTileReply::timeoutTimerEvent); - // emit tileGiveUp(_tile); + // _timeoutCounter = 0; + // _networkManager->setTransferTimeout(14000); // _timeoutTimer->stop(); + // _timeoutTimer->start(15000); + disconnect(_reply, &QNetworkReply::finished, this, &Viewer3DTileReply::requestFinished); + disconnect(_reply, &QNetworkReply::errorOccurred, this, &Viewer3DTileReply::requestError); + disconnect(_timeoutTimer, &QTimer::timeout, this, &Viewer3DTileReply::timeoutTimerEvent); + emit tileGiveUp(_tile); + _timeoutTimer->stop(); }else if(_tile.data.isEmpty()){ emit tileError(_tile); prepareDownload(); diff --git a/src/Viewer3D/Viewer3DTileReply.h b/src/Viewer3D/Viewer3DTileReply.h index 14fc25d6bf8..7b2d4c224b4 100644 --- a/src/Viewer3D/Viewer3DTileReply.h +++ b/src/Viewer3D/Viewer3DTileReply.h @@ -32,6 +32,7 @@ class Viewer3DTileReply : public QObject QTimer* _timeoutTimer; int _mapId; int _timeoutCounter; + static QByteArray _bingNoTileImage; void prepareDownload(); void requestFinished(); @@ -40,6 +41,7 @@ class Viewer3DTileReply : public QObject signals: void tileDone(tileInfo_t); + void tileEmpty(tileInfo_t); void tileError(tileInfo_t); void tileGiveUp(tileInfo_t); };