SafeArea.cc 3.97 KB
Newer Older
1
#include "SafeArea.h"
2 3 4 5

#include "QGCLoggingCategory.h"
#include "QGCQGeoCoordinate.h"

6
#include <QJsonObject>
7

8
QGC_LOGGING_CATEGORY(SafeAreaLog, "SafeAreaLog")
9

10 11 12 13
const char *SafeArea::safeAreaName = "Safe Area";
const char *SafeArea::depotLatitudeName = "DepotLatitude";
const char *SafeArea::depotLongitudeName = "DepotLongitude";
const char *SafeArea::depotAltitudeName = "DepotAltitude";
14

15 16 17 18
SafeArea::SafeArea(QObject *parent) : GeoArea(parent) { init(); }

SafeArea::SafeArea(const SafeArea &other, QObject *parent)
    : GeoArea(other, parent), _depot(other.depot()) {
19 20 21
  init();
}

22 23
SafeArea &SafeArea::operator=(const SafeArea &other) {
  GeoArea::operator=(other);
24 25 26 27
  this->setDepot(other.depot());
  return *this;
}

28 29 30 31 32 33 34 35 36
QString SafeArea::mapVisualQML() const { return "SafeAreaMapVisual.qml"; }

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; }
37

38
QGeoCoordinate SafeArea::depotQml() const { return _depot; }
39

40
bool SafeArea::setDepot(const QGeoCoordinate &coordinate) {
41 42 43 44 45 46 47 48 49 50 51 52
  if (_depot.latitude() != coordinate.latitude() ||
      _depot.longitude() != coordinate.longitude()) {
    if (this->containsCoordinate(coordinate)) {
      _depot = coordinate;
      _depot.setAltitude(0);
      emit depotChanged();
      return true;
    }
  }
  return false;
}

53 54 55
void SafeArea::saveToJson(QJsonObject &json) {
  this->GeoArea::saveToJson(json);
  json[areaTypeName] = safeAreaName;
56 57 58 59 60
  json[depotLatitudeName] = _depot.latitude();
  json[depotLongitudeName] = _depot.longitude();
  json[depotAltitudeName] = _depot.altitude();
}

61
bool SafeArea::loadFromJson(const QJsonObject &json, QString &errorString) {
62
  bool retVal = false;
63
  if (this->GeoArea::loadFromJson(json, errorString)) {
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    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;
}

92 93 94
void SafeArea::init() {
  this->setObjectName(safeAreaName);
  connect(this, &GeoArea::pathChanged, [this] {
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    if (!this->_depot.isValid() || !this->containsCoordinate(this->_depot)) {
      if (this->containsCoordinate(this->center())) {
        // Use center.
        this->setDepot(this->center());
      } else if (this->_depot.isValid()) {
        // Use nearest coordinate.
        auto minDist = std::numeric_limits<double>::infinity();
        int minIndex = 0;
        for (int idx = 0; idx < this->pathModel().count(); ++idx) {
          const QObject *obj = this->pathModel()[idx];
          const auto *vertex = qobject_cast<const QGCQGeoCoordinate *>(obj);
          if (vertex != nullptr) {
            auto d = vertex->coordinate().distanceTo(this->_depot);
            if (d < minDist) {
              minDist = d;
              minIndex = idx;
            }
          } else {
113
            qCCritical(SafeAreaLog) << "init(): nullptr catched!";
114 115
          }
        }
116 117 118
        this->setDepot(this->pathModel()
                           .value<QGCQGeoCoordinate *>(minIndex)
                           ->coordinate());
119 120
      } else if (this->pathModel().count() > 0) {
        // Use first coordinate.
121 122
        this->setDepot(
            this->pathModel().value<QGCQGeoCoordinate *>(0)->coordinate());
123 124 125 126
      }
    }
  });
}