#include "GeoArea.h" #include "geometry.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; } else { // set altitude to 0 for (int i = 0; i < this->count(); ++i) { auto vertex = this->vertexCoordinate(i); vertex.setAltitude(0); this->adjustVertex(i, vertex); } } return true; } bool GeoArea::isCorrect() { if (this->pathModel().count() >= 3) { auto origin = this->pathModel().value(0)->coordinate(); geometry::FPolygon polygonENU; geometry::areaToEnu(origin, this->pathModel(), polygonENU); std::string msg; if (bg::is_valid(polygonENU, msg)) { return true; } else { qCWarning(GeoAreaLog) << "isCorrect(): " << msg.c_str(); qCWarning(GeoAreaLog) << "isCorrect(): " << "origin: " << origin; std::stringstream ss; ss << bg::wkt(polygonENU); qCWarning(GeoAreaLog) << "isCorrect(): " << "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(); geometry::FPolygon polygonENU; geometry::areaToEnu(origin, this->pathModel(), polygonENU); geometry::FPoint cENU; geometry::toENU(origin, c, cENU); return bg::covered_by(cENU, polygonENU); } else { return false; } } void GeoArea::init() { this->setObjectName(nameString); } void GeoArea::setErrorString(const QString &str) { this->_errorString = str; emit errorStringChanged(); } void GeoArea::setErrorString(const std::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; }