From 5f9f30c257f7908500a7482ef8e2c1813e35efe3 Mon Sep 17 00:00:00 2001 From: Valentin Platzgummer Date: Fri, 27 Nov 2020 16:37:18 +0100 Subject: [PATCH] generators fixed, _isIncomplete stuff added to MeasurementComplexItem --- src/MeasurementComplexItem/AreaData.cc | 4 +- src/MeasurementComplexItem/AreaData.h | 2 +- .../CircularGenerator.cpp | 102 +- .../CircularGenerator.h | 10 +- src/MeasurementComplexItem/GeneratorBase.cc | 18 +- src/MeasurementComplexItem/GeneratorBase.h | 2 +- .../LinearGenerator.cpp | 84 +- src/MeasurementComplexItem/LinearGenerator.h | 12 +- .../MeasurementComplexItem.cc | 124 +-- .../MeasurementComplexItem.h | 14 +- .../geometry/GeoArea.cc | 33 +- src/MeasurementComplexItem/geometry/GeoArea.h | 7 + .../geometry/MeasurementArea.cc | 31 +- .../geometry/SafeArea.cc | 4 +- .../nemo_interface/SnakeTile.cpp | 8 +- .../nemo_interface/SnakeTile.h | 3 + .../qml/CircularGeneratorMapVisual.qml | 88 +- .../qml/MeasurementItemMapVisual.qml | 161 +++- .../qml/ParameterEditor.qml | 26 +- .../qml/SafeAreaMapVisual.qml | 72 +- src/MissionManager/QGCMapPolygon.cc | 910 +++++++++--------- 21 files changed, 866 insertions(+), 849 deletions(-) diff --git a/src/MeasurementComplexItem/AreaData.cc b/src/MeasurementComplexItem/AreaData.cc index 146404fbf..65d3ba1ec 100644 --- a/src/MeasurementComplexItem/AreaData.cc +++ b/src/MeasurementComplexItem/AreaData.cc @@ -39,7 +39,7 @@ bool AreaData::insert(GeoArea *areaData) { if (areaData != nullptr) { if (Q_LIKELY(!this->_areaList.contains(areaData))) { _areaList.append(areaData); - emit areaList(); + emit areaListChanged(); auto *measurementArea = qobject_cast(areaData); if (measurementArea != nullptr) { @@ -88,7 +88,7 @@ QmlObjectListModel *AreaData::areaList() { return &_areaList; } const QmlObjectListModel *AreaData::areaList() const { return &_areaList; } -const QGeoCoordinate &AreaData::origin() const { return _origin; } +QGeoCoordinate AreaData::origin() const { return _origin; } bool AreaData::isCorrect() { if (!initialized()) { diff --git a/src/MeasurementComplexItem/AreaData.h b/src/MeasurementComplexItem/AreaData.h index 0c0abddc2..41df7011d 100644 --- a/src/MeasurementComplexItem/AreaData.h +++ b/src/MeasurementComplexItem/AreaData.h @@ -47,7 +47,7 @@ public: //! \brief origin //! \return Returns an origin near one of the areas. //! \note Origin might change if the list of areas changes. - const QGeoCoordinate &origin() const; + QGeoCoordinate origin() const; Q_INVOKABLE bool isCorrect(); //! diff --git a/src/MeasurementComplexItem/CircularGenerator.cpp b/src/MeasurementComplexItem/CircularGenerator.cpp index d876f8bc4..65e77ef24 100644 --- a/src/MeasurementComplexItem/CircularGenerator.cpp +++ b/src/MeasurementComplexItem/CircularGenerator.cpp @@ -37,13 +37,21 @@ CircularGenerator::CircularGenerator(QObject *parent) : CircularGenerator(nullptr, parent) {} CircularGenerator::CircularGenerator(GeneratorBase::Data d, QObject *parent) - : GeneratorBase(d, parent), _connectionsEstablished(false), + : GeneratorBase(d, parent), _metaDataMap(FactMetaData::createMapFromJsonFile( QStringLiteral(":/json/CircularGenerator.SettingsGroup.json"), this)), _distance(settingsGroup, _metaDataMap[distanceName]), _deltaAlpha(settingsGroup, _metaDataMap[deltaAlphaName]), - _minLength(settingsGroup, _metaDataMap[minLengthName]) { - establishConnections(); + _minLength(settingsGroup, _metaDataMap[minLengthName]), + _measurementArea(nullptr) { + connect(this->distance(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this->deltaAlpha(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this->minLength(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this, &CircularGenerator::referenceChanged, this, + &GeneratorBase::generatorChanged); } QString CircularGenerator::editorQml() { @@ -199,77 +207,47 @@ void CircularGenerator::resetReference() { } } -void CircularGenerator::establishConnections() { - if (this->_d != nullptr && !this->_connectionsEstablished) { - auto measurementArea = - getGeoArea(*this->_d->areaList()); - auto serviceArea = getGeoArea(*this->_d->areaList()); - if (measurementArea != nullptr && serviceArea != nullptr) { - GeneratorBase::establishConnections(); +Fact *CircularGenerator::distance() { return &_distance; } - connect(this->_d, &AreaData::originChanged, this, - &GeneratorBase::generatorChanged); - connect(measurementArea, &MeasurementArea::progressChanged, this, - &GeneratorBase::generatorChanged); - connect(measurementArea, &MeasurementArea::tilesChanged, this, - &GeneratorBase::generatorChanged); - connect(measurementArea, &MeasurementArea::centerChanged, this, - &CircularGenerator::resetReferenceIfInvalid); - connect(measurementArea, &MeasurementArea::pathChanged, this, - &GeneratorBase::generatorChanged); - connect(serviceArea, &SafeArea::depotChanged, this, - &GeneratorBase::generatorChanged); - connect(this->distance(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this->deltaAlpha(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this->minLength(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this, &CircularGenerator::referenceChanged, this, - &GeneratorBase::generatorChanged); - this->_connectionsEstablished = true; - } - } +Fact *CircularGenerator::deltaAlpha() { return &_deltaAlpha; } + +Fact *CircularGenerator::minLength() { return &_minLength; } + +void CircularGenerator::onAreaListChanged() { + auto *measurementArea = getGeoArea(*this->_d->areaList()); + setMeasurementArea(measurementArea); } -void CircularGenerator::deleteConnections() { - if (this->_d != nullptr && this->_connectionsEstablished) { - auto measurementArea = - getGeoArea(*this->_d->areaList()); - auto serviceArea = getGeoArea(*this->_d->areaList()); - if (measurementArea != nullptr && serviceArea != nullptr) { - GeneratorBase::deleteConnections(); +void CircularGenerator::setMeasurementArea(MeasurementArea *area) { + if (_measurementArea != area) { - disconnect(this->_d, &AreaData::originChanged, this, - &GeneratorBase::generatorChanged); - disconnect(measurementArea, &MeasurementArea::progressChanged, this, + if (_measurementArea != nullptr) { + disconnect(_measurementArea, &MeasurementArea::progressChanged, this, &GeneratorBase::generatorChanged); - disconnect(measurementArea, &MeasurementArea::tilesChanged, this, + disconnect(_measurementArea, &MeasurementArea::tilesChanged, this, &GeneratorBase::generatorChanged); - disconnect(measurementArea, &MeasurementArea::centerChanged, this, + disconnect(_measurementArea, &MeasurementArea::centerChanged, this, &CircularGenerator::resetReferenceIfInvalid); - disconnect(measurementArea, &MeasurementArea::pathChanged, this, + disconnect(_measurementArea, &MeasurementArea::pathChanged, this, &GeneratorBase::generatorChanged); - disconnect(serviceArea, &SafeArea::depotChanged, this, - &GeneratorBase::generatorChanged); - disconnect(this->distance(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - disconnect(this->deltaAlpha(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - disconnect(this->minLength(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - disconnect(this, &CircularGenerator::referenceChanged, this, - &GeneratorBase::generatorChanged); - this->_connectionsEstablished = true; } - } -} -Fact *CircularGenerator::distance() { return &_distance; } + _measurementArea = area; -Fact *CircularGenerator::deltaAlpha() { return &_deltaAlpha; } + if (_measurementArea != nullptr) { + connect(_measurementArea, &MeasurementArea::progressChanged, this, + &GeneratorBase::generatorChanged); + connect(_measurementArea, &MeasurementArea::tilesChanged, this, + &GeneratorBase::generatorChanged); + connect(_measurementArea, &MeasurementArea::centerChanged, this, + &CircularGenerator::resetReferenceIfInvalid); + connect(_measurementArea, &MeasurementArea::pathChanged, this, + &GeneratorBase::generatorChanged); + } -Fact *CircularGenerator::minLength() { return &_minLength; } + emit generatorChanged(); + } +} bool circularTransects(const snake::FPoint &reference, const snake::FPolygon &polygon, diff --git a/src/MeasurementComplexItem/CircularGenerator.h b/src/MeasurementComplexItem/CircularGenerator.h index 7a9ff8b11..98fca1967 100644 --- a/src/MeasurementComplexItem/CircularGenerator.h +++ b/src/MeasurementComplexItem/CircularGenerator.h @@ -4,6 +4,8 @@ #include "SettingsFact.h" +class MeasurementArea; + namespace routing { class CircularGenerator : public GeneratorBase { @@ -48,18 +50,16 @@ public slots: Q_INVOKABLE void resetReferenceIfInvalid(); Q_INVOKABLE void resetReference(); -protected: - virtual void establishConnections() override; - virtual void deleteConnections() override; - private: - bool _connectionsEstablished; + void onAreaListChanged(); + void setMeasurementArea(MeasurementArea *area); QGeoCoordinate _reference; QMap _metaDataMap; SettingsFact _distance; SettingsFact _deltaAlpha; SettingsFact _minLength; + MeasurementArea *_measurementArea; }; } // namespace routing diff --git a/src/MeasurementComplexItem/GeneratorBase.cc b/src/MeasurementComplexItem/GeneratorBase.cc index d3a68c910..212458d22 100644 --- a/src/MeasurementComplexItem/GeneratorBase.cc +++ b/src/MeasurementComplexItem/GeneratorBase.cc @@ -8,8 +8,6 @@ GeneratorBase::GeneratorBase(QObject *parent) GeneratorBase::GeneratorBase(GeneratorBase::Data d, QObject *parent) : QObject(parent), _d(d) { establishConnections(); - connect(_d, &AreaData::areaListChanged, this, - &GeneratorBase::_areaListChangedHandler); } GeneratorBase::~GeneratorBase() {} @@ -17,27 +15,15 @@ GeneratorBase::~GeneratorBase() {} GeneratorBase::Data GeneratorBase::data() const { return _d; } void GeneratorBase::setData(Data d) { - if (d != nullptr) { - if (_d != nullptr) { - disconnect(_d, &AreaData::areaListChanged, this, - &GeneratorBase::_areaListChangedHandler); - } + if (d != _d && d != nullptr) { deleteConnections(); _d = d; establishConnections(); - connect(_d, &AreaData::areaListChanged, this, - &GeneratorBase::_areaListChangedHandler); + emit dataChanged(); } } void GeneratorBase::establishConnections() {} void GeneratorBase::deleteConnections() {} - -void GeneratorBase::_areaListChangedHandler() { - deleteConnections(); - establishConnections(); - emit generatorChanged(); -} - } // namespace routing diff --git a/src/MeasurementComplexItem/GeneratorBase.h b/src/MeasurementComplexItem/GeneratorBase.h index 9f6163f07..8fb375b36 100644 --- a/src/MeasurementComplexItem/GeneratorBase.h +++ b/src/MeasurementComplexItem/GeneratorBase.h @@ -37,6 +37,7 @@ public: signals: void generatorChanged(); + void dataChanged(); protected: virtual void establishConnections(); @@ -44,7 +45,6 @@ protected: Data _d; private: - void _areaListChangedHandler(); }; } // namespace routing diff --git a/src/MeasurementComplexItem/LinearGenerator.cpp b/src/MeasurementComplexItem/LinearGenerator.cpp index 336557239..118e307b9 100644 --- a/src/MeasurementComplexItem/LinearGenerator.cpp +++ b/src/MeasurementComplexItem/LinearGenerator.cpp @@ -32,8 +32,16 @@ LinearGenerator::LinearGenerator(GeneratorBase::Data d, QObject *parent) QStringLiteral(":/json/LinearGenerator.SettingsGroup.json"), this)), _distance(settingsGroup, _metaDataMap[distanceName]), _alpha(settingsGroup, _metaDataMap[alphaName]), - _minLength(settingsGroup, _metaDataMap[minLengthName]) { - establishConnections(); + _minLength(settingsGroup, _metaDataMap[minLengthName]), + _measurementArea(nullptr), _safeArea(nullptr) { + connect(this->distance(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this->alpha(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this->minLength(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this->_d, &AreaData::areaListChanged, this, + &LinearGenerator::onAreaListChanged); } QString LinearGenerator::editorQml() { @@ -147,63 +155,35 @@ Fact *LinearGenerator::alpha() { return &_alpha; } Fact *LinearGenerator::minLength() { return &_minLength; } -void LinearGenerator::establishConnections() { - if (this->_d != nullptr && !this->_connectionsEstablished) { - auto measurementArea = - getGeoArea(*this->_d->areaList()); - auto serviceArea = getGeoArea(*this->_d->areaList()); - - if (measurementArea != nullptr && serviceArea != nullptr) { - GeneratorBase::establishConnections(); - - connect(this->_d, &AreaData::originChanged, this, - &GeneratorBase::generatorChanged); - connect(measurementArea, &MeasurementArea::progressChanged, this, - &GeneratorBase::generatorChanged); - connect(measurementArea, &MeasurementArea::tilesChanged, this, - &GeneratorBase::generatorChanged); - connect(measurementArea, &MeasurementArea::pathChanged, this, - &GeneratorBase::generatorChanged); - connect(serviceArea, &SafeArea::depotChanged, this, - &GeneratorBase::generatorChanged); - connect(this->distance(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this->alpha(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this->minLength(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - this->_connectionsEstablished = true; - } - } +void LinearGenerator::onAreaListChanged() { + auto *measurementArea = getGeoArea(*this->_d->areaList()); + setMeasurementArea(measurementArea); } -void LinearGenerator::deleteConnections() { - if (this->_d != nullptr && this->_connectionsEstablished) { - auto measurementArea = - getGeoArea(*this->_d->areaList()); - auto serviceArea = getGeoArea(*this->_d->areaList()); - - if (measurementArea != nullptr && serviceArea != nullptr) { - GeneratorBase::deleteConnections(); +void LinearGenerator::setMeasurementArea(MeasurementArea *area) { + if (_measurementArea != area) { - disconnect(this->_d, &AreaData::originChanged, this, + if (_measurementArea != nullptr) { + disconnect(_measurementArea, &MeasurementArea::progressChanged, this, &GeneratorBase::generatorChanged); - disconnect(measurementArea, &MeasurementArea::progressChanged, this, + disconnect(_measurementArea, &MeasurementArea::tilesChanged, this, &GeneratorBase::generatorChanged); - disconnect(measurementArea, &MeasurementArea::tilesChanged, this, + disconnect(_measurementArea, &MeasurementArea::pathChanged, this, &GeneratorBase::generatorChanged); - disconnect(measurementArea, &MeasurementArea::pathChanged, this, - &GeneratorBase::generatorChanged); - disconnect(serviceArea, &SafeArea::depotChanged, this, - &GeneratorBase::generatorChanged); - disconnect(this->distance(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - disconnect(this->alpha(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - disconnect(this->minLength(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - this->_connectionsEstablished = true; } + + _measurementArea = area; + + if (_measurementArea != nullptr) { + connect(_measurementArea, &MeasurementArea::progressChanged, this, + &GeneratorBase::generatorChanged); + connect(_measurementArea, &MeasurementArea::tilesChanged, this, + &GeneratorBase::generatorChanged); + connect(_measurementArea, &MeasurementArea::pathChanged, this, + &GeneratorBase::generatorChanged); + } + + emit generatorChanged(); } } diff --git a/src/MeasurementComplexItem/LinearGenerator.h b/src/MeasurementComplexItem/LinearGenerator.h index 87d353049..0e6cc531a 100644 --- a/src/MeasurementComplexItem/LinearGenerator.h +++ b/src/MeasurementComplexItem/LinearGenerator.h @@ -4,6 +4,9 @@ #include "SettingsFact.h" +class MeasurementArea; +class SafeArea; + namespace routing { class LinearGenerator : public GeneratorBase { @@ -33,17 +36,16 @@ public: static const char *alphaName; static const char *minLengthName; -protected: - virtual void establishConnections() override; - virtual void deleteConnections() override; - private: - bool _connectionsEstablished; + void onAreaListChanged(); + void setMeasurementArea(MeasurementArea *area); QMap _metaDataMap; SettingsFact _distance; SettingsFact _alpha; SettingsFact _minLength; + MeasurementArea *_measurementArea; + SafeArea *_safeArea; }; } // namespace routing diff --git a/src/MeasurementComplexItem/MeasurementComplexItem.cc b/src/MeasurementComplexItem/MeasurementComplexItem.cc index 68d65eefb..4a09a2419 100644 --- a/src/MeasurementComplexItem/MeasurementComplexItem.cc +++ b/src/MeasurementComplexItem/MeasurementComplexItem.cc @@ -72,15 +72,32 @@ MeasurementComplexItem::MeasurementComplexItem( this->exitCoordinateSameAsEntry()); }); + // Connect isIncomplete. + connect(this, &MeasurementComplexItem::idleChanged, [this] { + if (this->idle()) { + if (this->route().size() > 0 && this->_isIncomplete == true) { + this->_isIncomplete = false; + emit this->isIncompleteChanged(); + } + } else { + if (this->_isIncomplete == false) { + this->_isIncomplete = true; + emit this->isIncompleteChanged(); + } + } + }); + connect(this, &MeasurementComplexItem::idleChanged, this, + &MeasurementComplexItem::readyForSaveStateChanged); + // Connect complexDistance. connect(this, &MeasurementComplexItem::routeChanged, [this] { emit this->complexDistanceChanged(); }); // Register Generators. auto lg = new routing::LinearGenerator(this->_pAreaData, this); - registerGenerator(lg->name(), lg); + addGenerator(lg->name(), lg); auto cg = new routing::CircularGenerator(this->_pAreaData, this); - registerGenerator(cg->name(), cg); + addGenerator(cg->name(), cg); qCritical() << "ToDo: _altitude connections missing."; qCritical() << "ToDo: add generator saveing."; @@ -192,7 +209,7 @@ void MeasurementComplexItem::save(QJsonArray &planItems) { qWarning() << "MeasurementComplexItem::save(): area data save missing."; qWarning() << "MeasurementComplexItem::save(): mission item save missing."; - if (ready()) { + if (idle()) { QJsonObject saveObject; saveObject[JsonHelper::jsonVersionKey] = 1; @@ -270,7 +287,7 @@ double MeasurementComplexItem::specifiedGimbalPitch() { void MeasurementComplexItem::appendMissionItems(QList &items, QObject *missionItemParent) { - if (ready()) { + if (idle()) { qCDebug(MeasurementComplexItemLog) << "appendMissionItems()"; int seqNum = this->_sequenceNumber; @@ -350,8 +367,8 @@ void MeasurementComplexItem::_setState(MeasurementComplexItem::STATE state) { emit editingChanged(); } - if (_ready(oldState) != _ready(state)) { - emit readyChanged(); + if (_idle(oldState) != _idle(state)) { + emit idleChanged(); } } } @@ -364,7 +381,7 @@ bool MeasurementComplexItem::_editing(MeasurementComplexItem::STATE state) { return state == STATE::EDITING; } -bool MeasurementComplexItem::_ready(MeasurementComplexItem::STATE state) { +bool MeasurementComplexItem::_idle(MeasurementComplexItem::STATE state) { return state == STATE::IDLE; } @@ -380,6 +397,7 @@ void MeasurementComplexItem::_updateRoute() { if (!editing()) { // Reset data. this->_route.clear(); + emit routeChanged(); this->_variantVector.clear(); this->_variantNames.clear(); emit variantNamesChanged(); @@ -443,14 +461,14 @@ void MeasurementComplexItem::_updateRoute() { } } else { qCDebug(MeasurementComplexItemLog) - << "_updateWorker(): plan data invalid."; + << "_updateWorker(): area data invalid."; return; } } } void MeasurementComplexItem::_changeVariant() { - if (ready()) { + if (idle()) { auto variant = this->_variant.rawValue().toUInt(); // Find old variant and run. Old run corresponts with empty list. @@ -470,11 +488,11 @@ void MeasurementComplexItem::_changeVariant() { if (old_variant != std::numeric_limits::max()) { // this->_route containes a route, swap it back to // this->_solutionVector - auto &oldVariantCoordinates = this->_variantVector[old_variant]; - oldVariantCoordinates.swap(this->_route); + auto &oldRoute = this->_variantVector[old_variant]; + oldRoute.swap(this->_route); } - auto &newVariantCoordinates = this->_variantVector[variant]; - this->_route.swap(newVariantCoordinates); + auto &newRoute = this->_variantVector[variant]; + this->_route.swap(newRoute); emit routeChanged(); } else { // error qCDebug(MeasurementComplexItemLog) @@ -496,7 +514,7 @@ void MeasurementComplexItem::_changeVariant() { } void MeasurementComplexItem::_reverseRoute() { - if (ready()) { + if (idle()) { if (this->_route.size() > 0) { auto &t = this->_route; std::reverse(t.begin(), t.end()); @@ -507,7 +525,7 @@ void MeasurementComplexItem::_reverseRoute() { ComplexMissionItem::ReadyForSaveState MeasurementComplexItem::readyForSaveState() const { - if (ready()) { + if (idle()) { return ReadyForSaveState::ReadyForSave; } else { return ReadyForSaveState::NotReadyForSaveData; @@ -557,8 +575,8 @@ int MeasurementComplexItem::lastSequenceNumber() const { return _sequenceNumber + std::max(0, this->_route.size() - 1); } -bool MeasurementComplexItem::registerGenerator(const QString &name, - routing::GeneratorBase *g) { +bool MeasurementComplexItem::addGenerator(const QString &name, + routing::GeneratorBase *g) { if (name.isEmpty()) { qCDebug(MeasurementComplexItemLog) << "registerGenerator(): empty name string."; @@ -587,7 +605,7 @@ bool MeasurementComplexItem::registerGenerator(const QString &name, } } -bool MeasurementComplexItem::unregisterGenerator(const QString &name) { +bool MeasurementComplexItem::removeGenerator(const QString &name) { auto index = this->_generatorNameList.indexOf(name); if (index >= 0) { // Is this the current generator? @@ -615,9 +633,9 @@ bool MeasurementComplexItem::unregisterGenerator(const QString &name) { } } -bool MeasurementComplexItem::unregisterGenerator(int index) { +bool MeasurementComplexItem::removeGenerator(int index) { if (index > 0 && index < this->_generatorNameList.size()) { - return unregisterGenerator(this->_generatorNameList.at(index)); + return removeGenerator(this->_generatorNameList.at(index)); } else { qCDebug(MeasurementComplexItemLog) << "unregisterGenerator(): index (" << index @@ -701,7 +719,6 @@ void MeasurementComplexItem::_storeRoutingData( // Store solutions. auto ori = this->_pAreaData->origin(); ori.setAltitude(0); - const auto &transectsENU = pRoute->transects; QVector variantVector; const auto nSolutions = pRoute->solutionVector.size(); @@ -711,60 +728,13 @@ void MeasurementComplexItem::_storeRoutingData( if (solution.size() > 0) { const auto &route = solution.at(0); const auto &path = route.path; - const auto &info = route.info; - if (info.size() > 1) { - // Find index of first waypoint. - std::size_t idxFirst = 0; - const auto &infoFirst = info.at(1); - const auto &firstTransect = transectsENU[infoFirst.index]; - if (firstTransect.size() > 0) { - const auto &firstWaypoint = infoFirst.reversed - ? firstTransect.back() - : firstTransect.front(); - double th = 0.01; - for (std::size_t i = 0; i < path.size(); ++i) { - auto dist = bg::distance(path[i], firstWaypoint); - if (dist < th) { - idxFirst = i; - break; - } - } - - // Find index of last waypoint. - std::size_t idxLast = path.size() - 1; - const auto &infoLast = info.at(info.size() - 2); - const auto &lastTransect = transectsENU[infoLast.index]; - if (lastTransect.size() > 0) { - const auto &lastWaypoint = infoLast.reversed - ? lastTransect.front() - : lastTransect.back(); - for (long i = path.size() - 1; i >= 0; --i) { - auto dist = bg::distance(path[i], lastWaypoint); - if (dist < th) { - idxLast = i; - break; - } - } - - // Convert to geo coordinates. - for (std::size_t i = idxFirst; i <= idxLast; ++i) { - auto &vertex = path[i]; - QGeoCoordinate c; - snake::fromENU(ori, vertex, c); - var.append(QVariant::fromValue(c)); - } - - } else { - qCDebug(MeasurementComplexItemLog) - << "_setTransects(): lastTransect.size() == 0"; - } - } else { - qCDebug(MeasurementComplexItemLog) - << "_setTransects(): firstTransect.size() == 0"; - } - } else { - qCDebug(MeasurementComplexItemLog) - << "_setTransects(): transectsInfo.size() <= 1"; + + // Convert to geo coordinates. + + for (const auto &vertex : path) { + QGeoCoordinate c; + snake::fromENU(ori, vertex, c); + var.append(QVariant::fromValue(c)); } } else { qCDebug(MeasurementComplexItemLog) @@ -789,12 +759,14 @@ void MeasurementComplexItem::_storeRoutingData( } emit variantNamesChanged(); + // Set variant to 0. disconnect(&this->_variant, &Fact::rawValueChanged, this, &MeasurementComplexItem::_changeVariant); this->_variant.setCookedValue(QVariant(0)); connect(&this->_variant, &Fact::rawValueChanged, this, &MeasurementComplexItem::_changeVariant); + // Select first variant as route. this->_route.swap(this->_variantVector.first()); emit routeChanged(); @@ -817,6 +789,6 @@ bool MeasurementComplexItem::calculating() const { bool MeasurementComplexItem::editing() const { return _editing(this->_state); } -bool MeasurementComplexItem::ready() const { return _ready(this->_state); } +bool MeasurementComplexItem::idle() const { return _idle(this->_state); } bool MeasurementComplexItem::followTerrain() const { return _followTerrain; } diff --git a/src/MeasurementComplexItem/MeasurementComplexItem.h b/src/MeasurementComplexItem/MeasurementComplexItem.h index f6fc98eff..836ec2ded 100644 --- a/src/MeasurementComplexItem/MeasurementComplexItem.h +++ b/src/MeasurementComplexItem/MeasurementComplexItem.h @@ -41,7 +41,7 @@ public: generatorNameListChanged) Q_PROPERTY(bool calculating READ calculating NOTIFY calculatingChanged) Q_PROPERTY(bool editing READ editing NOTIFY editingChanged) - Q_PROPERTY(bool ready READ ready NOTIFY readyChanged) + Q_PROPERTY(bool idle READ idle NOTIFY idleChanged) Q_PROPERTY( routing::GeneratorBase *generator READ generator NOTIFY generatorChanged) Q_PROPERTY(int generatorIndex READ generatorIndex NOTIFY generatorChanged) @@ -94,9 +94,9 @@ public: virtual QString abbreviation(void) const override final; // Generator - bool registerGenerator(const QString &name, routing::GeneratorBase *g); - bool unregisterGenerator(const QString &name); - bool unregisterGenerator(int index); + bool addGenerator(const QString &name, routing::GeneratorBase *g); + bool removeGenerator(const QString &name); + bool removeGenerator(int index); Q_INVOKABLE bool switchToGenerator(const QString &name); Q_INVOKABLE bool switchToGenerator(int index); QStringList generatorNameList(); @@ -137,7 +137,7 @@ public: bool calculating() const; bool editing() const; - bool ready() const; + bool idle() const; bool followTerrain() const; static const char *settingsGroup; @@ -154,7 +154,7 @@ signals: void calculatingChanged(); void editingChanged(); - void readyChanged(); + void idleChanged(); void areaDataChanged(); void routeChanged(); @@ -173,7 +173,7 @@ private: void _setAreaData(PtrAreaData data); static bool _calculating(STATE state); static bool _editing(STATE state); - static bool _ready(STATE state); + static bool _idle(STATE state); // Hirarcical stuff. PlanMasterController *_masterController; diff --git a/src/MeasurementComplexItem/geometry/GeoArea.cc b/src/MeasurementComplexItem/geometry/GeoArea.cc index bcc74ca0a..2b4d5c657 100644 --- a/src/MeasurementComplexItem/geometry/GeoArea.cc +++ b/src/MeasurementComplexItem/geometry/GeoArea.cc @@ -17,13 +17,16 @@ const char *GeoArea::settingsGroup = "GeoArea"; GeoArea::GeoArea(QObject *parent) : QGCMapPolygon(parent) { init(); } GeoArea::GeoArea(const GeoArea &other, QObject *parent) - : QGCMapPolygon(other, parent), _errorString(other._errorString) { + : QGCMapPolygon(other, parent) { init(); + _errorString = other._errorString; } GeoArea &GeoArea::operator=(const GeoArea &other) { QGCMapPolygon::operator=(other); + _errorString = other._errorString; + return *this; } @@ -63,7 +66,33 @@ bool GeoArea::isCorrect() { QString GeoArea::errorString() const { return this->_errorString; } -void GeoArea::init() { this->setObjectName(wimaAreaName); } +bool GeoArea::covers(const QGeoCoordinate &c) { + if (GeoArea::isCorrect()) { + auto origin = this->pathModel().value(0)->coordinate(); + snake::FPolygon polygonENU; + snake::areaToEnu(origin, this->pathModel(), polygonENU); + snake::FPoint cENU; + snake::toENU(origin, c, cENU); + return bg::covered_by(cENU, polygonENU); + } else { + return false; + } +} + +void GeoArea::init() { + this->setObjectName(wimaAreaName); + // connect(this, &GeoArea::pathChanged, [this] { + // if (this->objectName() != "Tile") { + // qDebug() << this->objectName() << " path: " << this->path() << "\n"; + // } + // }); + // connect(this, &GeoArea::centerChanged, [this] { + // if (this->objectName() != "Tile") { + // qDebug() << this->objectName() << " center: " << this->center() << + // "\n"; + // } + // }); +} void GeoArea::setErrorString(const QString &str) { this->_errorString = str; diff --git a/src/MeasurementComplexItem/geometry/GeoArea.h b/src/MeasurementComplexItem/geometry/GeoArea.h index ca2f77ea5..a724c3674 100644 --- a/src/MeasurementComplexItem/geometry/GeoArea.h +++ b/src/MeasurementComplexItem/geometry/GeoArea.h @@ -27,6 +27,13 @@ public: Q_INVOKABLE virtual bool isCorrect(); Q_INVOKABLE QString errorString() const; + //! + //! \brief covers Checks if GeoArea covers c. + //! \param c + //! \return Returns true if c is inside, or on the border of GeoArea. + //! + Q_INVOKABLE bool covers(const QGeoCoordinate &c); + // static Members static const char *wimaAreaName; static const char *areaTypeName; diff --git a/src/MeasurementComplexItem/geometry/MeasurementArea.cc b/src/MeasurementComplexItem/geometry/MeasurementArea.cc index a09c36b1c..e11716f97 100644 --- a/src/MeasurementComplexItem/geometry/MeasurementArea.cc +++ b/src/MeasurementComplexItem/geometry/MeasurementArea.cc @@ -23,7 +23,7 @@ TileData &TileData::operator=(const TileData &other) { const auto *obj = other.tiles[i]; const auto *tile = qobject_cast(obj); if (tile != nullptr) { - this->tiles.append(new SnakeTile(*tile, this)); + this->tiles.append(tile->clone(this)); } else { qCWarning(MeasurementAreaLog) << "TileData::operator=: nullptr"; } @@ -103,18 +103,41 @@ MeasurementArea::MeasurementArea(const MeasurementArea &other, QObject *parent) _showTiles(SettingsFact(settingsGroup, _metaDataMap[showTilesName], this /* QObject parent */)), _state(STATE::IDLE) { + init(); + disableUpdate(); + _tileHeight = other._tileHeight; _tileWidth = other._tileWidth; _minTileAreaPercent = other._minTileAreaPercent; _showTiles = other._showTiles; - _progress = other._progress; - _tileData = other._tileData; - init(); + if (other.ready()) { + _progress = other._progress; + _tileData = other._tileData; + enableUpdate(); + } else { + enableUpdate(); + doUpdate(); + } } MeasurementArea &MeasurementArea::operator=(const MeasurementArea &other) { GeoArea::operator=(other); + + disableUpdate(); + _tileHeight = other._tileHeight; + _tileWidth = other._tileWidth; + _minTileAreaPercent = other._minTileAreaPercent; + _showTiles = other._showTiles; + + if (other.ready()) { + _progress = other._progress; + _tileData = other._tileData; + enableUpdate(); + } else { + enableUpdate(); + doUpdate(); + } return *this; } diff --git a/src/MeasurementComplexItem/geometry/SafeArea.cc b/src/MeasurementComplexItem/geometry/SafeArea.cc index 1cdf1a504..8d718933f 100644 --- a/src/MeasurementComplexItem/geometry/SafeArea.cc +++ b/src/MeasurementComplexItem/geometry/SafeArea.cc @@ -73,7 +73,7 @@ void SafeArea::putDepotInside() { bool SafeArea::setDepot(const QGeoCoordinate &newDepot) { if (_depot.latitude() != newDepot.latitude() || _depot.longitude() != newDepot.longitude()) { - if (this->containsCoordinate(newDepot)) { + if (this->covers(newDepot)) { _depot = newDepot; _depot.setAltitude(0); emit depotChanged(); @@ -125,7 +125,7 @@ bool SafeArea::loadFromJson(const QJsonObject &json, QString &errorString) { bool SafeArea::isCorrect() { if (GeoArea::isCorrect()) { if (this->_depot.isValid()) { - if (this->containsCoordinate(this->_depot)) { + if (this->covers(this->_depot)) { return true; } else { setErrorString(tr("Depot outside Safe Area")); diff --git a/src/MeasurementComplexItem/nemo_interface/SnakeTile.cpp b/src/MeasurementComplexItem/nemo_interface/SnakeTile.cpp index aae74f6a6..febd68cfd 100644 --- a/src/MeasurementComplexItem/nemo_interface/SnakeTile.cpp +++ b/src/MeasurementComplexItem/nemo_interface/SnakeTile.cpp @@ -1,10 +1,10 @@ #include "SnakeTile.h" -SnakeTile::SnakeTile(QObject *parent) : GeoArea(parent) {} +SnakeTile::SnakeTile(QObject *parent) : GeoArea(parent) { init(); } SnakeTile::SnakeTile(const SnakeTile &other, QObject *parent) - : GeoArea(parent) { - *this = other; + : GeoArea(other, parent) { + init(); } SnakeTile::~SnakeTile() {} @@ -18,3 +18,5 @@ SnakeTile *SnakeTile::clone(QObject *parent) const { } void SnakeTile::push_back(const QGeoCoordinate &c) { this->appendVertex(c); } + +void SnakeTile::init() { this->setObjectName("Tile"); } diff --git a/src/MeasurementComplexItem/nemo_interface/SnakeTile.h b/src/MeasurementComplexItem/nemo_interface/SnakeTile.h index 8db2e7066..1beee1f93 100644 --- a/src/MeasurementComplexItem/nemo_interface/SnakeTile.h +++ b/src/MeasurementComplexItem/nemo_interface/SnakeTile.h @@ -16,4 +16,7 @@ public: virtual SnakeTile *clone(QObject *parent) const; void push_back(const QGeoCoordinate &c); + +private: + void init(); }; diff --git a/src/MeasurementComplexItem/qml/CircularGeneratorMapVisual.qml b/src/MeasurementComplexItem/qml/CircularGeneratorMapVisual.qml index 7455e0e0f..76142d597 100644 --- a/src/MeasurementComplexItem/qml/CircularGeneratorMapVisual.qml +++ b/src/MeasurementComplexItem/qml/CircularGeneratorMapVisual.qml @@ -1,5 +1,6 @@ import QtQuick 2.0 import QGroundControl 1.0 +import QtLocation 5.11 Item { id: _root @@ -11,74 +12,53 @@ Item { property var generator property bool checked: false - property var _referenceComponent: undefined signal clicked() - onVisibleChanged: { - if (visible){ - _addRefPoint() - } else { - _destroyRefPoint() - } - } - - Component.onCompleted: { - if (visible){ - _addRefPoint() - } - } + Item { + id: refPointItem - Component.onDestruction: { - _destroyRefPoint() - } + property var reference: generator.reference - function _addRefPoint(){ - if (!_referenceComponent){ - _referenceComponent = refPointComponent.createObject(_root) - map.addMapItem(_referenceComponent) + onReferenceChanged: { + if (mapItem.coordinate !== reference){ + mapItem.coordinate = reference + } } - } - function _destroyRefPoint(){ - if (_referenceComponent){ - map.removeMapItem(_referenceComponent) - _referenceComponent.destroy() - _referenceComponent = undefined - } - } + MapQuickItem { + id: mapItem - // Ref. point (Base Station) - Component { - id: refPointComponent - DragCoordinate { - id: dragCoordinate + coordinate: _root.generator.reference + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY + visible: refPointItem.visible + z: QGroundControl.zOrderMapItems - property var ref: _root.generator.reference + sourceItem: + MissionItemIndexLabel { + checked: true + label: qsTr("Reference") + highlightSelected: true + onClicked: _root.clicked(0) + visible: mapItem.visible + z: mapItem.z + } + } - map: _root.map - z: QGroundControl.zOrderMapItems - checked: _root.checked - coordinate: ref + ItemDragger { + anchor: mapItem + z: QGroundControl.zOrderMapItems+1 + draggable: true - onDragReleased: { - syncAndBind() - } - Component.onCompleted: { - syncAndBind() - } - onClicked: { - _root.clicked() + onDragStop:{ + _root.generator.reference = mapItem.coordinate } + } - function syncAndBind(){ - if (coordinate.latitude !== ref.latitude || - coordinate.longitude !== ref.longitude){ - _root.generator.reference = coordinate - } - coordinate = Qt.binding(function(){return _root.generator.reference}) - } + Component.onCompleted: { + _root.map.addMapItem(mapItem) } } } diff --git a/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml b/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml index 6b7986078..8e94bd5d0 100644 --- a/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml +++ b/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml @@ -28,10 +28,12 @@ Item { property bool _editing: _missionItem.editing property var _generator: _missionItem.generator - property var _transectsComponent: undefined - property var _entryCoordinate: undefined - property var _exitCoordinate: undefined - property var _generatorVisuals: undefined + property var _routeObject: undefined + property var _entryCoordinateObject: undefined + property var _exitCoordinateObject: undefined + property var _generatorObject: undefined + property var _entryArrowObject: undefined + property var _exitArrowObject: undefined property bool _isCurrentItem: _missionItem.isCurrentItem @@ -53,19 +55,23 @@ Item { Component.onCompleted: { console.assert(map != undefined, "please set the map property") - _addEntryCoordinate() - _addExitCoordinate() - _addTransectsComponent() - _addGeneratorVisuals() var bbox = boundingBox() _missionItem.areaData.initialize(bbox[0], bbox[1]) +// _addEntryCoordinate() +// _addExitCoordinate() + _addTransects() + _addGeneratorVisuals() + _addEntryArrow() + _addExitArrow() } Component.onDestruction: { - _destroyEntryCoordinate() - _destroyExitCoordinate() - _destroyTransectsComponent() +// _destroyEntryCoordinate() +// _destroyExitCoordinate() + _destroyTransects() _destroyGeneratorVisuals() + _destroyEntryArrow() + _destroyExitArrow() } on_GeneratorChanged: { @@ -78,11 +84,10 @@ Item { id: visualTransectsComponent MapPolyline { + visible: !_missionItem.editing line.color: "white" line.width: 2 path: _missionItem.route - - onPathChanged: console.log("path:" + path) } } @@ -126,6 +131,37 @@ Item { } } + // Entry arrow + Component { + id: entryArrowComponent + + MapLineArrow { + property int length: _missionItem.route.length + property var route: _missionItem.route + + fromCoord: length > 1 ? route[0] : QtPositioning.coordinate() + toCoord: length > 1 ? route[1] : QtPositioning.coordinate() + arrowPosition: 2 + visible: length > 1 && !_missionItem.editing + opacity: _root.opacity + } + } + + // Exit arrow + Component { + id: exitArrowComponent + + MapLineArrow { + property int length: _missionItem.route.length + property var route: _missionItem.route + + fromCoord: length > 3 ? route[length-2] : QtPositioning.coordinate() + toCoord: length > 3 ? route[length-1] : QtPositioning.coordinate() + arrowPosition: 2 + visible: length > 3 && !_missionItem.editing + opacity: _root.opacity + } + } // GeoAreas Repeater { @@ -138,76 +174,101 @@ Item { // Generator visuals function _addGeneratorVisuals(){ - if (_generator.mapVisualQml && !_generatorVisuals) { + if (_generator.mapVisualQml && !_generatorObject) { var component = Qt.createComponent(_generator.mapVisualQml) if (component.status === Component.Error) { console.log("Error loading Qml: ", _generator.mapVisualQml, component.errorString()) } else { - _generatorVisuals = - component.createObject(_root, { - "map": _root.map, - "generator": _root._generator, - "checked": Qt.binding( - function(){ - return _root._isCurrentItem - }) - }) - _generatorVisuals.clicked.connect( + _generatorObject = component.createObject(_root, { + "map": _root.map, + "generator": _root._generator, + "checked": Qt.binding(function(){return _root._isCurrentItem}) + }) + _generatorObject.clicked.connect( function(){_root.clicked(_missionItem.sequenceNumber)}) } } } function _destroyGeneratorVisuals(){ - if(_generatorVisuals){ - _generatorVisuals.destroy() - _generatorVisuals = undefined + if(_generatorObject){ + _generatorObject.destroy() + _generatorObject = undefined } } - function _addTransectsComponent(){ - if (!_transectsComponent){ - _transectsComponent = visualTransectsComponent.createObject(_root) - map.addMapItem(_transectsComponent) + function _addTransects(){ + if (!_routeObject){ + _routeObject= visualTransectsComponent.createObject(_root) + map.addMapItem(_routeObject) } } function _addExitCoordinate(){ - if (!_exitCoordinate){ - _exitCoordinate = exitPointComponent.createObject(_root) - map.addMapItem(_exitCoordinate) + if (!_exitCoordinateObject){ + _exitCoordinateObject = exitPointComponent.createObject(_root) + map.addMapItem(_exitCoordinateObject) } } function _addEntryCoordinate(){ - if (!_entryCoordinate){ - _entryCoordinate = entryPointComponent.createObject(_root) - map.addMapItem(_entryCoordinate) + if (!_entryCoordinateObject){ + _entryCoordinateObject = entryPointComponent.createObject(_root) + map.addMapItem(_entryCoordinateObject) + } + } + + function _addEntryArrow(){ + if (!_entryArrowObject){ + _entryArrowObject = entryArrowComponent.createObject(_root) + map.addMapItem(_entryArrowObject) } } + function _addExitArrow(){ + if (!_exitArrowObject){ + _exitArrowObject = exitArrowComponent.createObject(_root) + map.addMapItem(_exitArrowObject) + } + } function _destroyEntryCoordinate(){ - if (_entryCoordinate){ - map.removeMapItem(_entryCoordinate) - _entryCoordinate.destroy() - _entryCoordinate = undefined + if (_entryCoordinateObject){ + map.removeMapItem(_entryCoordinateObject) + _entryCoordinateObject.destroy() + _entryCoordinateObject = undefined } } function _destroyExitCoordinate(){ - if (_exitCoordinate){ - map.removeMapItem(_exitCoordinate) - _exitCoordinate.destroy() - _exitCoordinate = undefined + if (_exitCoordinateObject){ + map.removeMapItem(_exitCoordinateObject) + _exitCoordinateObject.destroy() + _exitCoordinateObject = undefined + } + } + + function _destroyTransects(){ + if (_routeObject){ + map.removeMapItem(_routeObject) + _routeObject.destroy() + _routeObject= undefined + } + } + + function _destroyEntryArrow(){ + if (_entryArrowObject){ + map.removeMapItem(_entryArrowObject) + _entryArrowObject.destroy() + _entryArrowObject = undefined } } - function _destroyTransectsComponent(){ - if (_transectsComponent){ - map.removeMapItem(_transectsComponent) - _transectsComponent.destroy() - _transectsComponent = undefined + function _destroyExitArrow(){ + if (_exitArrowObject){ + map.removeMapItem(_exitArrowObject) + _exitArrowObject.destroy() + _exitArrowObject = undefined } } diff --git a/src/MeasurementComplexItem/qml/ParameterEditor.qml b/src/MeasurementComplexItem/qml/ParameterEditor.qml index f4a23f7c2..be7897e08 100644 --- a/src/MeasurementComplexItem/qml/ParameterEditor.qml +++ b/src/MeasurementComplexItem/qml/ParameterEditor.qml @@ -68,29 +68,36 @@ ColumnLayout { } GridLayout{ Layout.columnSpan: 2 + Layout.fillWidth: true + Layout.maximumWidth: parent.width columnSpacing: _margin rowSpacing: _margin - columns: 6 + ExclusiveGroup{id:variantGroup} Repeater{ id: variantRepeater - property var fact: missionItem.variant - property int variant: fact.value property var names: missionItem.variantNames property int len: missionItem.variantNames.length model: len delegate: QGCRadioButton { - checked: index === variantRepeater.variant + checked: index === variant text: variantRepeater.names[index] ? variantRepeater.names[index]: "" + property int variant: missionItem.variant.value + + onVariantChanged: { + if (variant === index){ + checked = true + } + } + onCheckedChanged: { - if (checked){ + if (checked && variant !== index){ missionItem.variant.value = index } - checked = Qt.binding(function(){ return index === variantRepeater.variant}) } } } // variant repeater @@ -135,6 +142,13 @@ ColumnLayout { visible: generatorHeader.checked } + QGCButton{ + text:qsTr("Reverse") + onClicked: missionItem.reverseRoute() + Layout.columnSpan: 2 + Layout.fillWidth: true + } + // bussy indicator ColumnLayout{ Layout.fillWidth: true diff --git a/src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml b/src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml index ed268c6b6..78985cc45 100644 --- a/src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml +++ b/src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml @@ -46,57 +46,47 @@ Item { interiorOpacity: 0.3 } - Loader { - id:depotLoader - sourceComponent: depotComponent - } - - // Depot Point. - Component { - id: depotComponent - - Item { - id: depotMapItem + Item { + id: depotMapItem - MapQuickItem { - id: mapItem + MapQuickItem { + id: mapItem - coordinate: _root.geoArea.depot - anchorPoint.x: sourceItem.anchorPointX - anchorPoint.y: sourceItem.anchorPointY - visible: true - z: QGroundControl.zOrderMapItems + coordinate: _root.geoArea.depot + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY + visible: depotMapItem.visible + z: QGroundControl.zOrderMapItems - Component.onCompleted: { - coordinate = Qt.binding(function(){return _root.geoArea.depot}) - } + Component.onCompleted: { + coordinate = Qt.binding(function(){return _root.geoArea.depot}) + } - sourceItem: - MissionItemIndexLabel { - checked: true - label: qsTr("Depot") - highlightSelected: true - onClicked: _root.clicked(0) - visible: mapItem.visible - z: mapItem.z - } + sourceItem: + MissionItemIndexLabel { + checked: true + label: qsTr("Depot") + highlightSelected: true + onClicked: _root.clicked(0) + visible: mapItem.visible + z: mapItem.z } + } - ItemDragger { - anchor: mapItem - z: QGroundControl.zOrderMapItems+1 - draggable: _root.geoArea.interactive + ItemDragger { + anchor: mapItem + z: QGroundControl.zOrderMapItems+1 + draggable: _root.geoArea.interactive - onDragStop:{ - _root.geoArea.depot = mapItem.coordinate - mapItem.coordinate = Qt.binding(function(){return _root.geoArea.depot}) - } + onDragStop:{ + _root.geoArea.depot = mapItem.coordinate + mapItem.coordinate = Qt.binding(function(){return _root.geoArea.depot}) } + } - Component.onCompleted: { - _root.map.addMapItem(mapItem) - } + Component.onCompleted: { + _root.map.addMapItem(mapItem) } } } diff --git a/src/MissionManager/QGCMapPolygon.cc b/src/MissionManager/QGCMapPolygon.cc index 17122057e..e3d2d169f 100644 --- a/src/MissionManager/QGCMapPolygon.cc +++ b/src/MissionManager/QGCMapPolygon.cc @@ -8,576 +8,560 @@ ****************************************************************************/ #include "QGCMapPolygon.h" -#include "QGCGeo.h" #include "JsonHelper.h" -#include "QGCQGeoCoordinate.h" #include "QGCApplication.h" -#include "ShapeFileHelper.h" +#include "QGCGeo.h" #include "QGCLoggingCategory.h" +#include "QGCQGeoCoordinate.h" +#include "ShapeFileHelper.h" -#include #include +#include +#include +#include #include #include -#include -#include -const char* QGCMapPolygon::jsonPolygonKey = "polygon"; +const char *QGCMapPolygon::jsonPolygonKey = "polygon"; -QGCMapPolygon::QGCMapPolygon(QObject* parent) - : QObject (parent) - , _dirty (false) - , _centerDrag (false) - , _ignoreCenterUpdates (false) - , _interactive (false) - , _resetActive (false) -{ - _init(); +QGCMapPolygon::QGCMapPolygon(QObject *parent) + : QObject(parent), _dirty(false), _centerDrag(false), + _ignoreCenterUpdates(false), _interactive(false), _resetActive(false) { + _init(); } -QGCMapPolygon::QGCMapPolygon(const QGCMapPolygon& other, QObject* parent) - : QObject (parent) - , _dirty (false) - , _centerDrag (false) - , _ignoreCenterUpdates (false) - , _interactive (false) - , _resetActive (false) -{ - *this = other; - - _init(); +QGCMapPolygon::QGCMapPolygon(const QGCMapPolygon &other, QObject *parent) + : QObject(parent), _dirty(false), _centerDrag(false), + _ignoreCenterUpdates(false), _interactive(false), _resetActive(false) { + _init(); + *this = other; } -void QGCMapPolygon::_init(void) -{ - connect(&_polygonModel, &QmlObjectListModel::dirtyChanged, this, &QGCMapPolygon::_polygonModelDirtyChanged); - connect(&_polygonModel, &QmlObjectListModel::countChanged, this, &QGCMapPolygon::_polygonModelCountChanged); +void QGCMapPolygon::_init(void) { + connect(&_polygonModel, &QmlObjectListModel::dirtyChanged, this, + &QGCMapPolygon::_polygonModelDirtyChanged); + connect(&_polygonModel, &QmlObjectListModel::countChanged, this, + &QGCMapPolygon::_polygonModelCountChanged); - connect(this, &QGCMapPolygon::pathChanged, this, &QGCMapPolygon::_updateCenter); - connect(this, &QGCMapPolygon::countChanged, this, &QGCMapPolygon::isValidChanged); - connect(this, &QGCMapPolygon::countChanged, this, &QGCMapPolygon::isEmptyChanged); + connect(this, &QGCMapPolygon::pathChanged, this, + &QGCMapPolygon::_updateCenter); + connect(this, &QGCMapPolygon::countChanged, this, + &QGCMapPolygon::isValidChanged); + connect(this, &QGCMapPolygon::countChanged, this, + &QGCMapPolygon::isEmptyChanged); } -const QGCMapPolygon& QGCMapPolygon::operator=(const QGCMapPolygon& other) -{ - clear(); +const QGCMapPolygon &QGCMapPolygon::operator=(const QGCMapPolygon &other) { + clear(); - QVariantList vertices = other.path(); - QList rgCoord; - for (const QVariant& vertexVar: vertices) { - rgCoord.append(vertexVar.value()); - } - appendVertices(rgCoord); + QVariantList vertices = other.path(); + QList rgCoord; + for (const QVariant &vertexVar : vertices) { + rgCoord.append(vertexVar.value()); + } + appendVertices(rgCoord); - setDirty(true); + setDirty(true); - return *this; + return *this; } -void QGCMapPolygon::clear(void) -{ - // Bug workaround, see below - while (_polygonPath.count() > 1) { - _polygonPath.takeLast(); - } - emit pathChanged(); +void QGCMapPolygon::clear(void) { + // Bug workaround, see below + while (_polygonPath.count() > 1) { + _polygonPath.takeLast(); + } + emit pathChanged(); - // Although this code should remove the polygon from the map it doesn't. There appears - // to be a bug in QGCMapPolygon which causes it to not be redrawn if the list is empty. So - // we work around it by using the code above to remove all but the last point which in turn - // will cause the polygon to go away. - _polygonPath.clear(); + // Although this code should remove the polygon from the map it doesn't. There + // appears to be a bug in QGCMapPolygon which causes it to not be redrawn if + // the list is empty. So we work around it by using the code above to remove + // all but the last point which in turn will cause the polygon to go away. + _polygonPath.clear(); - _polygonModel.clearAndDeleteContents(); + _polygonModel.clearAndDeleteContents(); - emit cleared(); + emit cleared(); - setDirty(true); + setDirty(true); } -void QGCMapPolygon::adjustVertex(int vertexIndex, const QGeoCoordinate coordinate) -{ - _polygonPath[vertexIndex] = QVariant::fromValue(coordinate); - _polygonModel.value(vertexIndex)->setCoordinate(coordinate); - if (!_centerDrag) { - // When dragging center we don't signal path changed until all vertices are updated - emit pathChanged(); - } - setDirty(true); +void QGCMapPolygon::adjustVertex(int vertexIndex, + const QGeoCoordinate coordinate) { + _polygonPath[vertexIndex] = QVariant::fromValue(coordinate); + _polygonModel.value(vertexIndex) + ->setCoordinate(coordinate); + if (!_centerDrag) { + // When dragging center we don't signal path changed until all vertices are + // updated + emit pathChanged(); + } + setDirty(true); } -void QGCMapPolygon::setDirty(bool dirty) -{ - if (_dirty != dirty) { - _dirty = dirty; - if (!dirty) { - _polygonModel.setDirty(false); - } - emit dirtyChanged(dirty); +void QGCMapPolygon::setDirty(bool dirty) { + if (_dirty != dirty) { + _dirty = dirty; + if (!dirty) { + _polygonModel.setDirty(false); } + emit dirtyChanged(dirty); + } } -QGeoCoordinate QGCMapPolygon::_coordFromPointF(const QPointF& point) const -{ - QGeoCoordinate coord; +QGeoCoordinate QGCMapPolygon::_coordFromPointF(const QPointF &point) const { + QGeoCoordinate coord; - if (_polygonPath.count() > 0) { - QGeoCoordinate tangentOrigin = _polygonPath[0].value(); - convertNedToGeo(-point.y(), point.x(), 0, tangentOrigin, &coord); - } + if (_polygonPath.count() > 0) { + QGeoCoordinate tangentOrigin = _polygonPath[0].value(); + convertNedToGeo(-point.y(), point.x(), 0, tangentOrigin, &coord); + } - return coord; + return coord; } -QPointF QGCMapPolygon::_pointFFromCoord(const QGeoCoordinate& coordinate) const -{ - if (_polygonPath.count() > 0) { - double y, x, down; - QGeoCoordinate tangentOrigin = _polygonPath[0].value(); +QPointF +QGCMapPolygon::_pointFFromCoord(const QGeoCoordinate &coordinate) const { + if (_polygonPath.count() > 0) { + double y, x, down; + QGeoCoordinate tangentOrigin = _polygonPath[0].value(); - convertGeoToNed(coordinate, tangentOrigin, &y, &x, &down); - return QPointF(x, -y); - } + convertGeoToNed(coordinate, tangentOrigin, &y, &x, &down); + return QPointF(x, -y); + } - return QPointF(); + return QPointF(); } -QPolygonF QGCMapPolygon::_toPolygonF(void) const -{ - QPolygonF polygon; +QPolygonF QGCMapPolygon::_toPolygonF(void) const { + QPolygonF polygon; - if (_polygonPath.count() > 2) { - for (int i=0; i<_polygonPath.count(); i++) { - polygon.append(_pointFFromCoord(_polygonPath[i].value())); - } + if (_polygonPath.count() > 2) { + for (int i = 0; i < _polygonPath.count(); i++) { + polygon.append(_pointFFromCoord(_polygonPath[i].value())); } + } - return polygon; + return polygon; } -bool QGCMapPolygon::containsCoordinate(const QGeoCoordinate& coordinate) const -{ - if (_polygonPath.count() > 2) { - return _toPolygonF().containsPoint(_pointFFromCoord(coordinate), Qt::OddEvenFill); - } else { - return false; - } +bool QGCMapPolygon::containsCoordinate(const QGeoCoordinate &coordinate) const { + if (_polygonPath.count() > 2) { + return _toPolygonF().containsPoint(_pointFFromCoord(coordinate), + Qt::OddEvenFill); + } else { + return false; + } } -void QGCMapPolygon::setPath(const QList& path) -{ - _polygonPath.clear(); - _polygonModel.clearAndDeleteContents(); - for(const QGeoCoordinate& coord: path) { - _polygonPath.append(QVariant::fromValue(coord)); - _polygonModel.append(new QGCQGeoCoordinate(coord, this)); - } +void QGCMapPolygon::setPath(const QList &path) { + _polygonPath.clear(); + _polygonModel.clearAndDeleteContents(); + for (const QGeoCoordinate &coord : path) { + _polygonPath.append(QVariant::fromValue(coord)); + _polygonModel.append(new QGCQGeoCoordinate(coord, this)); + } - setDirty(true); - emit pathChanged(); + setDirty(true); + emit pathChanged(); } -void QGCMapPolygon::setPath(const QVariantList& path) -{ - _polygonPath = path; +void QGCMapPolygon::setPath(const QVariantList &path) { + _polygonPath = path; - _polygonModel.clearAndDeleteContents(); - for (int i=0; i<_polygonPath.count(); i++) { - _polygonModel.append(new QGCQGeoCoordinate(_polygonPath[i].value(), this)); - } + _polygonModel.clearAndDeleteContents(); + for (int i = 0; i < _polygonPath.count(); i++) { + _polygonModel.append( + new QGCQGeoCoordinate(_polygonPath[i].value(), this)); + } - setDirty(true); - emit pathChanged(); + setDirty(true); + emit pathChanged(); } -void QGCMapPolygon::saveToJson(QJsonObject& json) -{ - QJsonValue jsonValue; +void QGCMapPolygon::saveToJson(QJsonObject &json) { + QJsonValue jsonValue; - JsonHelper::saveGeoCoordinateArray(_polygonPath, false /* writeAltitude*/, jsonValue); - json.insert(jsonPolygonKey, jsonValue); - setDirty(false); + JsonHelper::saveGeoCoordinateArray(_polygonPath, false /* writeAltitude*/, + jsonValue); + json.insert(jsonPolygonKey, jsonValue); + setDirty(false); } -bool QGCMapPolygon::loadFromJson(const QJsonObject& json, bool required, QString& errorString) -{ - errorString.clear(); - clear(); +bool QGCMapPolygon::loadFromJson(const QJsonObject &json, bool required, + QString &errorString) { + errorString.clear(); + clear(); - if (required) { - if (!JsonHelper::validateRequiredKeys(json, QStringList(jsonPolygonKey), errorString)) { - return false; - } - } else if (!json.contains(jsonPolygonKey)) { - return true; + if (required) { + if (!JsonHelper::validateRequiredKeys(json, QStringList(jsonPolygonKey), + errorString)) { + return false; } + } else if (!json.contains(jsonPolygonKey)) { + return true; + } - if (!JsonHelper::loadGeoCoordinateArray(json[jsonPolygonKey], false /* altitudeRequired */, _polygonPath, errorString)) { - return false; - } + if (!JsonHelper::loadGeoCoordinateArray(json[jsonPolygonKey], + false /* altitudeRequired */, + _polygonPath, errorString)) { + return false; + } - for (int i=0; i<_polygonPath.count(); i++) { - _polygonModel.append(new QGCQGeoCoordinate(_polygonPath[i].value(), this)); - } + for (int i = 0; i < _polygonPath.count(); i++) { + _polygonModel.append( + new QGCQGeoCoordinate(_polygonPath[i].value(), this)); + } - setDirty(false); - emit pathChanged(); + setDirty(false); + emit pathChanged(); - return true; + return true; } -QList QGCMapPolygon::coordinateList(void) const -{ - QList coords; +QList QGCMapPolygon::coordinateList(void) const { + QList coords; - for (int i=0; i<_polygonPath.count(); i++) { - coords.append(_polygonPath[i].value()); - } + for (int i = 0; i < _polygonPath.count(); i++) { + coords.append(_polygonPath[i].value()); + } - return coords; + return coords; } -void QGCMapPolygon::splitPolygonSegment(int vertexIndex) -{ - int nextIndex = vertexIndex + 1; - if (nextIndex > _polygonPath.length() - 1) { - nextIndex = 0; - } +void QGCMapPolygon::splitPolygonSegment(int vertexIndex) { + int nextIndex = vertexIndex + 1; + if (nextIndex > _polygonPath.length() - 1) { + nextIndex = 0; + } - QGeoCoordinate firstVertex = _polygonPath[vertexIndex].value(); - QGeoCoordinate nextVertex = _polygonPath[nextIndex].value(); + QGeoCoordinate firstVertex = + _polygonPath[vertexIndex].value(); + QGeoCoordinate nextVertex = _polygonPath[nextIndex].value(); - double distance = firstVertex.distanceTo(nextVertex); - double azimuth = firstVertex.azimuthTo(nextVertex); - QGeoCoordinate newVertex = firstVertex.atDistanceAndAzimuth(distance / 2, azimuth); + double distance = firstVertex.distanceTo(nextVertex); + double azimuth = firstVertex.azimuthTo(nextVertex); + QGeoCoordinate newVertex = + firstVertex.atDistanceAndAzimuth(distance / 2, azimuth); - if (nextIndex == 0) { - appendVertex(newVertex); - } else { - _polygonModel.insert(nextIndex, new QGCQGeoCoordinate(newVertex, this)); - _polygonPath.insert(nextIndex, QVariant::fromValue(newVertex)); - emit pathChanged(); - } + if (nextIndex == 0) { + appendVertex(newVertex); + } else { + _polygonModel.insert(nextIndex, new QGCQGeoCoordinate(newVertex, this)); + _polygonPath.insert(nextIndex, QVariant::fromValue(newVertex)); + emit pathChanged(); + } } -void QGCMapPolygon::appendVertex(const QGeoCoordinate& coordinate) -{ - _polygonPath.append(QVariant::fromValue(coordinate)); - _polygonModel.append(new QGCQGeoCoordinate(coordinate, this)); - emit pathChanged(); +void QGCMapPolygon::appendVertex(const QGeoCoordinate &coordinate) { + _polygonPath.append(QVariant::fromValue(coordinate)); + _polygonModel.append(new QGCQGeoCoordinate(coordinate, this)); + emit pathChanged(); } -void QGCMapPolygon::appendVertices(const QList& coordinates) -{ - QList objects; +void QGCMapPolygon::appendVertices(const QList &coordinates) { + QList objects; - _beginResetIfNotActive(); - for (const QGeoCoordinate& coordinate: coordinates) { - objects.append(new QGCQGeoCoordinate(coordinate, this)); - _polygonPath.append(QVariant::fromValue(coordinate)); - } - _polygonModel.append(objects); - _endResetIfNotActive(); + _beginResetIfNotActive(); + for (const QGeoCoordinate &coordinate : coordinates) { + objects.append(new QGCQGeoCoordinate(coordinate, this)); + _polygonPath.append(QVariant::fromValue(coordinate)); + } + _polygonModel.append(objects); + _endResetIfNotActive(); - emit pathChanged(); + emit pathChanged(); } -void QGCMapPolygon::appendVertices(const QVariantList& varCoords) -{ - QList rgCoords; - for (const QVariant& varCoord: varCoords) { - rgCoords.append(varCoord.value()); - } - appendVertices(rgCoords); +void QGCMapPolygon::appendVertices(const QVariantList &varCoords) { + QList rgCoords; + for (const QVariant &varCoord : varCoords) { + rgCoords.append(varCoord.value()); + } + appendVertices(rgCoords); } -void QGCMapPolygon::_polygonModelDirtyChanged(bool dirty) -{ - if (dirty) { - setDirty(true); - } +void QGCMapPolygon::_polygonModelDirtyChanged(bool dirty) { + if (dirty) { + setDirty(true); + } } -void QGCMapPolygon::removeVertex(int vertexIndex) -{ - if (vertexIndex < 0 && vertexIndex > _polygonPath.length() - 1) { - qWarning() << "Call to removePolygonCoordinate with bad vertexIndex:count" << vertexIndex << _polygonPath.length(); - return; - } +void QGCMapPolygon::removeVertex(int vertexIndex) { + if (vertexIndex < 0 && vertexIndex > _polygonPath.length() - 1) { + qWarning() << "Call to removePolygonCoordinate with bad vertexIndex:count" + << vertexIndex << _polygonPath.length(); + return; + } - if (_polygonPath.length() <= 3) { - // Don't allow the user to trash the polygon - return; - } + if (_polygonPath.length() <= 3) { + // Don't allow the user to trash the polygon + return; + } - QObject* coordObj = _polygonModel.removeAt(vertexIndex); - coordObj->deleteLater(); - if(vertexIndex == _selectedVertexIndex) { - selectVertex(-1); - } else if (vertexIndex < _selectedVertexIndex) { - selectVertex(_selectedVertexIndex - 1); - } // else do nothing - keep current selected vertex + QObject *coordObj = _polygonModel.removeAt(vertexIndex); + coordObj->deleteLater(); + if (vertexIndex == _selectedVertexIndex) { + selectVertex(-1); + } else if (vertexIndex < _selectedVertexIndex) { + selectVertex(_selectedVertexIndex - 1); + } // else do nothing - keep current selected vertex - _polygonPath.removeAt(vertexIndex); - emit pathChanged(); + _polygonPath.removeAt(vertexIndex); + emit pathChanged(); } -void QGCMapPolygon::_polygonModelCountChanged(int count) -{ - emit countChanged(count); -} - -void QGCMapPolygon::_updateCenter(void) -{ - if (!_ignoreCenterUpdates) { - QGeoCoordinate center; - - if (_polygonPath.count() > 2) { - QPointF centroid(0, 0); - QPolygonF polygonF = _toPolygonF(); - for (int i=0; i 2) { + QPointF centroid(0, 0); + QPolygonF polygonF = _toPolygonF(); + for (int i = 0; i < polygonF.count(); i++) { + centroid += polygonF[i]; + } + center = _coordFromPointF(QPointF(centroid.x() / polygonF.count(), + centroid.y() / polygonF.count())); + } + if (_center != center) { + _center = center; + emit centerChanged(center); + } + } +} - for (int i=0; i(); - QGeoCoordinate newVertex = oldVertex.atDistanceAndAzimuth(distance, azimuth); - adjustVertex(i, newVertex); - } +void QGCMapPolygon::setCenter(QGeoCoordinate newCenter) { + if (newCenter != _center) { + _ignoreCenterUpdates = true; - if (_centerDrag) { - // When center dragging, signals from adjustVertext are not sent. So we need to signal here when all adjusting is complete. - emit pathChanged(); - } + // Adjust polygon vertices to new center + double distance = _center.distanceTo(newCenter); + double azimuth = _center.azimuthTo(newCenter); - _ignoreCenterUpdates = false; + for (int i = 0; i < count(); i++) { + QGeoCoordinate oldVertex = _polygonPath[i].value(); + QGeoCoordinate newVertex = + oldVertex.atDistanceAndAzimuth(distance, azimuth); + adjustVertex(i, newVertex); + } - _center = newCenter; - emit centerChanged(newCenter); + if (_centerDrag) { + // When center dragging, signals from adjustVertext are not sent. So we + // need to signal here when all adjusting is complete. + emit pathChanged(); } + + _ignoreCenterUpdates = false; + + _center = newCenter; + emit centerChanged(newCenter); + } } -void QGCMapPolygon::setCenterDrag(bool centerDrag) -{ - if (centerDrag != _centerDrag) { - _centerDrag = centerDrag; - emit centerDragChanged(centerDrag); - } +void QGCMapPolygon::setCenterDrag(bool centerDrag) { + if (centerDrag != _centerDrag) { + _centerDrag = centerDrag; + emit centerDragChanged(centerDrag); + } } -void QGCMapPolygon::setInteractive(bool interactive) -{ - if (_interactive != interactive) { - _interactive = interactive; - emit interactiveChanged(interactive); - } +void QGCMapPolygon::setInteractive(bool interactive) { + if (_interactive != interactive) { + _interactive = interactive; + emit interactiveChanged(interactive); + } } -QGeoCoordinate QGCMapPolygon::vertexCoordinate(int vertex) const -{ - if (vertex >= 0 && vertex < _polygonPath.count()) { - return _polygonPath[vertex].value(); - } else { - qWarning() << "QGCMapPolygon::vertexCoordinate bad vertex requested:count" << vertex << _polygonPath.count(); - return QGeoCoordinate(); - } +QGeoCoordinate QGCMapPolygon::vertexCoordinate(int vertex) const { + if (vertex >= 0 && vertex < _polygonPath.count()) { + return _polygonPath[vertex].value(); + } else { + qWarning() << "QGCMapPolygon::vertexCoordinate bad vertex requested:count" + << vertex << _polygonPath.count(); + return QGeoCoordinate(); + } } -QList QGCMapPolygon::nedPolygon(void) const -{ - QList nedPolygon; - - if (count() > 0) { - QGeoCoordinate tangentOrigin = vertexCoordinate(0); - - for (int i=0; i<_polygonModel.count(); i++) { - double y, x, down; - QGeoCoordinate vertex = vertexCoordinate(i); - if (i == 0) { - // This avoids a nan calculation that comes out of convertGeoToNed - x = y = 0; - } else { - convertGeoToNed(vertex, tangentOrigin, &y, &x, &down); - } - nedPolygon += QPointF(x, y); - } +QList QGCMapPolygon::nedPolygon(void) const { + QList nedPolygon; + + if (count() > 0) { + QGeoCoordinate tangentOrigin = vertexCoordinate(0); + + for (int i = 0; i < _polygonModel.count(); i++) { + double y, x, down; + QGeoCoordinate vertex = vertexCoordinate(i); + if (i == 0) { + // This avoids a nan calculation that comes out of convertGeoToNed + x = y = 0; + } else { + convertGeoToNed(vertex, tangentOrigin, &y, &x, &down); + } + nedPolygon += QPointF(x, y); } + } - return nedPolygon; + return nedPolygon; } +void QGCMapPolygon::offset(double distance) { + QList rgNewPolygon; -void QGCMapPolygon::offset(double distance) -{ - QList rgNewPolygon; + // I'm sure there is some beautiful famous algorithm to do this, but here is a + // brute force method - // I'm sure there is some beautiful famous algorithm to do this, but here is a brute force method + if (count() > 2) { + // Convert the polygon to NED + QList rgNedVertices = nedPolygon(); - if (count() > 2) { - // Convert the polygon to NED - QList rgNedVertices = nedPolygon(); + // Walk the edges, offsetting by the specified distance + QList rgOffsetEdges; + for (int i = 0; i < rgNedVertices.count(); i++) { + int lastIndex = i == rgNedVertices.count() - 1 ? 0 : i + 1; + QLineF offsetEdge; + QLineF originalEdge(rgNedVertices[i], rgNedVertices[lastIndex]); - // Walk the edges, offsetting by the specified distance - QList rgOffsetEdges; - for (int i=0; i rgCoords; - if (!ShapeFileHelper::loadPolygonFromFile(file, rgCoords, errorString)) { - qgcApp()->showAppMessage(errorString); - return false; - } +bool QGCMapPolygon::loadKMLOrSHPFile(const QString &file) { + QString errorString; + QList rgCoords; + if (!ShapeFileHelper::loadPolygonFromFile(file, rgCoords, errorString)) { + qgcApp()->showAppMessage(errorString); + return false; + } - _beginResetIfNotActive(); - clear(); - appendVertices(rgCoords); - _endResetIfNotActive(); + _beginResetIfNotActive(); + clear(); + appendVertices(rgCoords); + _endResetIfNotActive(); - return true; + return true; } -double QGCMapPolygon::area(void) const -{ - // https://www.mathopenref.com/coordpolygonarea2.html +double QGCMapPolygon::area(void) const { + // https://www.mathopenref.com/coordpolygonarea2.html - if (_polygonPath.count() < 3) { - return 0; - } + if (_polygonPath.count() < 3) { + return 0; + } - double coveredArea = 0.0; - QList nedVertices = nedPolygon(); - for (int i=0; i nedVertices = nedPolygon(); + for (int i = 0; i < nedVertices.count(); i++) { + if (i != 0) { + coveredArea += nedVertices[i - 1].x() * nedVertices[i].y() - + nedVertices[i].x() * nedVertices[i - 1].y(); + } else { + coveredArea += nedVertices.last().x() * nedVertices[i].y() - + nedVertices[i].x() * nedVertices.last().y(); } - return 0.5 * fabs(coveredArea); + } + return 0.5 * fabs(coveredArea); } -void QGCMapPolygon::verifyClockwiseWinding(void) -{ - if (_polygonPath.count() <= 2) { - return; - } +void QGCMapPolygon::verifyClockwiseWinding(void) { + if (_polygonPath.count() <= 2) { + return; + } - double sum = 0; - for (int i=0; i<_polygonPath.count(); i++) { - QGeoCoordinate coord1 = _polygonPath[i].value(); - QGeoCoordinate coord2 = (i == _polygonPath.count() - 1) ? _polygonPath[0].value() : _polygonPath[i+1].value(); + double sum = 0; + for (int i = 0; i < _polygonPath.count(); i++) { + QGeoCoordinate coord1 = _polygonPath[i].value(); + QGeoCoordinate coord2 = (i == _polygonPath.count() - 1) + ? _polygonPath[0].value() + : _polygonPath[i + 1].value(); - sum += (coord2.longitude() - coord1.longitude()) * (coord2.latitude() + coord1.latitude()); - } + sum += (coord2.longitude() - coord1.longitude()) * + (coord2.latitude() + coord1.latitude()); + } - if (sum < 0.0) { - // Winding is counter-clockwise and needs reversal + if (sum < 0.0) { + // Winding is counter-clockwise and needs reversal - QList rgReversed; - for (const QVariant& varCoord: _polygonPath) { - rgReversed.prepend(varCoord.value()); - } - - _beginResetIfNotActive(); - clear(); - appendVertices(rgReversed); - _endResetIfNotActive(); + QList rgReversed; + for (const QVariant &varCoord : _polygonPath) { + rgReversed.prepend(varCoord.value()); } + + _beginResetIfNotActive(); + clear(); + appendVertices(rgReversed); + _endResetIfNotActive(); + } } -void QGCMapPolygon::beginReset(void) -{ - _resetActive = true; - _polygonModel.beginReset(); +void QGCMapPolygon::beginReset(void) { + _resetActive = true; + _polygonModel.beginReset(); } -void QGCMapPolygon::endReset(void) -{ - _resetActive = false; - _polygonModel.endReset(); - emit pathChanged(); - emit centerChanged(_center); +void QGCMapPolygon::endReset(void) { + _resetActive = false; + _polygonModel.endReset(); + emit pathChanged(); + emit centerChanged(_center); } -void QGCMapPolygon::_beginResetIfNotActive(void) -{ - if (!_resetActive) { - beginReset(); - } +void QGCMapPolygon::_beginResetIfNotActive(void) { + if (!_resetActive) { + beginReset(); + } } -void QGCMapPolygon::_endResetIfNotActive(void) -{ - if (!_resetActive) { - endReset(); - } +void QGCMapPolygon::_endResetIfNotActive(void) { + if (!_resetActive) { + endReset(); + } } -QDomElement QGCMapPolygon::kmlPolygonElement(KMLDomDocument& domDocument) -{ +QDomElement QGCMapPolygon::kmlPolygonElement(KMLDomDocument &domDocument) { #if 0 @@ -599,55 +583,61 @@ QDomElement QGCMapPolygon::kmlPolygonElement(KMLDomDocument& domDocument) #endif - QDomElement polygonElement = domDocument.createElement("Polygon"); + QDomElement polygonElement = domDocument.createElement("Polygon"); - domDocument.addTextElement(polygonElement, "altitudeMode", "clampToGround"); + domDocument.addTextElement(polygonElement, "altitudeMode", "clampToGround"); - QDomElement outerBoundaryIsElement = domDocument.createElement("outerBoundaryIs"); - QDomElement linearRingElement = domDocument.createElement("LinearRing"); + QDomElement outerBoundaryIsElement = + domDocument.createElement("outerBoundaryIs"); + QDomElement linearRingElement = domDocument.createElement("LinearRing"); - outerBoundaryIsElement.appendChild(linearRingElement); - polygonElement.appendChild(outerBoundaryIsElement); + outerBoundaryIsElement.appendChild(linearRingElement); + polygonElement.appendChild(outerBoundaryIsElement); - QString coordString; - for (const QVariant& varCoord : _polygonPath) { - coordString += QStringLiteral("%1\n").arg(domDocument.kmlCoordString(varCoord.value())); - } - coordString += QStringLiteral("%1\n").arg(domDocument.kmlCoordString(_polygonPath.first().value())); - domDocument.addTextElement(linearRingElement, "coordinates", coordString); + QString coordString; + for (const QVariant &varCoord : _polygonPath) { + coordString += QStringLiteral("%1\n").arg( + domDocument.kmlCoordString(varCoord.value())); + } + coordString += QStringLiteral("%1\n").arg( + domDocument.kmlCoordString(_polygonPath.first().value())); + domDocument.addTextElement(linearRingElement, "coordinates", coordString); - return polygonElement; + return polygonElement; } -void QGCMapPolygon::setTraceMode(bool traceMode) -{ - if (traceMode != _traceMode) { - _traceMode = traceMode; - emit traceModeChanged(traceMode); - } +void QGCMapPolygon::setTraceMode(bool traceMode) { + if (traceMode != _traceMode) { + _traceMode = traceMode; + emit traceModeChanged(traceMode); + } } -void QGCMapPolygon::setShowAltColor(bool showAltColor){ - if (showAltColor != _showAltColor) { - _showAltColor = showAltColor; - emit showAltColorChanged(showAltColor); - } +void QGCMapPolygon::setShowAltColor(bool showAltColor) { + if (showAltColor != _showAltColor) { + _showAltColor = showAltColor; + emit showAltColorChanged(showAltColor); + } } -void QGCMapPolygon::selectVertex(int index) -{ - if(index == _selectedVertexIndex) return; // do nothing +void QGCMapPolygon::selectVertex(int index) { + if (index == _selectedVertexIndex) + return; // do nothing - if(-1 <= index && index < count()) { - _selectedVertexIndex = index; - } else { - if (!qgcApp()->runningUnitTests()) { - qCWarning(ParameterManagerLog) - << QString("QGCMapPolygon: Selected vertex index (%1) is out of bounds! " - "Polygon vertices indexes range is [%2..%3].").arg(index).arg(0).arg(count()-1); - } - _selectedVertexIndex = -1; // deselect vertex + if (-1 <= index && index < count()) { + _selectedVertexIndex = index; + } else { + if (!qgcApp()->runningUnitTests()) { + qCWarning(ParameterManagerLog) + << QString( + "QGCMapPolygon: Selected vertex index (%1) is out of bounds! " + "Polygon vertices indexes range is [%2..%3].") + .arg(index) + .arg(0) + .arg(count() - 1); } + _selectedVertexIndex = -1; // deselect vertex + } - emit selectedVertexChanged(_selectedVertexIndex); + emit selectedVertexChanged(_selectedVertexIndex); } -- 2.22.0