#include "GeoArea.h" #include "snake.h" #include "QGCLoggingCategory.h" #include "QGCQGeoCoordinate.h" #include QGC_LOGGING_CATEGORY(GeoAreaLog, "GeoAreaLog") const char *GeoArea::nameString = "GeoArea"; const char *GeoArea::areaTypeKey = "AreaType"; const char *GeoArea::settingsGroup = "GeoArea"; // Constructors GeoArea::GeoArea(QObject *parent) : QGCMapPolygon(parent) { init(); } GeoArea::GeoArea(const GeoArea &other, QObject *parent) : QGCMapPolygon(other, parent) { init(); _errorString = other._errorString; } GeoArea &GeoArea::operator=(const GeoArea &other) { QGCMapPolygon::operator=(other); _errorString = other._errorString; return *this; } bool GeoArea::saveToJson(QJsonObject &json) { this->QGCMapPolygon::saveToJson(json); return true; } bool GeoArea::loadFromJson(const QJsonObject &json, QString &errorString) { if (!this->QGCMapPolygon::loadFromJson(json, false /*no poly required*/, errorString)) { qWarning() << errorString; return false; } return true; } bool GeoArea::isCorrect() { if (this->pathModel().count() >= 3) { auto origin = this->pathModel().value(0)->coordinate(); snake::FPolygon polygonENU; snake::areaToEnu(origin, this->pathModel(), polygonENU); std::string msg; if (bg::is_valid(polygonENU, msg)) { return true; } else { qCWarning(GeoAreaLog) << msg.c_str(); qCWarning(GeoAreaLog) << "origin: " << origin; std::stringstream ss; ss << bg::wkt(polygonENU); qCWarning(GeoAreaLog) << "polygonENU: " << ss.str().c_str(); setErrorString(this->objectName() + tr(" must be a simple polygon.")); } } return false; } QString GeoArea::errorString() const { return this->_errorString; } 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(nameString); // 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; emit errorStringChanged(); } void GeoArea::setErrorString(const string &str) { this->_errorString = str.c_str(); emit errorStringChanged(); } bool copyAreaList(const QmlObjectListModel &from, QmlObjectListModel &to, QObject *parent) { // Check if elements are valid. for (int i = 0; i < from.count(); ++i) { auto obj = from[i]; auto area = qobject_cast(obj); if (area == nullptr) { return false; } } // Clone elements. for (int i = 0; i < from.count(); ++i) { auto obj = from[i]; auto area = qobject_cast(obj); to.append(area->clone(parent)); } return true; }