#include "SafeArea.h" #include "JsonHelper.h" #include "QGCLoggingCategory.h" #include "QGCQGeoCoordinate.h" #include QGC_LOGGING_CATEGORY(SafeAreaLog, "SafeAreaLog") const char *SafeArea::name = "Safe Area"; const char *depotKey = "Depot Point"; SafeArea::SafeArea(QObject *parent) : GeoArea(parent) { init(); } SafeArea::SafeArea(const SafeArea &other, QObject *parent) : GeoArea(other, parent), _depot(other.depot()) { init(); } SafeArea &SafeArea::operator=(const SafeArea &other) { GeoArea::operator=(other); this->setDepot(other.depot()); return *this; } QString SafeArea::mapVisualQML() const { return "SafeAreaMapVisual.qml"; // return ""; } QString SafeArea::editorQML() const { return "SafeAreaEditor.qml"; } SafeArea *SafeArea::clone(QObject *parent) const { return new SafeArea(*this, parent); } const QGeoCoordinate &SafeArea::depot() const { return _depot; } QGeoCoordinate SafeArea::depotQml() const { return _depot; } void SafeArea::putDepotInside() { if (!this->containsCoordinate(this->_depot) && this->pathModel().count() > 0) { if (this->_depot.isValid()) { // Use nearest coordinate. auto minDist = std::numeric_limits::infinity(); int minIndex = 0; for (int idx = 0; idx < this->pathModel().count(); ++idx) { const QObject *obj = this->pathModel()[idx]; const auto *vertex = qobject_cast(obj); if (vertex != nullptr) { auto d = vertex->coordinate().distanceTo(this->_depot); if (d < minDist) { minDist = d; minIndex = idx; } } else { qCCritical(SafeAreaLog) << "init(): nullptr catched!"; } } this->setDepot( this->pathModel().value(minIndex)->coordinate()); } else { // Use first coordinate. this->setDepot( this->pathModel().value(0)->coordinate()); } } } bool SafeArea::setDepot(const QGeoCoordinate &newDepot) { if (_depot.latitude() != newDepot.latitude() || _depot.longitude() != newDepot.longitude()) { if (this->covers(newDepot)) { _depot = newDepot; _depot.setAltitude(0); emit depotChanged(); return true; } } return false; } bool SafeArea::saveToJson(QJsonObject &json) { if (this->GeoArea::saveToJson(json)) { json[areaTypeKey] = name; QJsonValue jsonDepot; JsonHelper::saveGeoCoordinate(_depot, false, jsonDepot); json[depotKey] = jsonDepot; return true; } else { qCDebug(SafeAreaLog) << "saveToJson(): error in GeoArea::safeToJson()"; } return false; } bool SafeArea::loadFromJson(const QJsonObject &json, QString &errorString) { bool returnValue = true; if (!this->GeoArea::loadFromJson(json, errorString)) { returnValue = false; } QList versionKeyInfoList = { {depotKey, QJsonValue::Array, true}, }; if (!JsonHelper::validateKeys(json, versionKeyInfoList, errorString)) { returnValue = false; } else { const auto &jsonDepot = json[depotKey]; if (!JsonHelper::loadGeoCoordinate(jsonDepot, false, _depot, errorString)) { returnValue = false; } } return returnValue; } bool SafeArea::isCorrect() { if (GeoArea::isCorrect()) { if (this->_depot.isValid()) { if (this->covers(this->_depot)) { return true; } else { setErrorString(tr("Depot outside Safe Area")); } } else { qCritical(SafeAreaLog) << "Depot invalid " << _depot; } } return false; } void SafeArea::init() { this->setObjectName(name); connect(this, &GeoArea::pathChanged, this, &SafeArea::putDepotInside); }