#include "SafeArea.h" #include "QGCLoggingCategory.h" #include "QGCQGeoCoordinate.h" #include QGC_LOGGING_CATEGORY(SafeAreaLog, "SafeAreaLog") const char *SafeArea::safeAreaName = "Safe Area"; const char *SafeArea::depotLatitudeName = "DepotLatitude"; const char *SafeArea::depotLongitudeName = "DepotLongitude"; const char *SafeArea::depotAltitudeName = "DepotAltitude"; 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->containsCoordinate(newDepot)) { _depot = newDepot; _depot.setAltitude(0); emit depotChanged(); return true; } } return false; } void SafeArea::saveToJson(QJsonObject &json) { this->GeoArea::saveToJson(json); json[areaTypeName] = safeAreaName; json[depotLatitudeName] = _depot.latitude(); json[depotLongitudeName] = _depot.longitude(); json[depotAltitudeName] = _depot.altitude(); } bool SafeArea::loadFromJson(const QJsonObject &json, QString &errorString) { bool retVal = false; if (this->GeoArea::loadFromJson(json, errorString)) { double lat = 0; if (json.contains(depotLatitudeName) && json[depotLatitudeName].isDouble()) { lat = json[depotLatitudeName].toDouble(); double lon = 0; if (json.contains(depotLongitudeName) && json[depotLongitudeName].isDouble()) { lon = json[depotLongitudeName].toDouble(); double alt = 0; if (json.contains(depotAltitudeName) && json[depotAltitudeName].isDouble()) { alt = json[depotAltitudeName].toDouble(); this->setDepot(QGeoCoordinate(lat, lon, alt)); retVal = true; } else { errorString = "Not able to load depot altitude."; } } else { errorString = "Not able to load depot longitude."; } } else { errorString = "Not able to load depot latitude."; } retVal = true; } return retVal; } bool SafeArea::isCorrect() { if (GeoArea::isCorrect()) { if (this->_depot.isValid()) { if (this->containsCoordinate(this->_depot)) { return true; } else { setErrorString(tr("Depot outside Safe Area")); } } else { qCritical(SafeAreaLog) << "Depot invalid " << _depot; } } return false; } void SafeArea::init() { this->setObjectName(safeAreaName); connect(this, &GeoArea::pathChanged, this, &SafeArea::putDepotInside); }