diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 0d088431cd861b850d31e5e0221b07db0808e00b..a6ef69da848fa895df3de4b45d98c5e9f37bf00d 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -573,6 +573,7 @@ HEADERS += \ src/QmlControls/QGCImageProvider.h \ src/QmlControls/QGroundControlQmlGlobal.h \ src/QmlControls/QmlObjectListModel.h \ + src/QmlControls/QGCGeoBoundingCube.h \ src/QmlControls/RCChannelMonitorController.h \ src/QmlControls/ScreenToolsController.h \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \ @@ -766,6 +767,7 @@ SOURCES += \ src/QmlControls/QGCImageProvider.cc \ src/QmlControls/QGroundControlQmlGlobal.cc \ src/QmlControls/QmlObjectListModel.cc \ + src/QmlControls/QGCGeoBoundingCube.cc \ src/QmlControls/RCChannelMonitorController.cc \ src/QmlControls/ScreenToolsController.cc \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \ diff --git a/src/Airmap/AirMapAdvisoryManager.cc b/src/Airmap/AirMapAdvisoryManager.cc index c2f6e59ea62a858caa47091f8363943f724c46b1..40d09c98262897856254044b9041f6fcb411244f 100644 --- a/src/Airmap/AirMapAdvisoryManager.cc +++ b/src/Airmap/AirMapAdvisoryManager.cc @@ -22,7 +22,6 @@ using namespace airmap; //----------------------------------------------------------------------------- AirMapAdvisory::AirMapAdvisory(QObject* parent) : AirspaceAdvisory(parent) - , _radius(0.0) { } @@ -30,19 +29,17 @@ AirMapAdvisory::AirMapAdvisory(QObject* parent) AirMapAdvisoryManager::AirMapAdvisoryManager(AirMapSharedState& shared, QObject *parent) : AirspaceAdvisoryProvider(parent) , _valid(false) - , _lastRadius(0.0) , _shared(shared) { } //----------------------------------------------------------------------------- void -AirMapAdvisoryManager::setROI(const QGeoCoordinate& center, double radiusMeters) +AirMapAdvisoryManager::setROI(const QGCGeoBoundingCube& roi) { //-- If first time or we've moved more than ADVISORY_UPDATE_DISTANCE, ask for updates. - if(!_lastRoiCenter.isValid() || _lastRoiCenter.distanceTo(center) > ADVISORY_UPDATE_DISTANCE || _lastRadius != radiusMeters) { - _lastRadius = radiusMeters; - _lastRoiCenter = center; + if(!_lastROI.isValid() || _lastROI.pointNW.distanceTo(roi.pointNW) > ADVISORY_UPDATE_DISTANCE || _lastROI.pointSE.distanceTo(roi.pointSE) > ADVISORY_UPDATE_DISTANCE) { + _lastROI = roi; _requestAdvisories(); } } @@ -71,11 +68,13 @@ AirMapAdvisoryManager::_requestAdvisories() _valid = false; _advisories.clearAndDeleteContents(); Status::GetStatus::Parameters params; - params.longitude = _lastRoiCenter.longitude(); - params.latitude = _lastRoiCenter.latitude(); + params.longitude = _lastROI.center().longitude(); + params.latitude = _lastROI.center().latitude(); params.types = Airspace::Type::all; params.weather = false; - params.buffer = _lastRadius; + double diagonal = _lastROI.pointNW.distanceTo(_lastROI.pointSE); + params.buffer = fmax(fmin(diagonal, 10000.0), 500.0); + params.flight_date_time = Clock::universal_time(); std::weak_ptr isAlive(_instance); _shared.client()->status().get_status_by_point(params, [this, isAlive](const Status::GetStatus::Result& result) { if (!isAlive.lock()) return; diff --git a/src/Airmap/AirMapAdvisoryManager.h b/src/Airmap/AirMapAdvisoryManager.h index 4e668f4fd7c92776f7ea3591fb51284ab451555c..38fcb0163fbc8b23c643561ffd22b08473aed5f8 100644 --- a/src/Airmap/AirMapAdvisoryManager.h +++ b/src/Airmap/AirMapAdvisoryManager.h @@ -16,7 +16,7 @@ #include "AirspaceAdvisoryProvider.h" #include "AirMapSharedState.h" -#include +#include "QGCGeoBoundingCube.h" #include "airmap/status.h" @@ -53,20 +53,19 @@ class AirMapAdvisoryManager : public AirspaceAdvisoryProvider, public LifetimeCh { Q_OBJECT public: - AirMapAdvisoryManager (AirMapSharedState &shared, QObject *parent = nullptr); - bool valid () override { return _valid; } - AdvisoryColor airspaceColor () override { return _airspaceColor; } - QmlObjectListModel* advisories () override { return &_advisories; } - void setROI (const QGeoCoordinate& center, double radiusMeters) override; + AirMapAdvisoryManager (AirMapSharedState &shared, QObject *parent = nullptr); + bool valid () override { return _valid; } + AdvisoryColor airspaceColor () override { return _airspaceColor; } + QmlObjectListModel* advisories () override { return &_advisories; } + void setROI (const QGCGeoBoundingCube& roi) override; signals: - void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); + void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); private: - void _requestAdvisories(); + void _requestAdvisories (); private: bool _valid; - double _lastRadius; AirMapSharedState& _shared; - QGeoCoordinate _lastRoiCenter; + QGCGeoBoundingCube _lastROI; QmlObjectListModel _advisories; AdvisoryColor _airspaceColor; }; diff --git a/src/Airmap/AirMapFlightPlanManager.cc b/src/Airmap/AirMapFlightPlanManager.cc index e409188ac2b47d87ecc3abc045bbbe01b9a276a6..9c4b56bbdc6d0a88918f9616ed42f7157d6fcac9 100644 --- a/src/Airmap/AirMapFlightPlanManager.cc +++ b/src/Airmap/AirMapFlightPlanManager.cc @@ -106,12 +106,7 @@ AirMapFlightPlanManager::_createFlightPlan() QGCGeoBoundingCube bc = _controller->travelBoundingCube(); _flight.maxAltitude = fmax(bc.pointNW.altitude(), bc.pointSE.altitude()); _flight.takeoffCoord = _controller->takeoffCoordinate(); - _flight.coords.append(QGeoCoordinate(bc.pointNW.latitude(), bc.pointNW.longitude(), _flight.maxAltitude)); - _flight.coords.append(QGeoCoordinate(bc.pointNW.latitude(), bc.pointSE.longitude(), _flight.maxAltitude)); - _flight.coords.append(QGeoCoordinate(bc.pointSE.latitude(), bc.pointSE.longitude(), _flight.maxAltitude)); - _flight.coords.append(QGeoCoordinate(bc.pointSE.latitude(), bc.pointNW.longitude(), _flight.maxAltitude)); - _flight.coords.append(QGeoCoordinate(bc.pointNW.latitude(), bc.pointNW.longitude(), _flight.maxAltitude)); - + _flight.coords = bc.polygon2D(); if(_flightStartTime.isNull() || _flightStartTime < QDateTime::currentDateTime()) { _flightStartTime = QDateTime::currentDateTime().addSecs(5 * 60); emit flightStartTimeChanged(); @@ -382,6 +377,11 @@ AirMapFlightPlanManager::_pollBriefing() //-- Iterate Rules for (const auto& rule : ruleset.rules) { AirMapRule* pRule = new AirMapRule(rule, this); + //-- Iterate Rule Features + for (const auto& feature : rule.features) { + AirMapRuleFeature* pFeature = new AirMapRuleFeature(feature, this); + pRule->_features.append(pFeature); + } pRuleSet->_rules.append(pRule); } //-- Sort rules by relevance order diff --git a/src/Airmap/AirMapManager.cc b/src/Airmap/AirMapManager.cc index f5aeeea8e270d37d71e3a3b4403bd8c4bb3dbbbc..a995f2769dac7926a3a80d92000af66ffca246ee 100644 --- a/src/Airmap/AirMapManager.cc +++ b/src/Airmap/AirMapManager.cc @@ -37,8 +37,8 @@ AirMapManager::AirMapManager(QGCApplication* app, QGCToolbox* toolbox) { _logger = std::make_shared(); qt::register_types(); // TODO: still needed? - _logger->logging_category().setEnabled(QtDebugMsg, false); - _logger->logging_category().setEnabled(QtInfoMsg, false); + _logger->logging_category().setEnabled(QtDebugMsg, false); + _logger->logging_category().setEnabled(QtInfoMsg, false); _logger->logging_category().setEnabled(QtWarningMsg, true); _dispatchingLogger = std::make_shared(_logger); connect(&_shared, &AirMapSharedState::error, this, &AirMapManager::_error); diff --git a/src/Airmap/AirMapRestrictionManager.cc b/src/Airmap/AirMapRestrictionManager.cc index 777f61160dccb4adace79d43ec24932e2c0d6e2d..2bf78c598f2a8a82f6bc348534916a2e9eaf1936 100644 --- a/src/Airmap/AirMapRestrictionManager.cc +++ b/src/Airmap/AirMapRestrictionManager.cc @@ -20,25 +20,26 @@ using namespace airmap; //----------------------------------------------------------------------------- AirMapRestrictionManager::AirMapRestrictionManager(AirMapSharedState& shared) : _shared(shared) - , _lastRadius(0.0) { } //----------------------------------------------------------------------------- void -AirMapRestrictionManager::setROI(const QGeoCoordinate& center, double radiusMeters) +AirMapRestrictionManager::setROI(const QGCGeoBoundingCube& roi) { - //-- If first time or we've moved more than ADVISORY_UPDATE_DISTANCE, ask for updates. - if(!_lastRoiCenter.isValid() || _lastRoiCenter.distanceTo(center) > RESTRICTION_UPDATE_DISTANCE || _lastRadius != radiusMeters) { - _lastRadius = radiusMeters; - _lastRoiCenter = center; - _requestRestrictions(center, radiusMeters); + //-- If first time or we've moved more than RESTRICTION_UPDATE_DISTANCE, ask for updates. + if(!_lastROI.isValid() || _lastROI.pointNW.distanceTo(roi.pointNW) > RESTRICTION_UPDATE_DISTANCE || _lastROI.pointSE.distanceTo(roi.pointSE) > RESTRICTION_UPDATE_DISTANCE) { + //-- No more than 40000 km^2 + if(roi.area() < 40000.0) { + _lastROI = roi; + _requestRestrictions(roi); + } } } //----------------------------------------------------------------------------- void -AirMapRestrictionManager::_requestRestrictions(const QGeoCoordinate& center, double radiusMeters) +AirMapRestrictionManager::_requestRestrictions(const QGCGeoBoundingCube& roi) { if (!_shared.client()) { qCDebug(AirMapManagerLog) << "No AirMap client instance. Not updating Airspace"; @@ -48,14 +49,22 @@ AirMapRestrictionManager::_requestRestrictions(const QGeoCoordinate& center, dou qCWarning(AirMapManagerLog) << "AirMapRestrictionManager::updateROI: state not idle"; return; } - qCDebug(AirMapManagerLog) << "setting ROI"; + qCDebug(AirMapManagerLog) << "Setting Restriction Manager ROI"; _polygons.clear(); _circles.clear(); _state = State::RetrieveItems; Airspaces::Search::Parameters params; - params.geometry = Geometry::point(center.latitude(), center.longitude()); - params.buffer = radiusMeters; params.full = true; + params.date_time = Clock::universal_time(); + //-- Geometry: Polygon + Geometry::Polygon polygon; + for (const auto& qcoord : roi.polygon2D()) { + Geometry::Coordinate coord; + coord.latitude = qcoord.latitude(); + coord.longitude = qcoord.longitude(); + polygon.outer_ring.coordinates.push_back(coord); + } + params.geometry = Geometry(polygon); std::weak_ptr isAlive(_instance); _shared.client()->airspaces().search(params, [this, isAlive](const Airspaces::Search::Result& result) { diff --git a/src/Airmap/AirMapRestrictionManager.h b/src/Airmap/AirMapRestrictionManager.h index cc4fc8979876f28854b8ff6a7220c6c720f4f276..849bbe3d24e7523f0899ce70e67b3afe68b764b9 100644 --- a/src/Airmap/AirMapRestrictionManager.h +++ b/src/Airmap/AirMapRestrictionManager.h @@ -12,6 +12,7 @@ #include "LifetimeChecker.h" #include "AirspaceRestrictionProvider.h" #include "AirMapSharedState.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -30,13 +31,13 @@ public: AirMapRestrictionManager (AirMapSharedState& shared); QmlObjectListModel* polygons () override { return &_polygons; } QmlObjectListModel* circles () override { return &_circles; } - void setROI (const QGeoCoordinate& center, double radiusMeters) override; + void setROI (const QGCGeoBoundingCube &roi) override; signals: void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); private: - void _requestRestrictions(const QGeoCoordinate& center, double radiusMeters); + void _requestRestrictions(const QGCGeoBoundingCube& roi); void _addPolygonToList (const airmap::Geometry::Polygon& polygon); enum class State { @@ -45,8 +46,7 @@ private: }; AirMapSharedState& _shared; - double _lastRadius; - QGeoCoordinate _lastRoiCenter; + QGCGeoBoundingCube _lastROI; State _state = State::Idle; QmlObjectListModel _polygons; QmlObjectListModel _circles; diff --git a/src/Airmap/AirMapRulesetsManager.cc b/src/Airmap/AirMapRulesetsManager.cc index 0e44f8c91da148225b8dfc0983fa9f46eb4b6aeb..e8de64098ec0fd9daca1e5e58aaf8f02d977cab1 100644 --- a/src/Airmap/AirMapRulesetsManager.cc +++ b/src/Airmap/AirMapRulesetsManager.cc @@ -177,7 +177,7 @@ rules_sort(QObject* a, QObject* b) } //----------------------------------------------------------------------------- -void AirMapRulesetsManager::setROI(const QGeoCoordinate& center) +void AirMapRulesetsManager::setROI(const QGCGeoBoundingCube& roi) { if (!_shared.client()) { qCDebug(AirMapManagerLog) << "No AirMap client instance. Not updating Airspace"; @@ -192,7 +192,15 @@ void AirMapRulesetsManager::setROI(const QGeoCoordinate& center) _ruleSets.clearAndDeleteContents(); _state = State::RetrieveItems; RuleSets::Search::Parameters params; - params.geometry = Geometry::point(center.latitude(), center.longitude()); + //-- Geometry: Polygon + Geometry::Polygon polygon; + for (const auto& qcoord : roi.polygon2D()) { + Geometry::Coordinate coord; + coord.latitude = qcoord.latitude(); + coord.longitude = qcoord.longitude(); + polygon.outer_ring.coordinates.push_back(coord); + } + params.geometry = Geometry(polygon); std::weak_ptr isAlive(_instance); _shared.client()->rulesets().search(params, [this, isAlive](const RuleSets::Search::Result& result) { diff --git a/src/Airmap/AirMapRulesetsManager.h b/src/Airmap/AirMapRulesetsManager.h index 8540dc276cd4251f939b3e722eb764a7d9c76f15..4d5ec47996ef6806d97e7a3c4e3da0b89c396d3b 100644 --- a/src/Airmap/AirMapRulesetsManager.h +++ b/src/Airmap/AirMapRulesetsManager.h @@ -12,6 +12,7 @@ #include "LifetimeChecker.h" #include "AirspaceRulesetsProvider.h" #include "AirMapSharedState.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -50,6 +51,7 @@ class AirMapRule : public AirspaceRule { Q_OBJECT friend class AirMapRulesetsManager; + friend class AirMapFlightPlanManager; public: AirMapRule (QObject* parent = NULL); @@ -107,7 +109,7 @@ public: QmlObjectListModel* ruleSets () override { return &_ruleSets; } QString selectedRuleSets() override; - void setROI (const QGeoCoordinate& center) override; + void setROI (const QGCGeoBoundingCube& roi) override; signals: void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); diff --git a/src/Airmap/AirMapWeatherInfoManager.cc b/src/Airmap/AirMapWeatherInfoManager.cc index d309a8c708f1023cd87a61cb3d3c1c486b0d85e1..8c2c51af757cf42e3f0b017ba5cc34000512d834 100644 --- a/src/Airmap/AirMapWeatherInfoManager.cc +++ b/src/Airmap/AirMapWeatherInfoManager.cc @@ -23,17 +23,17 @@ AirMapWeatherInfoManager::AirMapWeatherInfoManager(AirMapSharedState& shared, QO } void -AirMapWeatherInfoManager::setROI(const QGeoCoordinate& center) +AirMapWeatherInfoManager::setROI(const QGCGeoBoundingCube& roi) { //-- If first time or we've moved more than WEATHER_UPDATE_DISTANCE, ask for weather updates. - if(!_lastRoiCenter.isValid() || _lastRoiCenter.distanceTo(center) > WEATHER_UPDATE_DISTANCE) { - _lastRoiCenter = center; - _requestWeatherUpdate(center); + if(!_lastRoiCenter.isValid() || _lastRoiCenter.distanceTo(roi.center()) > WEATHER_UPDATE_DISTANCE) { + _lastRoiCenter = roi.center(); + _requestWeatherUpdate(_lastRoiCenter); _weatherTime.start(); } else { //-- Check weather once every WEATHER_UPDATE_TIME if(_weatherTime.elapsed() > WEATHER_UPDATE_TIME) { - _requestWeatherUpdate(center); + _requestWeatherUpdate(roi.center()); _weatherTime.start(); } } diff --git a/src/Airmap/AirMapWeatherInfoManager.h b/src/Airmap/AirMapWeatherInfoManager.h index d078e2db0155efaae57c1d326548e2ddea43ee3d..9f7a34104989031a97b110ebaa02641e600301e5 100644 --- a/src/Airmap/AirMapWeatherInfoManager.h +++ b/src/Airmap/AirMapWeatherInfoManager.h @@ -13,6 +13,7 @@ #include "AirspaceWeatherInfoProvider.h" #include "AirMapSharedState.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -41,7 +42,7 @@ public: quint32 visibility () override { return _weather.visibility; } quint32 precipitation () override { return _weather.precipitation; } - void setROI (const QGeoCoordinate& center) override; + void setROI (const QGCGeoBoundingCube& roi) override; signals: void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); diff --git a/src/Airmap/AirspaceControl.qml b/src/Airmap/AirspaceControl.qml index 7643c2fb9e2192b29a7e173aaa50a6cafd588e44..8f7a601dfaabca0c61f1199fb827f69e77c03033 100644 --- a/src/Airmap/AirspaceControl.qml +++ b/src/Airmap/AirspaceControl.qml @@ -86,10 +86,19 @@ Item { color: _textColor anchors.verticalCenter: parent.verticalCenter } - QGCLabel { - text: qsTr("Airspace") - color: _textColor + Column { + spacing: 0 anchors.verticalCenter: parent.verticalCenter + QGCLabel { + text: qsTr("Airspace") + color: _textColor + } + QGCLabel { + text: _validAdvisories ? QGroundControl.airspaceManager.advisories.advisories.count + qsTr(" Advisories") : "" + color: _textColor + visible: _validAdvisories + font.pointSize: ScreenTools.smallFontPointSize + } } Item { width: ScreenTools.defaultFontPixelWidth diff --git a/src/AirspaceManagement/AirspaceAdvisoryProvider.h b/src/AirspaceManagement/AirspaceAdvisoryProvider.h index 4946a4c0ed401c9c025c51f9be9fbbda44e681a9..300def80552af0538ca263e8a970335688671231 100644 --- a/src/AirspaceManagement/AirspaceAdvisoryProvider.h +++ b/src/AirspaceManagement/AirspaceAdvisoryProvider.h @@ -15,6 +15,7 @@ */ #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -49,7 +50,7 @@ public: * Set region of interest that should be queried. When finished, the advisoryChanged() signal will be emmited. * @param center Center coordinate for ROI */ - virtual void setROI (const QGeoCoordinate& center, double radiusMeters) = 0; + virtual void setROI (const QGCGeoBoundingCube& roi) = 0; signals: void advisoryChanged (); diff --git a/src/AirspaceManagement/AirspaceManager.cc b/src/AirspaceManagement/AirspaceManager.cc index a903063398e975f63f5080ac88d5a2f12b1207d3..27cdbc8d0e6bf886f8836e119fbb7db14e036b00 100644 --- a/src/AirspaceManagement/AirspaceManager.cc +++ b/src/AirspaceManagement/AirspaceManager.cc @@ -70,30 +70,29 @@ void AirspaceManager::setToolbox(QGCToolbox* toolbox) _flightPlan = _instantiateAirspaceFlightPlanProvider(); } -void AirspaceManager::setROI(QGeoCoordinate center, double radiusMeters) +void AirspaceManager::setROI(const QGeoCoordinate& pointNW, const QGeoCoordinate& pointSE) { - _setROI(center, radiusMeters); + _setROI(QGCGeoBoundingCube(pointNW, pointSE)); } -void AirspaceManager::_setROI(const QGeoCoordinate& center, double radiusMeters) +void AirspaceManager::_setROI(const QGCGeoBoundingCube& roi) { - _roiCenter = center; - _roiRadius = radiusMeters; + _roi = roi; _roiUpdateTimer.start(); } void AirspaceManager::_updateToROI() { if(_airspaces) { - _airspaces->setROI(_roiCenter, _roiRadius); + _airspaces->setROI(_roi); } if(_ruleSetsProvider) { - _ruleSetsProvider->setROI(_roiCenter); + _ruleSetsProvider->setROI(_roi); } if(_weatherProvider) { - _weatherProvider->setROI(_roiCenter); + _weatherProvider->setROI(_roi); } if (_advisories) { - _advisories->setROI(_roiCenter, _roiRadius); + _advisories->setROI(_roi); } } diff --git a/src/AirspaceManagement/AirspaceManager.h b/src/AirspaceManagement/AirspaceManager.h index c0f470b96b5d07eb6d5a6ed4fd909f0928d87665..d99e8a65f26628b1c7db6c39fb0e3d0faae22592 100644 --- a/src/AirspaceManagement/AirspaceManager.h +++ b/src/AirspaceManagement/AirspaceManager.h @@ -26,6 +26,7 @@ #include "QGCToolbox.h" #include "QGCLoggingCategory.h" #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -63,7 +64,7 @@ public: Q_PROPERTY(AirspaceFlightPlanProvider* flightPlan READ flightPlan CONSTANT) Q_PROPERTY(bool airspaceVisible READ airspaceVisible WRITE setAirspaceVisible NOTIFY airspaceVisibleChanged) - Q_INVOKABLE void setROI (QGeoCoordinate center, double radius); + Q_INVOKABLE void setROI (const QGeoCoordinate& pointNW, const QGeoCoordinate& pointSE); AirspaceWeatherInfoProvider* weatherInfo () { return _weatherProvider; } AirspaceAdvisoryProvider* advisories () { return _advisories; } @@ -92,7 +93,7 @@ protected: * @param center Center coordinate for ROI * @param radiusMeters Radius in meters around center which is of interest */ - virtual void _setROI (const QGeoCoordinate& center, double radiusMeters); + virtual void _setROI (const QGCGeoBoundingCube& roi); /** * Factory methods @@ -111,8 +112,7 @@ protected: AirspaceRestrictionProvider* _airspaces = nullptr; ///< Airspace info AirspaceFlightPlanProvider* _flightPlan = nullptr; ///< Flight plan management QTimer _roiUpdateTimer; - QGeoCoordinate _roiCenter; - double _roiRadius; + QGCGeoBoundingCube _roi; private: void _updateToROI (); diff --git a/src/AirspaceManagement/AirspaceRestrictionProvider.h b/src/AirspaceManagement/AirspaceRestrictionProvider.h index 2b627ec8e47d1e70689c09c03ec4e76898c36f98..723a78ace2744d928531795cd1c591149e643b68 100644 --- a/src/AirspaceManagement/AirspaceRestrictionProvider.h +++ b/src/AirspaceManagement/AirspaceRestrictionProvider.h @@ -15,6 +15,7 @@ */ #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -37,7 +38,7 @@ public: * @param center Center coordinate for ROI * @param radiusMeters Radius in meters around center which is of interest */ - virtual void setROI (const QGeoCoordinate& center, double radiusMeters) = 0; + virtual void setROI (const QGCGeoBoundingCube& roi) = 0; virtual QmlObjectListModel* polygons () = 0; ///< List of AirspacePolygonRestriction objects virtual QmlObjectListModel* circles () = 0; ///< List of AirspaceCircularRestriction objects diff --git a/src/AirspaceManagement/AirspaceRulesetsProvider.h b/src/AirspaceManagement/AirspaceRulesetsProvider.h index 91777f80e82db7d477b96113ff4c003f5b7bf6c5..834b8f8ecd59e52cd06f277a1165d2f6b7966731 100644 --- a/src/AirspaceManagement/AirspaceRulesetsProvider.h +++ b/src/AirspaceManagement/AirspaceRulesetsProvider.h @@ -16,6 +16,7 @@ */ #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -161,7 +162,7 @@ public: * Set region of interest that should be queried. When finished, the rulesChanged() signal will be emmited. * @param center Center coordinate for ROI */ - virtual void setROI (const QGeoCoordinate& center) = 0; + virtual void setROI (const QGCGeoBoundingCube& roi) = 0; signals: void ruleSetsChanged (); diff --git a/src/AirspaceManagement/AirspaceWeatherInfoProvider.h b/src/AirspaceManagement/AirspaceWeatherInfoProvider.h index a8f99bf0ad6435042f41d1e9614ff2f3fd794bfe..5e0de6660db1dfb97a537ccf2f73c4bb091e97ae 100644 --- a/src/AirspaceManagement/AirspaceWeatherInfoProvider.h +++ b/src/AirspaceManagement/AirspaceWeatherInfoProvider.h @@ -14,6 +14,7 @@ * Weather information provided by the Airspace Managemement */ +#include "QGCGeoBoundingCube.h" #include #include @@ -50,7 +51,7 @@ public: * Set region of interest that should be queried. When finished, the weatherChanged() signal will be emmited. * @param center Center coordinate for ROI */ - virtual void setROI (const QGeoCoordinate& center) = 0; + virtual void setROI (const QGCGeoBoundingCube& roi) = 0; signals: void weatherChanged (); diff --git a/src/FlightDisplay/FlightDisplayViewMap.qml b/src/FlightDisplay/FlightDisplayViewMap.qml index 6c5b9dd65a13a53e761b52be722c0afd81a73389..c8affbe72dddb55ad40b9e056aad9d5765e23d4e 100644 --- a/src/FlightDisplay/FlightDisplayViewMap.qml +++ b/src/FlightDisplay/FlightDisplayViewMap.qml @@ -57,13 +57,25 @@ FlightMap { property bool _disableVehicleTracking: false property bool _keepVehicleCentered: _mainIsMap ? false : true - // Track last known map position and zoom from Fly view in settings - onZoomLevelChanged: QGroundControl.flightMapZoom = zoomLevel - onCenterChanged: { + function updateAirspace() { if(_airspaceEnabled) { - QGroundControl.airspaceManager.setROI(center, 1000) + var coordinateNW = flightMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */) + var coordinateSE = flightMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */) + if(coordinateNW.isValid && coordinateSE.isValid) { + QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE) + } } + } + + // Track last known map position and zoom from Fly view in settings + + onZoomLevelChanged: { + QGroundControl.flightMapZoom = zoomLevel + updateAirspace() + } + onCenterChanged: { QGroundControl.flightMapPosition = center + updateAirspace() } // When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires diff --git a/src/FlightDisplay/FlightDisplayViewWidgets.qml b/src/FlightDisplay/FlightDisplayViewWidgets.qml index 1641001b2a21efda88792f04c4df90a4056c3512..0a58861a86b36a11a855a6bfa98ee0cfe94c9eae 100644 --- a/src/FlightDisplay/FlightDisplayViewWidgets.qml +++ b/src/FlightDisplay/FlightDisplayViewWidgets.qml @@ -30,7 +30,7 @@ Item { property var qgcView property bool useLightColors property var missionController - property bool showValues: QGroundControl.airspaceManager.airspaceVisible + property bool showValues: !QGroundControl.airspaceManager.airspaceVisible property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property bool _isSatellite: _mainIsMap ? (_flightMap ? _flightMap.isSatelliteMap : true) : true diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index 0f0b3743941a7ba2d7580ed3e9819052b0cfb1f9..9fc75cf807a9da74158c6b81637ead0983621257 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -16,7 +16,7 @@ #include "Vehicle.h" #include "QGCLoggingCategory.h" #include "MavlinkQmlSingleton.h" -#include "QGCGeo.h" +#include "QGCGeoBoundingCube.h" #include diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index 42f5c4451ed011ea6e2bd256bd443be9f7354a3d..75387571327464be315149428908634ea5d95d9e 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -84,6 +84,16 @@ QGCView { _missionController.setCurrentPlanViewIndex(sequenceNumber, true) } + function updateAirspace() { + if(_airspaceEnabled) { + var coordinateNW = editorMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */) + var coordinateSE = editorMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */) + if(coordinateNW.isValid && coordinateSE.isValid) { + QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE) + } + } + } + property bool _firstMissionLoadComplete: false property bool _firstFenceLoadComplete: false property bool _firstRallyLoadComplete: false @@ -347,11 +357,8 @@ QGCView { QGCMapPalette { id: mapPal; lightColors: editorMap.isSatelliteMap } - onCenterChanged: { - if(_airspaceEnabled) { - QGroundControl.airspaceManager.setROI(center, 5000) - } - } + onZoomLevelChanged: updateAirspace() + onCenterChanged: updateAirspace() MouseArea { //-- It's a whole lot faster to just fill parent and deal with top offset below @@ -542,7 +549,7 @@ QGCView { height: ScreenTools.availableHeight width: _rightPanelWidth color: qgcPal.window - opacity: 0.2 + opacity: planExpanded.visible ? 0.2 : 0 anchors.bottom: parent.bottom anchors.right: parent.right anchors.rightMargin: ScreenTools.defaultFontPixelWidth diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 9dbfcd0fe90c1c217a705fc0ab5b1e420a276364..9f8be2da7241953107a4b0961c3f2521b54de179 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -61,6 +61,7 @@ #include "JoystickConfigController.h" #include "JoystickManager.h" #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include "MissionManager.h" #include "QGroundControlQmlGlobal.h" #include "FlightMapSettings.h" @@ -381,6 +382,8 @@ void QGCApplication::_initCommon(void) qmlRegisterUncreatableType("QGroundControl.Controllers", 1, 0, "RallyPointController", "Reference only"); qmlRegisterUncreatableType ("QGroundControl.Controllers", 1, 0, "VisualMissionItem", "Reference only"); + qmlRegisterType ("QGroundControl", 1, 0, "QGCGeoBoundingCube"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ParameterEditorController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ESP8266ComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ScreenToolsController"); diff --git a/src/QGCGeo.cc b/src/QGCGeo.cc index 0160e4f230fba10f0d0cc45d31ad2ac47d7114aa..0c27941cb9ce26b72b6f638854256ccb9268e68f 100644 --- a/src/QGCGeo.cc +++ b/src/QGCGeo.cc @@ -102,10 +102,3 @@ void convertUTMToGeo(double easting, double northing, int zone, bool southhemi, coord.setLatitude(RadToDeg(latRadians)); coord.setLongitude(RadToDeg(lonRadians)); } - -double QGCGeoBoundingCube::MaxAlt = 1000000.0; -double QGCGeoBoundingCube::MinAlt = -1000000.0; -double QGCGeoBoundingCube::MaxNorth = 90.0; -double QGCGeoBoundingCube::MaxSouth = -90.0; -double QGCGeoBoundingCube::MaxWest = -180.0; -double QGCGeoBoundingCube::MaxEast = 180.0; diff --git a/src/QGCGeo.h b/src/QGCGeo.h index f4a4638e9a11777bcf9fe195651c822624dc6bcb..18f91ed2cdff24e1d267d18fde9577ece26f6829 100644 --- a/src/QGCGeo.h +++ b/src/QGCGeo.h @@ -81,46 +81,4 @@ int convertGeoToUTM(const QGeoCoordinate& coord, double& easting, double& northi // The function does not return a value. void convertUTMToGeo(double easting, double northing, int zone, bool southhemi, QGeoCoordinate& coord); -// A bounding cube -class QGCGeoBoundingCube { -public: - QGCGeoBoundingCube() - : pointNW(QGeoCoordinate(MaxSouth, MaxEast, MaxAlt)) - , pointSE(QGeoCoordinate(MaxNorth, MaxWest, MinAlt)) - { - } - QGCGeoBoundingCube(QGeoCoordinate p1, QGeoCoordinate p2) - : pointNW(p1) - , pointSE(p2) - { - } - QGeoCoordinate pointNW; - QGeoCoordinate pointSE; - inline bool operator ==(const QGCGeoBoundingCube& other) - { - return pointNW == other.pointNW && pointSE == other.pointSE; - } - inline bool operator !=(const QGCGeoBoundingCube& other) - { - return !(*this == other); - } - inline QGCGeoBoundingCube operator =(const QGCGeoBoundingCube& other) - { - pointNW = other.pointNW; - pointSE = other.pointSE; - return *this; - } - inline bool isValid() - { - return pointNW.isValid() && pointSE.isValid() && pointNW.latitude() != MaxSouth && pointSE.latitude() != MaxNorth && \ - pointNW.longitude() != MaxEast && pointSE.longitude() != MaxWest && pointNW.altitude() < MaxAlt and pointSE.altitude() > MinAlt; - } - static double MaxAlt; - static double MinAlt; - static double MaxNorth; - static double MaxSouth; - static double MaxWest; - static double MaxEast; -}; - #endif // QGCGEO_H diff --git a/src/QmlControls/QGCGeoBoundingCube.cc b/src/QmlControls/QGCGeoBoundingCube.cc new file mode 100644 index 0000000000000000000000000000000000000000..7fe03d0ff8c22076d8c81c53fcae8a290778bf61 --- /dev/null +++ b/src/QmlControls/QGCGeoBoundingCube.cc @@ -0,0 +1,83 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "QGCGeoBoundingCube.h" +#include + +double QGCGeoBoundingCube::MaxAlt = 1000000.0; +double QGCGeoBoundingCube::MinAlt = -1000000.0; +double QGCGeoBoundingCube::MaxNorth = 90.0; +double QGCGeoBoundingCube::MaxSouth = -90.0; +double QGCGeoBoundingCube::MaxWest = -180.0; +double QGCGeoBoundingCube::MaxEast = 180.0; + +//----------------------------------------------------------------------------- +bool +QGCGeoBoundingCube::isValid() const +{ + return pointNW.isValid() && pointSE.isValid() && pointNW.latitude() != MaxSouth && pointSE.latitude() != MaxNorth && \ + pointNW.longitude() != MaxEast && pointSE.longitude() != MaxWest && pointNW.altitude() < MaxAlt and pointSE.altitude() > MinAlt; +} + +//----------------------------------------------------------------------------- +QGeoCoordinate +QGCGeoBoundingCube::center() const +{ + double lat = (((pointNW.latitude() + 90.0) + (pointSE.latitude() + 90.0)) / 2.0) - 90.0; + double lon = (((pointNW.longitude() + 180.0) + (pointSE.longitude() + 180.0)) / 2.0) - 180.0; + double alt = (pointNW.altitude() + pointSE.altitude()) / 2.0; + //qDebug() << pointNW << pointSE << QGeoCoordinate(lat, lon, alt); + return QGeoCoordinate(lat, lon, alt); +} + +//----------------------------------------------------------------------------- +QList +QGCGeoBoundingCube::polygon2D() const +{ + QList coords; + coords.append(QGeoCoordinate(pointNW.latitude(), pointNW.longitude(), pointSE.altitude())); + coords.append(QGeoCoordinate(pointNW.latitude(), pointSE.longitude(), pointSE.altitude())); + coords.append(QGeoCoordinate(pointSE.latitude(), pointSE.longitude(), pointSE.altitude())); + coords.append(QGeoCoordinate(pointSE.latitude(), pointNW.longitude(), pointSE.altitude())); + coords.append(QGeoCoordinate(pointNW.latitude(), pointNW.longitude(), pointSE.altitude())); + return coords; +} + +//----------------------------------------------------------------------------- +double +QGCGeoBoundingCube::width() const +{ + QGeoCoordinate ne = QGeoCoordinate(pointNW.latitude(), pointSE.longitude()); + return pointNW.distanceTo(ne); +} + +//----------------------------------------------------------------------------- +double +QGCGeoBoundingCube::height() const +{ + QGeoCoordinate sw = QGeoCoordinate(pointSE.latitude(), pointNW.longitude()); + return pointNW.distanceTo(sw); +} + +//----------------------------------------------------------------------------- +double +QGCGeoBoundingCube::area() const +{ + // Area in km^2 + double a = (height() / 1000.0) * (width() / 1000.0); + //qDebug() << "Area:" << a; + return a; +} + +//----------------------------------------------------------------------------- +double +QGCGeoBoundingCube::radius() const +{ + return pointNW.distanceTo(pointSE) / 2.0; +} diff --git a/src/QmlControls/QGCGeoBoundingCube.h b/src/QmlControls/QGCGeoBoundingCube.h new file mode 100644 index 0000000000000000000000000000000000000000..225f3072cf6dcdf83b3d37eef2f9d8a183071d64 --- /dev/null +++ b/src/QmlControls/QGCGeoBoundingCube.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +#pragma once + +#include +#include + +// A bounding "cube" for small surface areas (doesn't take in consideration earth's curvature) +// Coordinate system makes NW Up Left Bottom (0,0,0) and SE Bottom Right Top (y,x,z) +class QGCGeoBoundingCube : public QObject { + Q_OBJECT +public: + QGCGeoBoundingCube(const QGCGeoBoundingCube& other) + { + pointNW = other.pointNW; + pointSE = other.pointSE; + } + + QGCGeoBoundingCube() + : pointNW(QGeoCoordinate(MaxSouth, MaxEast, MaxAlt)) + , pointSE(QGeoCoordinate(MaxNorth, MaxWest, MinAlt)) + { + } + + QGCGeoBoundingCube(QGeoCoordinate p1, QGeoCoordinate p2) + : pointNW(p1) + , pointSE(p2) + { + } + + Q_PROPERTY(QGeoCoordinate pointNW MEMBER pointNW CONSTANT) + Q_PROPERTY(QGeoCoordinate pointSE MEMBER pointNW CONSTANT) + + Q_INVOKABLE bool isValid() const; + Q_INVOKABLE QGeoCoordinate center() const; + + inline bool operator ==(const QGCGeoBoundingCube& other) + { + return pointNW == other.pointNW && pointSE == other.pointSE; + } + + inline bool operator !=(const QGCGeoBoundingCube& other) + { + return !(*this == other); + } + + inline const QGCGeoBoundingCube& operator =(const QGCGeoBoundingCube& other) + { + pointNW = other.pointNW; + pointSE = other.pointSE; + return *this; + } + + //-- 2D + QList polygon2D() const; + double width () const; + double height () const; + double area () const; + double radius () const; + + QGeoCoordinate pointNW; + QGeoCoordinate pointSE; + static double MaxAlt; + static double MinAlt; + static double MaxNorth; + static double MaxSouth; + static double MaxWest; + static double MaxEast; +};