Commit dfceedc3 authored by Valentin Platzgummer's avatar Valentin Platzgummer

wima planer, plan data, wima controller edited

parent 47641f63
...@@ -4,410 +4,409 @@ ...@@ -4,410 +4,409 @@
* \variable WimaArea::epsilonMeter * \variable WimaArea::epsilonMeter
* \brief The accuracy used for distance calculations (unit: m). * \brief The accuracy used for distance calculations (unit: m).
*/ */
const double WimaArea::epsilonMeter = 1e-5; const double WimaArea::epsilonMeter = 1e-5;
/*! /*!
* \variable WimaArea::maxAltitudeName * \variable WimaArea::maxAltitudeName
* \brief A string containing the name of the \c _maxAltitude member. Among other used for storing. * \brief A string containing the name of the \c _maxAltitude member. Among
* other used for storing.
*/ */
const char* WimaArea::maxAltitudeName = "maxAltitude"; const char *WimaArea::maxAltitudeName = "maxAltitude";
/*! /*!
* \variable WimaArea::wimaAreaName * \variable WimaArea::wimaAreaName
* \brief A string containing the name of this \c WimaArea member. Among other used for storing. * \brief A string containing the name of this \c WimaArea member. Among other
* used for storing.
*/ */
const char* WimaArea::wimaAreaName = "WimaArea"; const char *WimaArea::wimaAreaName = "WimaArea";
/*! /*!
* \variable WimaArea::areaTypeName * \variable WimaArea::areaTypeName
* \brief A string containing \c {"AreaType"}. Among other used for stroing. * \brief A string containing \c {"AreaType"}. Among other used for stroing.
*/ */
const char* WimaArea::areaTypeName = "AreaType"; const char *WimaArea::areaTypeName = "AreaType";
const char *WimaArea::borderPolygonOffsetName = "BorderPolygonOffset";
const char* WimaArea::borderPolygonOffsetName = "BorderPolygonOffset"; const char *WimaArea::showBorderPolygonName = "ShowBorderPolygon";
const char* WimaArea::showBorderPolygonName = "ShowBorderPolygon"; const char *WimaArea::settingsGroup = "MeasurementArea";
const char* WimaArea::settingsGroup = "MeasurementArea";
// Constructors // Constructors
WimaArea::WimaArea(QObject *parent) WimaArea::WimaArea(QObject *parent)
: QGCMapPolygon (parent) : QGCMapPolygon(parent),
, _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/WimaArea.SettingsGroup.json"), this /* QObject parent */)) _metaDataMap(FactMetaData::createMapFromJsonFile(
, _borderPolygonOffset (SettingsFact(settingsGroup, _metaDataMap[borderPolygonOffsetName], this /* QObject parent */)) QStringLiteral(":/json/WimaArea.SettingsGroup.json"),
, _showBorderPolygon (SettingsFact(settingsGroup, _metaDataMap[showBorderPolygonName], this /* QObject parent */)) this /* QObject parent */)),
, _borderPolygon (QGCMapPolygon(this)) _borderPolygonOffset(SettingsFact(settingsGroup,
, _wimaAreaInteractive (false) _metaDataMap[borderPolygonOffsetName],
{ this /* QObject parent */)),
init(); _showBorderPolygon(SettingsFact(settingsGroup,
_maxAltitude = 30; _metaDataMap[showBorderPolygonName],
this /* QObject parent */)),
_borderPolygon(QGCMapPolygon(this)), _wimaAreaInteractive(false) {
init();
_maxAltitude = 30;
} }
WimaArea::WimaArea(const WimaArea &other, QObject *parent) WimaArea::WimaArea(const WimaArea &other, QObject *parent)
: QGCMapPolygon (parent) : QGCMapPolygon(parent),
, _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/WimaArea.SettingsGroup.json"), this /* QObject parent */)) _metaDataMap(FactMetaData::createMapFromJsonFile(
, _borderPolygonOffset (SettingsFact(settingsGroup, _metaDataMap[borderPolygonOffsetName], this /* QObject parent */)) QStringLiteral(":/json/WimaArea.SettingsGroup.json"),
, _showBorderPolygon (SettingsFact(settingsGroup, _metaDataMap[showBorderPolygonName], this /* QObject parent */)) this /* QObject parent */)),
, _borderPolygon (QGCMapPolygon(this)) _borderPolygonOffset(SettingsFact(settingsGroup,
, _wimaAreaInteractive (false) _metaDataMap[borderPolygonOffsetName],
{ this /* QObject parent */)),
init(); _showBorderPolygon(SettingsFact(settingsGroup,
*this = other; _metaDataMap[showBorderPolygonName],
this /* QObject parent */)),
_borderPolygon(QGCMapPolygon(this)), _wimaAreaInteractive(false) {
init();
*this = other;
} }
/*! /*!
*\fn WimaArea &WimaArea::operator=(const WimaArea &other) *\fn WimaArea &WimaArea::operator=(const WimaArea &other)
* *
* Assigns \a other to this \c WimaArea and returns a reference to this \c WimaArea. * Assigns \a other to this \c WimaArea and returns a reference to this \c
*WimaArea.
* *
* Copies only path and maximum altitude. * Copies only path and maximum altitude.
*/ */
WimaArea &WimaArea::operator=(const WimaArea &other) WimaArea &WimaArea::operator=(const WimaArea &other) {
{ QGCMapPolygon::operator=(other);
QGCMapPolygon::operator=(other); this->_maxAltitude = other.maxAltitude();
this->_maxAltitude = other.maxAltitude(); this->setPath(other.path());
this->setPath(other.path());
return *this; return *this;
} }
void WimaArea::setWimaAreaInteractive(bool interactive) void WimaArea::setWimaAreaInteractive(bool interactive) {
{ if (WimaArea::_wimaAreaInteractive != interactive) {
if (WimaArea::_wimaAreaInteractive != interactive) { WimaArea::_wimaAreaInteractive = interactive;
WimaArea::_wimaAreaInteractive = interactive;
emit WimaArea::wimaAreaInteractiveChanged(); emit WimaArea::wimaAreaInteractiveChanged();
} }
} }
/*! /*!
\fn void WimaArea::setMaxAltitude(double altitude) \fn void WimaArea::setMaxAltitude(double altitude)
Sets the \c _maxAltitude member to \a altitude and emits the signal \c maxAltitudeChanged() Sets the \c _maxAltitude member to \a altitude and emits the signal \c
if \c _maxAltitude is not equal to altitude. maxAltitudeChanged() if \c _maxAltitude is not equal to altitude.
*/ */
void WimaArea::setMaxAltitude(double altitude) void WimaArea::setMaxAltitude(double altitude) {
{ if (altitude > 0 && qFuzzyCompare(altitude, _maxAltitude)) {
if ( altitude > 0 && qFuzzyCompare(altitude, _maxAltitude) ) { _maxAltitude = altitude;
_maxAltitude = altitude; emit maxAltitudeChanged();
emit maxAltitudeChanged(); }
}
} }
void WimaArea::setShowBorderPolygon(bool showBorderPolygon) void WimaArea::setShowBorderPolygon(bool showBorderPolygon) {
{ _showBorderPolygon.setRawValue(showBorderPolygon);
_showBorderPolygon.setRawValue(showBorderPolygon);
} }
void WimaArea::setBorderPolygonOffset(double offset) {
if (!qFuzzyCompare(_borderPolygonOffset.rawValue().toDouble(), offset)) {
_borderPolygonOffset.setRawValue(offset);
emit borderPolygonOffsetChanged();
void WimaArea::setBorderPolygonOffset(double offset) }
{
if ( !qFuzzyCompare(_borderPolygonOffset.rawValue().toDouble(), offset) ) {
_borderPolygonOffset.setRawValue(offset);
emit borderPolygonOffsetChanged();
}
} }
void WimaArea::recalcPolygons() void WimaArea::recalcPolygons() {
{ if (_showBorderPolygon.rawValue().toBool() == true) {
if (_showBorderPolygon.rawValue().toBool() == true) {
if ( _borderPolygon.count() >= 3 ) {
//_borderPolygon.verifyClockwiseWinding(); // causes seg. fault
this->setPath(_borderPolygon.coordinateList());
this->offset(-_borderPolygonOffset.rawValue().toDouble());
}
} else {
if (this->count() >= 3){
//this->verifyClockwiseWinding(); // causes seg. fault
_borderPolygon.setPath(this->coordinateList());
_borderPolygon.offset(_borderPolygonOffset.rawValue().toDouble());
}
emit borderPolygonChanged(); if (_borderPolygon.count() >= 3) {
//_borderPolygon.verifyClockwiseWinding(); // causes seg. fault
this->setPath(_borderPolygon.coordinateList());
this->offset(-_borderPolygonOffset.rawValue().toDouble());
} }
} else {
if (this->count() >= 3) {
// this->verifyClockwiseWinding(); // causes seg. fault
_borderPolygon.setPath(this->coordinateList());
_borderPolygon.offset(_borderPolygonOffset.rawValue().toDouble());
}
emit borderPolygonChanged();
}
} }
void WimaArea::updatePolygonConnections(QVariant showBorderPolygon) void WimaArea::updatePolygonConnections(QVariant showBorderPolygon) {
{ if (showBorderPolygon.toBool() == true) {
if (showBorderPolygon.toBool() == true) { connect(&_borderPolygon, &QGCMapPolygon::pathChanged, this,
connect(&_borderPolygon, &QGCMapPolygon::pathChanged, this, &WimaArea::recalcPolygons); &WimaArea::recalcPolygons);
disconnect(this, &QGCMapPolygon::pathChanged, this, &WimaArea::recalcPolygons); disconnect(this, &QGCMapPolygon::pathChanged, this,
} else { &WimaArea::recalcPolygons);
disconnect(&_borderPolygon, &QGCMapPolygon::pathChanged, this, &WimaArea::recalcPolygons); } else {
connect(this, &QGCMapPolygon::pathChanged, this, &WimaArea::recalcPolygons); disconnect(&_borderPolygon, &QGCMapPolygon::pathChanged, this,
} &WimaArea::recalcPolygons);
connect(this, &QGCMapPolygon::pathChanged, this, &WimaArea::recalcPolygons);
}
} }
void WimaArea::recalcInteractivity() void WimaArea::recalcInteractivity() {
{ if (_wimaAreaInteractive == false) {
if ( _wimaAreaInteractive == false) { QGCMapPolygon::setInteractive(false);
QGCMapPolygon::setInteractive(false); _borderPolygon.setInteractive(false);
_borderPolygon.setInteractive(false); } else {
if (_showBorderPolygon.rawValue().toBool() == true) {
_borderPolygon.setInteractive(true);
QGCMapPolygon::setInteractive(false);
} else { } else {
if (_showBorderPolygon.rawValue().toBool() == true) { _borderPolygon.setInteractive(false);
_borderPolygon.setInteractive(true); QGCMapPolygon::setInteractive(true);
QGCMapPolygon::setInteractive(false);
} else {
_borderPolygon.setInteractive(false);
QGCMapPolygon::setInteractive(true);
}
} }
}
} }
/*! /*!
* \fn int WimaArea::getClosestVertexIndex(const QGeoCoordinate &coordinate) const * \fn int WimaArea::getClosestVertexIndex(const QGeoCoordinate &coordinate)
* Returns the index of the vertex (element of the polygon path) * const Returns the index of the vertex (element of the polygon path) which has
* which has the least distance to \a coordinate. * the least distance to \a coordinate.
* *
* \sa QGeoCoordinate * \sa QGeoCoordinate
*/ */
int WimaArea::getClosestVertexIndex(const QGeoCoordinate &coordinate) const int WimaArea::getClosestVertexIndex(const QGeoCoordinate &coordinate) const {
{ if (this->count() == 0) {
if (this->count() == 0) { qWarning("Polygon count == 0!");
qWarning("Polygon count == 0!"); return -1;
return -1; } else if (this->count() == 1) {
}else if (this->count() == 1) { return 0;
return 0; } else {
}else { int index = 0;
int index = 0; double min_dist = coordinate.distanceTo(this->vertexCoordinate(index));
double min_dist = coordinate.distanceTo(this->vertexCoordinate(index)); for (int i = 1; i < this->count(); i++) {
for(int i = 1; i < this->count(); i++){ double dist = coordinate.distanceTo(this->vertexCoordinate(i));
double dist = coordinate.distanceTo(this->vertexCoordinate(i)); if (dist < min_dist) {
if (dist < min_dist){ min_dist = dist;
min_dist = dist; index = i;
index = i; }
}
}
return index;
} }
return index;
}
} }
/*! /*!
* \fn QGeoCoordinate WimaArea::getClosestVertex(const QGeoCoordinate& coordinate) const * \fn QGeoCoordinate WimaArea::getClosestVertex(const QGeoCoordinate&
* Returns the vertex of the polygon path with the least distance to \a coordinate. * coordinate) const Returns the vertex of the polygon path with the least
* distance to \a coordinate.
* *
* \sa QGeoCoordinate * \sa QGeoCoordinate
*/ */
QGeoCoordinate WimaArea::getClosestVertex(const QGeoCoordinate& coordinate) const QGeoCoordinate
{ WimaArea::getClosestVertex(const QGeoCoordinate &coordinate) const {
return this->vertexCoordinate(getClosestVertexIndex(coordinate)); return this->vertexCoordinate(getClosestVertexIndex(coordinate));
} }
/*! /*!
* \fn QGCMapPolygon WimaArea::toQGCPolygon(const WimaArea &area) * \fn QGCMapPolygon WimaArea::toQGCPolygon(const WimaArea &area)
* Converts the \c WimaArea \a area to \c QGCMapPolygon by copying the path only. * Converts the \c WimaArea \a area to \c QGCMapPolygon by copying the path
* only.
*/ */
QGCMapPolygon WimaArea::toQGCPolygon(const WimaArea &area) QGCMapPolygon WimaArea::toQGCPolygon(const WimaArea &area) {
{ QGCMapPolygon qgcPoly;
QGCMapPolygon qgcPoly; qgcPoly.setPath(area.path());
qgcPoly.setPath(area.path());
return QGCMapPolygon(qgcPoly); return QGCMapPolygon(qgcPoly);
} }
/*! /*!
* \fn QGCMapPolygon WimaArea::toQGCPolygon() const * \fn QGCMapPolygon WimaArea::toQGCPolygon() const
* Converts the calling \c WimaArea to \c QGCMapPolygon by copying the path only. * Converts the calling \c WimaArea to \c QGCMapPolygon by copying the path
* only.
*/ */
QGCMapPolygon WimaArea::toQGCPolygon() const QGCMapPolygon WimaArea::toQGCPolygon() const { return toQGCPolygon(*this); }
{
return toQGCPolygon(*this);
}
/*! /*!
* \fn bool WimaArea::join(WimaArea &area1, WimaArea &area2, WimaArea &joinedArea, QString &errorString) * \fn bool WimaArea::join(WimaArea &area1, WimaArea &area2, WimaArea
* Joins the areas \a area1 and \a area2 such that a \l {Simple Polygon} is created. * &joinedArea, QString &errorString) Joins the areas \a area1 and \a area2 such
* Stores the result inside \a joinedArea. * that a \l {Simple Polygon} is created. Stores the result inside \a
* Stores error messages in \a errorString. * joinedArea. Stores error messages in \a errorString. Returns \c true if the
* Returns \c true if the algorithm was able to join the areas; false else. * algorithm was able to join the areas; false else. The algorithm will be able
* The algorithm will be able to join the areas, if either their edges intersect with each other, * to join the areas, if either their edges intersect with each other, or one
* or one area contains the other. * area contains the other.
*/ */
bool WimaArea::join(const WimaArea &area1, const WimaArea &area2, WimaArea &joinedArea, QString &errorString) bool WimaArea::join(const WimaArea &area1, const WimaArea &area2,
{ WimaArea &joinedArea, QString &errorString) {
using namespace GeoUtilities; using namespace GeoUtilities;
using namespace PolygonCalculus; using namespace PolygonCalculus;
Q_UNUSED(errorString); Q_UNUSED(errorString);
QList<QGeoCoordinate> GeoPolygon1 = area1.coordinateList(); QList<QGeoCoordinate> GeoPolygon1 = area1.coordinateList();
QList<QGeoCoordinate> GeoPolygon2 = area2.coordinateList(); QList<QGeoCoordinate> GeoPolygon2 = area2.coordinateList();
// qWarning("befor joining"); // qWarning("befor joining");
// qWarning() << GeoPolygon1; // qWarning() << GeoPolygon1;
// qWarning() << GeoPolygon2; // qWarning() << GeoPolygon2;
QGeoCoordinate origin = GeoPolygon1[0]; QGeoCoordinate origin = GeoPolygon1[0];
// QGeoCoordinate tset = GeoPolygon1[2]; // QGeoCoordinate tset = GeoPolygon1[2];
// qWarning() << tset;qWarning() << toGeo(toCartesian2D(tset, origin), origin); // qWarning() << tset;qWarning() << toGeo(toCartesian2D(tset, origin),
// origin);
QPolygonF polygon1;
QPolygonF polygon1; toCartesianList(GeoPolygon1, origin, polygon1);
toCartesianList(GeoPolygon1, origin, polygon1); QPolygonF polygon2;
QPolygonF polygon2; toCartesianList(GeoPolygon2, origin, polygon2);
toCartesianList(GeoPolygon2, origin, polygon2);
// qWarning("after 1 transform");
// qWarning("after 1 transform"); // qWarning() << polygon1;
// qWarning() << polygon1; // qWarning() << polygon2;
// qWarning() << polygon2;
QPolygonF joinedPolygon;
QPolygonF joinedPolygon; JoinPolygonError retValue =
JoinPolygonError retValue = PolygonCalculus::join(polygon1, polygon2, joinedPolygon); PolygonCalculus::join(polygon1, polygon2, joinedPolygon);
// qWarning("after joining");
// qWarning("after joining"); // qWarning() << joinedPolygon;
// qWarning() << joinedPolygon;
if (retValue == JoinPolygonError::Disjoint) {
if (retValue == JoinPolygonError::Disjoint) { qWarning("Polygons are disjoint.");
qWarning("Polygons are disjoint."); } else if (retValue == JoinPolygonError::NotSimplePolygon) {
} else if (retValue == JoinPolygonError::NotSimplePolygon) { qWarning("Not a simple polygon.");
qWarning("Not a simple polygon."); } else if (retValue == JoinPolygonError::PathSizeLow) {
} else if (retValue == JoinPolygonError::PathSizeLow) { qWarning("Polygon vertex count is low.");
qWarning("Polygon vertex count is low."); } else {
} else { QVector<QGeoCoordinate> path;
QVector<QGeoCoordinate> path; toGeoList(joinedPolygon, origin, path);
toGeoList(joinedPolygon, origin, path); // qWarning("after transform");
// qWarning("after transform"); // qWarning() << path;
// qWarning() << path; joinedArea.setPath(path);
joinedArea.setPath(path); return true;
return true; }
}
return false; return false;
} }
/*! /*!
* \fn bool WimaArea::join(WimaArea &area1, WimaArea &area2, WimaArea &joinedArea) * \fn bool WimaArea::join(WimaArea &area1, WimaArea &area2, WimaArea
* Joins the areas \a area1 and \a area2 such that a \l {Simple Polygon} is created. * &joinedArea) Joins the areas \a area1 and \a area2 such that a \l {Simple
* Stores the result inside \a joinedArea. * Polygon} is created. Stores the result inside \a joinedArea. Returns \c true
* Returns \c true if the algorithm was able to join the areas; false else. * if the algorithm was able to join the areas; false else. The algorithm will
* The algorithm will be able to join the areas, if either their edges intersect with each other, * be able to join the areas, if either their edges intersect with each other,
* or one area contains the other. * or one area contains the other.
*/ */
bool WimaArea::join(const WimaArea &area1, const WimaArea &area2, WimaArea &joinedArea) bool WimaArea::join(const WimaArea &area1, const WimaArea &area2,
{ WimaArea &joinedArea) {
QString dummy; QString dummy;
return join(area1, area2, joinedArea, dummy); return join(area1, area2, joinedArea, dummy);
} }
/*! /*!
* \fn bool WimaArea::join(WimaArea &area) * \fn bool WimaArea::join(WimaArea &area)
* Joins the calling \c WimaArea and the \a area such that a \l {Simple Polygon} is created. * Joins the calling \c WimaArea and the \a area such that a \l {Simple Polygon}
* Overwrites the calling \c WimaArea with the result, if the algorithm was successful. * is created. Overwrites the calling \c WimaArea with the result, if the
* Returns \c true if the algorithm was able to join the areas; false else. * algorithm was successful. Returns \c true if the algorithm was able to join
* The algorithm will be able to join the areas, if either their edges intersect with each other, * the areas; false else. The algorithm will be able to join the areas, if
* or one area contains the other. * either their edges intersect with each other, or one area contains the other.
*/ */
bool WimaArea::join(WimaArea &area) bool WimaArea::join(WimaArea &area) {
{ WimaArea joinedArea;
WimaArea joinedArea; if (join(*this, area, joinedArea)) {
if ( join(*this, area, joinedArea) ) { // qWarning("WimaArea::join(WimaArea &area)");
//qWarning("WimaArea::join(WimaArea &area)"); // qWarning() << joinedArea.coordinateList();
//qWarning() << joinedArea.coordinateList(); this->setPath(joinedArea.path());
this->setPath(joinedArea.path()); return true;
return true; } else {
} else { return false;
return false; }
}
} }
/*! /*!
* \fn bool WimaArea::join(WimaArea &area, QString &errorString) * \fn bool WimaArea::join(WimaArea &area, QString &errorString)
* Joins the calling \c WimaArea and the \a area such that a \l {Simple Polygon} is created. * Joins the calling \c WimaArea and the \a area such that a \l {Simple Polygon}
* Overwrites the calling \c WimaArea with the result, if the algorithm was successful. * is created. Overwrites the calling \c WimaArea with the result, if the
* algorithm was successful.
* *
* Returns \c true if the algorithm was able to join the areas; false else. * Returns \c true if the algorithm was able to join the areas; false else.
* Stores error messages in \a errorString. * Stores error messages in \a errorString.
* *
* The algorithm will be able to join the areas, if either their edges intersect with each other, * The algorithm will be able to join the areas, if either their edges intersect
* or one area contains the other. * with each other, or one area contains the other.
*/ */
bool WimaArea::join(WimaArea &area, QString &errorString) bool WimaArea::join(WimaArea &area, QString &errorString) {
{ WimaArea joinedArea;
WimaArea joinedArea; if (join(*this, area, joinedArea, errorString)) {
if ( join(*this, area, joinedArea, errorString) ) { this->setPath(joinedArea.path());
this->setPath(joinedArea.path()); return true;
return true; } else {
} else { return false;
return false; }
}
} }
/*! /*!
* \fn int WimaArea::nextVertexIndex(int index) const * \fn int WimaArea::nextVertexIndex(int index) const
* Returns the index of the next vertex (of the areas path), which is \a index + 1 if \a index is smaller than \c {area.count() - 1}, * Returns the index of the next vertex (of the areas path), which is \a index +
* or 0 if \a index equals \c {area.count() - 1}, or -1 if the \a index is out of bounds. * 1 if \a index is smaller than \c {area.count() - 1}, or 0 if \a index equals
* \note The function \c {area.count()} (derived from \c QGCMapPolygon) returns the number of vertices defining the area. * \c {area.count() - 1}, or -1 if the \a index is out of bounds. \note The
* function \c {area.count()} (derived from \c QGCMapPolygon) returns the number
* of vertices defining the area.
*/ */
int WimaArea::nextVertexIndex(int index) const int WimaArea::nextVertexIndex(int index) const {
{ if (index >= 0 && index < count() - 1) {
if (index >= 0 && index < count()-1) { return index + 1;
return index + 1; } else if (index == count() - 1) {
} else if (index == count()-1) { return 0;
return 0; } else {
} else { qWarning(
qWarning("WimaArea::nextVertexIndex(): Index out of bounds! index:count = %i:%i", index, count()); "WimaArea::nextVertexIndex(): Index out of bounds! index:count = %i:%i",
return -1; index, count());
} return -1;
}
} }
/*! /*!
* \fn int WimaArea::previousVertexIndex(int index) const * \fn int WimaArea::previousVertexIndex(int index) const
* Returns the index of the previous vertex (of the areas path), which is \a index - 1 if \a index is larger 0, * Returns the index of the previous vertex (of the areas path), which is \a
* or \c {area.count() - 1} if \a index equals 0, or -1 if the \a index is out of bounds. * index - 1 if \a index is larger 0, or \c {area.count() - 1} if \a index
* \note The function \c {area.count()} (derived from \c QGCMapPolygon) returns the number of vertices defining the area. * equals 0, or -1 if the \a index is out of bounds. \note The function \c
* {area.count()} (derived from \c QGCMapPolygon) returns the number of vertices
* defining the area.
*/ */
int WimaArea::previousVertexIndex(int index) const int WimaArea::previousVertexIndex(int index) const {
{ if (index > 0 && index < count()) {
if (index > 0 && index < count()) { return index - 1;
return index - 1; } else if (index == 0) {
} else if (index == 0) { return count() - 1;
return count()-1; } else {
} else { qWarning("WimaArea::previousVertexIndex(): Index out of bounds! "
qWarning("WimaArea::previousVertexIndex(): Index out of bounds! index:count = %i:%i", index, count()); "index:count = %i:%i",
return -1; index, count());
} return -1;
}
} }
/*! /*!
* \fn bool WimaArea::isSelfIntersecting() * \fn bool WimaArea::isSelfIntersecting()
* Returns \c true if the calling area is self intersecting, \c false else. * Returns \c true if the calling area is self intersecting, \c false else.
* \note If the calling area is self intersecting, it's not a \l {Simple Polygon}. * \note If the calling area is self intersecting, it's not a \l {Simple
* Polygon}.
*/ */
bool WimaArea::isSimplePolygon() const bool WimaArea::isSimplePolygon() const {
{ using namespace PolygonCalculus;
using namespace PolygonCalculus; using namespace GeoUtilities;
using namespace GeoUtilities;
if (this->count() > 2) {
if (this->count() > 2) { QPolygonF polygon;
QPolygonF polygon; toCartesianList(this->coordinateList(), this->vertexCoordinate(0), polygon);
toCartesianList(this->coordinateList(), this->vertexCoordinate(0), polygon); return PolygonCalculus::isSimplePolygon(polygon);
return PolygonCalculus::isSimplePolygon(polygon); } else
} else return false;
return false;
} }
bool WimaArea::containsCoordinate(const QGeoCoordinate &coordinate) const bool WimaArea::containsCoordinate(const QGeoCoordinate &coordinate) const {
{ using namespace PlanimetryCalculus;
using namespace PlanimetryCalculus; using namespace PolygonCalculus;
using namespace PolygonCalculus; using namespace GeoUtilities;
using namespace GeoUtilities;
if (this->count() > 2) {
if (this->count() > 2) { QPolygonF polygon;
QPolygonF polygon; toCartesianList(this->coordinateList(), coordinate, polygon);
toCartesianList(this->coordinateList(), coordinate, polygon); return PlanimetryCalculus::contains(polygon, QPointF(0, 0));
return PlanimetryCalculus::contains(polygon, QPointF(0,0)); } else
} else return false;
return false;
} }
/*! /*!
...@@ -416,114 +415,123 @@ bool WimaArea::containsCoordinate(const QGeoCoordinate &coordinate) const ...@@ -416,114 +415,123 @@ bool WimaArea::containsCoordinate(const QGeoCoordinate &coordinate) const
* *
* \sa QJsonObject * \sa QJsonObject
*/ */
void WimaArea::saveToJson(QJsonObject &json) void WimaArea::saveToJson(QJsonObject &json) {
{ this->QGCMapPolygon::saveToJson(json);
this->QGCMapPolygon::saveToJson(json);
json[maxAltitudeName] = _maxAltitude;
json[maxAltitudeName] = _maxAltitude; json[borderPolygonOffsetName] = _borderPolygonOffset.rawValue().toDouble();
json[borderPolygonOffsetName] = _borderPolygonOffset.rawValue().toDouble(); json[showBorderPolygonName] = _showBorderPolygon.rawValue().toDouble();
json[showBorderPolygonName] = _showBorderPolygon.rawValue().toDouble(); json[areaTypeName] = wimaAreaName;
json[areaTypeName] = wimaAreaName;
} }
/*! /*!
* \fn bool WimaArea::loadFromJson(const QJsonObject &json, QString& errorString) * \fn bool WimaArea::loadFromJson(const QJsonObject &json, QString&
* Loads data from \a json and stores it inside the calling area. * errorString) Loads data from \a json and stores it inside the calling area.
* Returns \c true if loading was successful, \c false else. * Returns \c true if loading was successful, \c false else.
* Stores error messages inside \a errorString. * Stores error messages inside \a errorString.
* *
* \sa QJsonObject * \sa QJsonObject
*/ */
bool WimaArea::loadFromJson(const QJsonObject &json, QString& errorString) bool WimaArea::loadFromJson(const QJsonObject &json, QString &errorString) {
{ if (this->QGCMapPolygon::loadFromJson(json, false /*no poly required*/,
if ( this->QGCMapPolygon::loadFromJson(json, false /*no poly required*/, errorString) ) { errorString)) {
if ( json.contains(maxAltitudeName) && json[maxAltitudeName].isDouble()) { if (json.contains(maxAltitudeName) && json[maxAltitudeName].isDouble()) {
_maxAltitude = json[maxAltitudeName].toDouble(); _maxAltitude = json[maxAltitudeName].toDouble();
} else {
errorString.append(tr("Could not load Maximum Altitude value!\n"));
return false;
}
if ( json.contains(borderPolygonOffsetName) && json[borderPolygonOffsetName].isDouble()) {
_borderPolygonOffset.setRawValue(json[borderPolygonOffsetName].toDouble());
} else {
errorString.append(tr("Could not load border polygon offset value!\n"));
return false;
}
if ( json.contains(showBorderPolygonName) && json[showBorderPolygonName].isDouble()) {
_showBorderPolygon.setRawValue(json[showBorderPolygonName].toBool());
} else {
errorString.append(tr("Could not load border polygon offset value!\n"));
return false;
}
} else { } else {
qWarning() << errorString; errorString.append(tr("Could not load Maximum Altitude value!\n"));
return false; return false;
} }
return true; if (json.contains(borderPolygonOffsetName) &&
json[borderPolygonOffsetName].isDouble()) {
_borderPolygonOffset.setRawValue(
json[borderPolygonOffsetName].toDouble());
} else {
errorString.append(tr("Could not load border polygon offset value!\n"));
return false;
}
if (json.contains(showBorderPolygonName) &&
json[showBorderPolygonName].isDouble()) {
_showBorderPolygon.setRawValue(json[showBorderPolygonName].toBool());
} else {
errorString.append(tr("Could not load border polygon offset value!\n"));
return false;
}
} else {
qWarning() << errorString;
return false;
}
return true;
} }
/*! /*!
* \fn void WimaArea::init() * \fn void WimaArea::init()
* Funtion to be called during construction. * Funtion to be called during construction.
*/ */
void WimaArea::init() void WimaArea::init() {
{ this->setObjectName(wimaAreaName);
this->setObjectName(wimaAreaName);
if (_showBorderPolygon.rawValue().toBool() == true) {
if (_showBorderPolygon.rawValue().toBool() == true){ connect(&_borderPolygon, &QGCMapPolygon::pathChanged, this,
connect(&_borderPolygon, &QGCMapPolygon::pathChanged, this, &WimaArea::recalcPolygons); &WimaArea::recalcPolygons);
} else { } else {
connect(this, &QGCMapPolygon::pathChanged, this, &WimaArea::recalcPolygons); connect(this, &QGCMapPolygon::pathChanged, this, &WimaArea::recalcPolygons);
} }
connect(&_borderPolygonOffset, &SettingsFact::rawValueChanged, this, &WimaArea::recalcPolygons); connect(&_borderPolygonOffset, &SettingsFact::rawValueChanged, this,
connect(&_showBorderPolygon, &SettingsFact::rawValueChanged, this, &WimaArea::updatePolygonConnections); &WimaArea::recalcPolygons);
connect(&_showBorderPolygon, &SettingsFact::rawValueChanged, this, &WimaArea::recalcInteractivity); connect(&_showBorderPolygon, &SettingsFact::rawValueChanged, this,
connect(this, &WimaArea::wimaAreaInteractiveChanged, this, &WimaArea::recalcInteractivity); &WimaArea::updatePolygonConnections);
connect(&_showBorderPolygon, &SettingsFact::rawValueChanged, this,
&WimaArea::recalcInteractivity);
connect(this, &WimaArea::wimaAreaInteractiveChanged, this,
&WimaArea::recalcInteractivity);
} }
/*! /*!
* \fn void print(const WimaArea &area) * \fn void print(const WimaArea &area)
* Prints the data contained in \a area to the console. * Prints the data contained in \a area to the console.
*/ */
void print(const WimaArea &area) void print(const WimaArea &area) {
{ QString message;
QString message; print(area, message);
print(area, message); qWarning() << message;
qWarning() << message;
} }
/*! /*!
* \fn void print(const WimaArea &area) * \fn void print(const WimaArea &area)
* Prints the data contained in \a area to the \a outputString. * Prints the data contained in \a area to the \a outputString.
*/ */
void print(const WimaArea &area, QString &outputString) void print(const WimaArea &area, QString &outputString) {
{ outputString.append(QString("Type: %1\n").arg(area.objectName()));
outputString.append(QString("Type: %1\n").arg(area.objectName())); print(static_cast<const QGCMapPolygon &>(area), outputString);
print(static_cast<const QGCMapPolygon&>(area), outputString); outputString.append(QString("Maximum Altitude: %1\n").arg(area._maxAltitude));
outputString.append(QString("Maximum Altitude: %1\n").arg(area._maxAltitude)); outputString.append(
outputString.append(QString("Border Polygon Offset: %1\n").arg(area._borderPolygonOffset.rawValue().toDouble())); QString("Border Polygon Offset: %1\n")
.arg(area._borderPolygonOffset.rawValue().toDouble()));
outputString.append(QString("Border Polygon Coordinates\n").arg(area._borderPolygonOffset.rawValue().toDouble()));
for (int i = 0; i < area._borderPolygon.count(); i++) { outputString.append(
QGeoCoordinate coordinate = area._borderPolygon.vertexCoordinate(i); QString("Border Polygon Coordinates\n")
outputString.append(QString("%1\n").arg(coordinate.toString(QGeoCoordinate::Degrees))); .arg(area._borderPolygonOffset.rawValue().toDouble()));
} for (int i = 0; i < area._borderPolygon.count(); i++) {
QGeoCoordinate coordinate = area._borderPolygon.vertexCoordinate(i);
outputString.append(
QString("%1\n").arg(coordinate.toString(QGeoCoordinate::Degrees)));
}
} }
// QDoc Documentation // QDoc Documentation
/*! /*!
\group WimaAreaGroup \group WimaAreaGroup
\title Group of WimaAreas \title Group of WimaAreas
Every \c WimaArea of the equally named group uses a \l {Simple Polygon} derived from \c {QGCMapPolygon} Every \c WimaArea of the equally named group uses a \l {Simple Polygon}
to define areas inside which certain taskts are performed. derived from \c {QGCMapPolygon} to define areas inside which certain taskts
are performed.
*/ */
/*! /*!
...@@ -535,8 +543,8 @@ void print(const WimaArea &area, QString &outputString) ...@@ -535,8 +543,8 @@ void print(const WimaArea &area, QString &outputString)
all areas used within the Wima extension. all areas used within the Wima extension.
\c WimaArea uses a \l {Simple Polygon} derived from \c {QGCMapPolygon} \c WimaArea uses a \l {Simple Polygon} derived from \c {QGCMapPolygon}
to define areas inside which certain taskts are performed. The polygon (often refered to as the path) can to define areas inside which certain taskts are performed. The polygon
be displayed visually on a map. (often refered to as the path) can be displayed visually on a map.
*/ */
/*! /*!
...@@ -551,12 +559,14 @@ void print(const WimaArea &area, QString &outputString) ...@@ -551,12 +559,14 @@ void print(const WimaArea &area, QString &outputString)
/*! /*!
\property WimaArea::mapVisualQML \property WimaArea::mapVisualQML
\brief A string containing the name of the QML file used to displays this area on a map. \brief A string containing the name of the QML file used to displays this area
on a map.
*/ */
/*! /*!
\property WimaArea::editorQML \property WimaArea::editorQML
\brief A string containing the name of the QML file allowing to edit the area's properties. \brief A string containing the name of the QML file allowing to edit the
area's properties.
*/ */
/*! /*!
...@@ -568,5 +578,3 @@ void print(const WimaArea &area, QString &outputString) ...@@ -568,5 +578,3 @@ void print(const WimaArea &area, QString &outputString)
\externalpage https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm \externalpage https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
\title Dijkstra Algorithm \title Dijkstra Algorithm
*/ */
#pragma once #pragma once
#include "QGCGeo.h"
#include "QGCMapPolygon.h" #include "QGCMapPolygon.h"
#include "QGCMapPolyline.h" #include "QGCMapPolyline.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "qobject.h" #include "qobject.h"
#include <QLineF> #include <QLineF>
#include <QPointF>
#include "QGCGeo.h"
#include <QPair> #include <QPair>
#include <QPointF>
#include "GeoUtilities.h" #include "GeoUtilities.h"
#include "PolygonCalculus.h"
#include "PlanimetryCalculus.h" #include "PlanimetryCalculus.h"
#include "PolygonCalculus.h"
class WimaArea : public QGCMapPolygon //abstract base class for all WimaAreas class WimaArea : public QGCMapPolygon // abstract base class for all WimaAreas
{ {
Q_OBJECT Q_OBJECT
public: public:
WimaArea(QObject* parent = nullptr); WimaArea(QObject *parent = nullptr);
WimaArea(const WimaArea& other, QObject* parent = nullptr); WimaArea(const WimaArea &other, QObject *parent = nullptr);
WimaArea &operator=(const WimaArea &other); WimaArea &operator=(const WimaArea &other);
Q_PROPERTY(double maxAltitude READ maxAltitude WRITE setMaxAltitude NOTIFY
Q_PROPERTY(double maxAltitude READ maxAltitude WRITE setMaxAltitude NOTIFY maxAltitudeChanged) maxAltitudeChanged)
Q_PROPERTY(QString mapVisualQML READ mapVisualQML CONSTANT) Q_PROPERTY(QString mapVisualQML READ mapVisualQML CONSTANT)
Q_PROPERTY(QString editorQML READ editorQML CONSTANT) Q_PROPERTY(QString editorQML READ editorQML CONSTANT)
Q_PROPERTY(Fact* borderPolygonOffset READ borderPolygonOffsetFact CONSTANT) Q_PROPERTY(Fact *borderPolygonOffset READ borderPolygonOffsetFact CONSTANT)
Q_PROPERTY(QGCMapPolygon* borderPolygon READ borderPolygon NOTIFY borderPolygonChanged) Q_PROPERTY(QGCMapPolygon *borderPolygon READ borderPolygon NOTIFY
Q_PROPERTY(Fact* showBorderPolygon READ showBorderPolygon CONSTANT) borderPolygonChanged)
Q_PROPERTY(bool wimaAreaInteractive READ wimaAreaInteractive WRITE setWimaAreaInteractive NOTIFY wimaAreaInteractiveChanged) Q_PROPERTY(Fact *showBorderPolygon READ showBorderPolygon CONSTANT)
Q_PROPERTY(bool wimaAreaInteractive READ wimaAreaInteractive WRITE
setWimaAreaInteractive NOTIFY wimaAreaInteractiveChanged)
//Property accessors
double maxAltitude (void) const { return _maxAltitude;} // Property accessors
Fact* borderPolygonOffsetFact (void) { return &_borderPolygonOffset;} double maxAltitude(void) const { return _maxAltitude; }
Fact* showBorderPolygon (void) { return &_showBorderPolygon;} Fact *borderPolygonOffsetFact(void) { return &_borderPolygonOffset; }
double borderPolygonOffset (void) const { return _borderPolygonOffset.rawValue().toDouble();} Fact *showBorderPolygon(void) { return &_showBorderPolygon; }
QGCMapPolygon* borderPolygon (void) { return &_borderPolygon;} double borderPolygonOffset(void) const {
bool wimaAreaInteractive (void) const { return _wimaAreaInteractive;} return _borderPolygonOffset.rawValue().toDouble();
}
void setWimaAreaInteractive (bool interactive); QGCMapPolygon *borderPolygon(void) { return &_borderPolygon; }
bool wimaAreaInteractive(void) const { return _wimaAreaInteractive; }
// overrides from WimaArea
virtual QString mapVisualQML (void) const { return ""; } void setWimaAreaInteractive(bool interactive);
virtual QString editorQML (void) const { return ""; }
// overrides from WimaArea
// Member Methodes virtual QString mapVisualQML(void) const { return ""; }
int getClosestVertexIndex (const QGeoCoordinate& coordinate) const; virtual QString editorQML(void) const { return ""; }
QGeoCoordinate getClosestVertex (const QGeoCoordinate& coordinate) const;
QGCMapPolygon toQGCPolygon () const; // Member Methodes
bool join (WimaArea &area); int getClosestVertexIndex(const QGeoCoordinate &coordinate) const;
bool join (WimaArea &area, QString &errorString); QGeoCoordinate getClosestVertex(const QGeoCoordinate &coordinate) const;
int nextVertexIndex (int index) const; QGCMapPolygon toQGCPolygon() const;
int previousVertexIndex (int index) const; bool join(WimaArea &area);
bool isSimplePolygon () const; bool join(WimaArea &area, QString &errorString);
bool containsCoordinate (const QGeoCoordinate &coordinate) const; int nextVertexIndex(int index) const;
int previousVertexIndex(int index) const;
bool isSimplePolygon() const;
void saveToJson (QJsonObject& jsonObject); bool containsCoordinate(const QGeoCoordinate &coordinate) const;
bool loadFromJson (const QJsonObject &jsonObject, QString& errorString);
void saveToJson(QJsonObject &jsonObject);
// static Methodes bool loadFromJson(const QJsonObject &jsonObject, QString &errorString);
static QGCMapPolygon toQGCPolygon (const WimaArea& area);
static bool join (const WimaArea &area1, const WimaArea &area2, WimaArea& joinedArea, QString &errorString); // static Methodes
static bool join (const WimaArea &area1, const WimaArea &area2, WimaArea& joinedArea); static QGCMapPolygon toQGCPolygon(const WimaArea &area);
static bool join(const WimaArea &area1, const WimaArea &area2,
WimaArea &joinedArea, QString &errorString);
// Friends static bool join(const WimaArea &area1, const WimaArea &area2,
friend void print(const WimaArea& area, QString& outputString); WimaArea &joinedArea);
friend void print(const WimaArea& area);
// Friends
// static Members friend void print(const WimaArea &area, QString &outputString);
// Accurracy used to compute isDisjunct friend void print(const WimaArea &area);
static const double epsilonMeter;
static const char* maxAltitudeName; // static Members
static const char* wimaAreaName; // Accurracy used to compute isDisjunct
static const char* areaTypeName; static const double epsilonMeter;
static const char* borderPolygonOffsetName; static const char *maxAltitudeName;
static const char* showBorderPolygonName; static const char *wimaAreaName;
static const char* settingsGroup; static const char *areaTypeName;
static const char *borderPolygonOffsetName;
static const char *showBorderPolygonName;
static const char *settingsGroup;
signals: signals:
void maxAltitudeChanged (void); void maxAltitudeChanged(void);
void borderPolygonChanged (void); void borderPolygonChanged(void);
void borderPolygonOffsetChanged (void); void borderPolygonOffsetChanged(void);
void wimaAreaInteractiveChanged (void); void wimaAreaInteractiveChanged(void);
public slots: public slots:
void setMaxAltitude (double altitude); void setMaxAltitude(double altitude);
void setShowBorderPolygon (bool showBorderPolygon); void setShowBorderPolygon(bool showBorderPolygon);
void setBorderPolygonOffset (double offset); void setBorderPolygonOffset(double offset);
private slots: private slots:
void recalcPolygons (void); void recalcPolygons(void);
void updatePolygonConnections (QVariant value); void updatePolygonConnections(QVariant value);
void recalcInteractivity (void); void recalcInteractivity(void);
private: private:
void init(); void init();
double _maxAltitude; double _maxAltitude;
QMap<QString, FactMetaData*> _metaDataMap; QMap<QString, FactMetaData *> _metaDataMap;
SettingsFact _borderPolygonOffset; SettingsFact _borderPolygonOffset;
SettingsFact _showBorderPolygon; SettingsFact _showBorderPolygon;
QGCMapPolygon _borderPolygon; QGCMapPolygon _borderPolygon;
bool _wimaAreaInteractive; bool _wimaAreaInteractive;
}; };
#include "WimaAreaData.h" #include "WimaAreaData.h"
WimaAreaData::WimaAreaData(QObject *parent) WimaAreaData::WimaAreaData(QObject *parent) : QObject(parent) {
: QObject(parent) _maxAltitude = 0;
{
_maxAltitude = 0;
} }
WimaAreaData::~WimaAreaData() {}
/*! /*!
* \fn double WimaAreaData::maxAltitude() * \fn double WimaAreaData::maxAltitude()
* *
* Returns the maximum altitude at which vehicles are allowed to fly. * Returns the maximum altitude at which vehicles are allowed to fly.
*/ */
double WimaAreaData::maxAltitude() const double WimaAreaData::maxAltitude() const { return _maxAltitude; }
{
return _maxAltitude;
}
/*! /*!
* \fn double WimaAreaData::maxAltitude() * \fn double WimaAreaData::maxAltitude()
* *
* Returns the path (vertex list defining the \l {Simple Polygon}). * Returns the path (vertex list defining the \l {Simple Polygon}).
*/ */
QVariantList WimaAreaData::path() const QVariantList WimaAreaData::path() const { return _path; }
{
return _path;
}
QGeoCoordinate WimaAreaData::center() const QGeoCoordinate WimaAreaData::center() const { return _center; }
{
return _center;
}
const QList<QGeoCoordinate> &WimaAreaData::coordinateList() const const QList<QGeoCoordinate> &WimaAreaData::coordinateList() const {
{ return _list;
return _list;
} }
bool WimaAreaData::containsCoordinate(const QGeoCoordinate &coordinate) const bool WimaAreaData::containsCoordinate(const QGeoCoordinate &coordinate) const {
{ using namespace PlanimetryCalculus;
using namespace PlanimetryCalculus; using namespace PolygonCalculus;
using namespace PolygonCalculus; using namespace GeoUtilities;
using namespace GeoUtilities;
if (_path.size() > 2) {
if (_path.size() > 2) { QPolygonF polygon;
QPolygonF polygon; toCartesianList(this->coordinateList(), coordinate, polygon);
toCartesianList(this->coordinateList(), coordinate, polygon); return PlanimetryCalculus::contains(polygon, QPointF(0, 0));
return PlanimetryCalculus::contains(polygon, QPointF(0,0)); } else
} else return false;
return false;
} }
void WimaAreaData::append(const QGeoCoordinate &c) { void WimaAreaData::append(const QGeoCoordinate &c) {
_list.append(c); _list.append(c);
_path.push_back(QVariant::fromValue(c)); _path.push_back(QVariant::fromValue(c));
} }
void WimaAreaData::push_back(const QGeoCoordinate &c) void WimaAreaData::push_back(const QGeoCoordinate &c) { append(c); }
{
append(c);
}
void WimaAreaData::clear() { void WimaAreaData::clear() {
_list.clear(); _list.clear();
_path.clear(); _path.clear();
} }
/*! /*!
* \fn void WimaAreaData::setMaxAltitude(double maxAltitude) * \fn void WimaAreaData::setMaxAltitude(double maxAltitude)
* *
* Sets the maximum altitude member to \a maxAltitude and emits the \c maxAltitudeChanged() signal if * Sets the maximum altitude member to \a maxAltitude and emits the \c
* \a maxAltitude differs from the members value. * maxAltitudeChanged() signal if \a maxAltitude differs from the members value.
*/ */
void WimaAreaData::setMaxAltitude(double maxAltitude) void WimaAreaData::setMaxAltitude(double maxAltitude) {
{ if (!qFuzzyCompare(_maxAltitude, maxAltitude)) {
if ( !qFuzzyCompare(_maxAltitude, maxAltitude) ) { _maxAltitude = maxAltitude;
_maxAltitude = maxAltitude;
emit maxAltitudeChanged(_maxAltitude); emit maxAltitudeChanged(_maxAltitude);
} }
} }
void WimaAreaData::setPath(const QVariantList &coordinateList) void WimaAreaData::setPath(const QVariantList &coordinateList) {
{ _path = coordinateList;
_path = coordinateList; _list.clear();
_list.clear(); for (auto variant : coordinateList) {
for (auto variant : coordinateList) { _list.push_back(variant.value<QGeoCoordinate>());
_list.push_back(variant.value<QGeoCoordinate>()); }
}
} }
void WimaAreaData::setCenter(const QGeoCoordinate &center) void WimaAreaData::setCenter(const QGeoCoordinate &center) {
{ if (_center != center) {
if (_center != center) { _center = center;
_center = center;
emit centerChanged(); emit centerChanged();
} }
} }
/*! /*!
...@@ -104,46 +86,43 @@ void WimaAreaData::setCenter(const QGeoCoordinate &center) ...@@ -104,46 +86,43 @@ void WimaAreaData::setCenter(const QGeoCoordinate &center)
* *
* Assigns \a other to the invoking object * Assigns \a other to the invoking object
*/ */
void WimaAreaData::assign(const WimaAreaData &other) void WimaAreaData::assign(const WimaAreaData &other) {
{ setMaxAltitude(other.maxAltitude());
setMaxAltitude(other.maxAltitude()); setPath(other.path());
setPath(other.path()); setCenter(other.center());
setCenter(other.center());
} }
void WimaAreaData::assign(const WimaArea &other) void WimaAreaData::assign(const WimaArea &other) {
{ setMaxAltitude(other.maxAltitude());
setMaxAltitude(other.maxAltitude()); setPath(other.path());
setPath(other.path()); setCenter(other.center());
setCenter(other.center());
} }
/*! /*!
* \fn void WimaAreaData::setPath(const QList<QGeoCoordinate> &coordinateList) * \fn void WimaAreaData::setPath(const QList<QGeoCoordinate> &coordinateList)
* *
* Sets the path member to \a coordinateList by copying all entries of \a coordinateList. * Sets the path member to \a coordinateList by copying all entries of \a
* Emits the \c pathChanged() signal. * coordinateList. Emits the \c pathChanged() signal.
*/ */
void WimaAreaData::setPath(const QList<QGeoCoordinate> &coordinateList) void WimaAreaData::setPath(const QList<QGeoCoordinate> &coordinateList) {
{ _list = coordinateList;
_list = coordinateList;
_path.clear(); _path.clear();
// copy all coordinates to _path // copy all coordinates to _path
for(int i = 0; i < coordinateList.size(); i++) { for (int i = 0; i < coordinateList.size(); i++) {
_path.append(QVariant::fromValue(coordinateList.value(i))); _path.append(QVariant::fromValue(coordinateList.value(i)));
} }
emit pathChanged(_path); emit pathChanged(_path);
} }
/*! /*!
* \class WimaArea::WimaAreaData * \class WimaArea::WimaAreaData
* \brief Class to store and exchange data of a \c WimaArea Object. * \brief Class to store and exchange data of a \c WimaArea Object.
* Class to store and exchange data of a \c WimaArea Object. In contrast to \c WimaArea this class * Class to store and exchange data of a \c WimaArea Object. In contrast to \c
* does not uses the QGC Fact System. It is designed to exchange data between the \c WimaPlaner and * WimaArea this class does not uses the QGC Fact System. It is designed to
* the \c WimaController class. And it is the base class for any derived data objects * exchange data between the \c WimaPlaner and the \c WimaController class. And
* it is the base class for any derived data objects
* *
* \sa WimaArea * \sa WimaArea
*/ */
...@@ -6,52 +6,53 @@ ...@@ -6,52 +6,53 @@
#include "WimaArea.h" #include "WimaArea.h"
class WimaAreaData : public QObject// Abstract class for all WimaAreaData derived objects class WimaAreaData
: public QObject // Abstract class for all WimaAreaData derived objects
{ {
Q_OBJECT Q_OBJECT
public: public:
Q_PROPERTY(const QVariantList path READ path NOTIFY pathChanged) Q_PROPERTY(const QVariantList path READ path NOTIFY pathChanged)
Q_PROPERTY(QString type READ type CONSTANT) Q_PROPERTY(QString type READ type CONSTANT)
WimaAreaData(QObject *parent = nullptr); WimaAreaData(QObject *parent = nullptr);
WimaAreaData(const WimaAreaData& otherData) = delete; // avoid slicing ~WimaAreaData();
WimaAreaData& operator=(const WimaAreaData& otherData) = delete; // avoid slicing WimaAreaData(const WimaAreaData &otherData) = delete; // avoid slicing
WimaAreaData &
double maxAltitude() const; operator=(const WimaAreaData &otherData) = delete; // avoid slicing
QVariantList path() const;
QGeoCoordinate center() const; double maxAltitude() const;
const QList<QGeoCoordinate> &coordinateList() const; QVariantList path() const;
bool containsCoordinate(const QGeoCoordinate &coordinate) const; QGeoCoordinate center() const;
virtual QString type() const = 0; const QList<QGeoCoordinate> &coordinateList() const;
bool containsCoordinate(const QGeoCoordinate &coordinate) const;
void append(const QGeoCoordinate &c); virtual QString type() const = 0;
void push_back(const QGeoCoordinate &c);
void clear(); void append(const QGeoCoordinate &c);
void push_back(const QGeoCoordinate &c);
void clear();
signals: signals:
void maxAltitudeChanged (double maxAltitude); void maxAltitudeChanged(double maxAltitude);
void pathChanged (const QVariantList& coordinateList); void pathChanged(const QVariantList &coordinateList);
void centerChanged (void); void centerChanged(void);
public slots: public slots:
void setMaxAltitude(double maxAltitude); void setMaxAltitude(double maxAltitude);
void setPath(const QList<QGeoCoordinate> &coordinateList); void setPath(const QList<QGeoCoordinate> &coordinateList);
void setPath(const QVariantList &coordinateList); void setPath(const QVariantList &coordinateList);
void setCenter(const QGeoCoordinate &center); void setCenter(const QGeoCoordinate &center);
protected: protected:
void assign(const WimaAreaData &other); void assign(const WimaAreaData &other);
void assign(const WimaArea &other); void assign(const WimaArea &other);
private: private:
// Member Functions // Member Functions
// Member Variables // Member Variables
// see WimaArea.h for explanation // see WimaArea.h for explanation
double _maxAltitude; double _maxAltitude;
QVariantList _path; QVariantList _path;
QList<QGeoCoordinate> _list; QList<QGeoCoordinate> _list;
QGeoCoordinate _center; QGeoCoordinate _center;
}; };
...@@ -107,9 +107,13 @@ Fact *WimaMeasurementArea::showTiles() { return &_showTiles; } ...@@ -107,9 +107,13 @@ Fact *WimaMeasurementArea::showTiles() { return &_showTiles; }
QmlObjectListModel *WimaMeasurementArea::tiles() { return this->_pTiles.get(); } QmlObjectListModel *WimaMeasurementArea::tiles() { return this->_pTiles.get(); }
int WimaMeasurementArea::maxTiles() { return SNAKE_MAX_TILES; } const QmlObjectListModel *WimaMeasurementArea::tiles() const {
return this->_pTiles.get();
}
int WimaMeasurementArea::maxTiles() const { return SNAKE_MAX_TILES; }
bool WimaMeasurementArea::ready() { return !_calculating; } bool WimaMeasurementArea::ready() const { return !_calculating; }
void WimaMeasurementArea::saveToJson(QJsonObject &json) { void WimaMeasurementArea::saveToJson(QJsonObject &json) {
this->WimaArea::saveToJson(json); this->WimaArea::saveToJson(json);
......
...@@ -37,8 +37,9 @@ public: ...@@ -37,8 +37,9 @@ public:
Fact *minTransectLength(); Fact *minTransectLength();
Fact *showTiles(); Fact *showTiles();
QmlObjectListModel *tiles(); QmlObjectListModel *tiles();
int maxTiles(); const QmlObjectListModel *tiles() const;
bool ready(); int maxTiles() const;
bool ready() const;
// Member Methodes // Member Methodes
void saveToJson(QJsonObject &json); void saveToJson(QJsonObject &json);
......
...@@ -47,9 +47,9 @@ QString WimaMeasurementAreaData::type() const { return this->typeString; } ...@@ -47,9 +47,9 @@ QString WimaMeasurementAreaData::type() const { return this->typeString; }
void WimaMeasurementAreaData::assign(const WimaMeasurementAreaData &other) { void WimaMeasurementAreaData::assign(const WimaMeasurementAreaData &other) {
WimaAreaData::assign(other); WimaAreaData::assign(other);
this->tiles.clearAndDeleteContents(); this->tiles.clearAndDeleteContents();
for (std::size_t i = 0; i < other.tiles.count(); ++i) { for (std::size_t i = 0; i < std::size_t(other.tiles.count()); ++i) {
auto *obj = other.tiles.get(i); const auto *obj = other.tiles.get(i);
auto *tile = qobject_cast<SnakeTile *>(obj); const auto *tile = qobject_cast<const SnakeTile *>(obj);
if (tile != nullptr) { if (tile != nullptr) {
this->tiles.append(new SnakeTile(*tile, this)); this->tiles.append(new SnakeTile(*tile, this));
} else { } else {
...@@ -62,9 +62,9 @@ void WimaMeasurementAreaData::assign(const WimaMeasurementArea &other) { ...@@ -62,9 +62,9 @@ void WimaMeasurementAreaData::assign(const WimaMeasurementArea &other) {
WimaAreaData::assign(other); WimaAreaData::assign(other);
this->tiles.clearAndDeleteContents(); this->tiles.clearAndDeleteContents();
if (other.ready()) { if (other.ready()) {
for (std::size_t i = 0; i < other.tiles()->count(); ++i) { for (std::size_t i = 0; i < std::size_t(other.tiles()->count()); ++i) {
auto *obj = other.tiles()->get(i); const auto *obj = other.tiles()->get(i);
auto *tile = qobject_cast<SnakeTile *>(obj); const auto *tile = qobject_cast<const SnakeTile *>(obj);
if (tile != nullptr) { if (tile != nullptr) {
this->tiles.append(new SnakeTile(*tile, this)); this->tiles.append(new SnakeTile(*tile, this));
} else { } else {
......
...@@ -7,6 +7,12 @@ SnakeTile::SnakeTile(const SnakeTile &other, QObject *parent) ...@@ -7,6 +7,12 @@ SnakeTile::SnakeTile(const SnakeTile &other, QObject *parent)
*this = other; *this = other;
} }
SnakeTile::~SnakeTile() {}
QString SnakeTile::type() const { return "Tile"; }
SnakeTile *SnakeTile::Clone() const { return new SnakeTile(*this); }
SnakeTile &SnakeTile::operator=(const SnakeTile &other) { SnakeTile &SnakeTile::operator=(const SnakeTile &other) {
this->assign(other); this->assign(other);
return *this; return *this;
......
...@@ -3,12 +3,14 @@ ...@@ -3,12 +3,14 @@
#include "Wima/Geometry/WimaAreaData.h" #include "Wima/Geometry/WimaAreaData.h"
class SnakeTile : public WimaAreaData { class SnakeTile : public WimaAreaData {
Q_OBJECT
public: public:
SnakeTile(QObject *parent = nullptr); SnakeTile(QObject *parent = nullptr);
SnakeTile(const SnakeTile &other, QObject *parent = nullptr); SnakeTile(const SnakeTile &other, QObject *parent = nullptr);
~SnakeTile();
QString type() const { return "Tile"; } QString type() const override;
SnakeTile *Clone() const { return new SnakeTile(*this); } SnakeTile *Clone() const;
SnakeTile &operator=(const SnakeTile &other); SnakeTile &operator=(const SnakeTile &other);
......
...@@ -424,41 +424,34 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) { ...@@ -424,41 +424,34 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) {
emit visualItemsChanged(); emit visualItemsChanged();
// Copy transects. // Copy transects.
this->_rawTransects = planData->transects(); auto tempMissionItems = planData->missionItems();
if (tempMissionItems.size() < 1) {
qWarning("WimaController: Mission items from WimaPlaner empty!");
return false;
}
for (auto *item : tempMissionItems) {
_defaultWM.push_back(item->coordinate());
}
// // extract mission items // // extract mission items
_WMSettings.setHomePosition(QGeoCoordinate(
_serviceArea.depot().latitude(), _serviceArea.depot().longitude(), 0));
// auto tempMissionItems = planData->missionItems(); // auto tempMissionItems = planData->missionItems();
if (!_defaultWM.reset()) {
Q_ASSERT(false);
return false;
}
// if (tempMissionItems.size() < 1) { // if (tempMissionItems.size() < 1) {
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit waypointPathChanged();
emit currentWaypointPathChanged();
// qWarning("WimaController: Mission items from WimaPlaner empty!"); // qWarning("WimaController: Mission items from WimaPlaner empty!");
// return false; // return false;
// } _snakeThread.setMeasurementArea(_measurementArea.coordinateList());
_snakeThread.setServiceArea(_serviceArea.coordinateList());
// qWarning() << "WimaController:"; _snakeThread.setCorridor(_corridor.coordinateList());
// for (auto *item : tempMissionItems) { _currentThread->start();
// qWarning() << item->coordinate();
// _defaultWM.push_back(item->coordinate());
// }
// _WMSettings.setHomePosition(QGeoCoordinate(
// _serviceArea.depot().latitude(), _serviceArea.depot().longitude(),
// 0));
// qWarning() << "service area depot: " << _serviceArea.depot();
// if (!_defaultWM.reset()) {
// qWarning() << "_defaultWM.reset() failed";
// return false;
// }
// emit missionItemsChanged();
// emit currentMissionItemsChanged();
// emit waypointPathChanged();
// emit currentWaypointPathChanged();
// // Update Snake Data Manager
// _snakeThread.setMeasurementArea(_measurementArea.coordinateList());
// _snakeThread.setServiceArea(_serviceArea.coordinateList());
// _snakeThread.setCorridor(_corridor.coordinateList());
// _currentThread->start();
_localPlanDataValid = true; _localPlanDataValid = true;
return true; return true;
......
...@@ -294,6 +294,11 @@ private: ...@@ -294,6 +294,11 @@ private:
SettingsFact _arrivalReturnSpeed; // arrival and return path speed SettingsFact _arrivalReturnSpeed; // arrival and return path speed
SettingsFact _altitude; // mission altitude SettingsFact _altitude; // mission altitude
SettingsFact _enableSnake; // Enable Snake (see snake.h) SettingsFact _enableSnake; // Enable Snake (see snake.h)
SettingsFact _snakeTileWidth;
SettingsFact _snakeTileHeight;
SettingsFact _snakeMinTileArea;
SettingsFact _snakeLineDistance;
SettingsFact _snakeMinTransectLength;
// Smart RTL. // Smart RTL.
QTimer _smartRTLTimer; QTimer _smartRTLTimer;
...@@ -304,6 +309,7 @@ private: ...@@ -304,6 +309,7 @@ private:
// Snake // Snake
QList<QList<QGeoCoordinate>> _rawTransects; QList<QList<QGeoCoordinate>> _rawTransects;
QmlObjectListModel tiles;
SnakeThread _snakeThread; // Snake Data Manager SnakeThread _snakeThread; // Snake Data Manager
SnakeThread _emptyThread; SnakeThread _emptyThread;
SnakeThread *_currentThread; SnakeThread *_currentThread;
......
...@@ -76,10 +76,6 @@ void WimaPlanData::append(const WimaCorridorData &areaData) { ...@@ -76,10 +76,6 @@ void WimaPlanData::append(const WimaCorridorData &areaData) {
} }
} }
void WimaPlanData::setTransects(const QList<QList<QGeoCoordinate>> &transects) {
this->_transects = transects;
}
/*! /*!
* \fn void WimaPlanData::append(const WimaServiceAreaData &areaData) * \fn void WimaPlanData::append(const WimaServiceAreaData &areaData)
* *
...@@ -114,10 +110,6 @@ const QList<const WimaAreaData *> &WimaPlanData::areaList() const { ...@@ -114,10 +110,6 @@ const QList<const WimaAreaData *> &WimaPlanData::areaList() const {
return _areaList; return _areaList;
} }
const QList<QList<QGeoCoordinate>> &WimaPlanData::transects() const {
return _transects;
}
const QList<MissionItem *> &WimaPlanData::missionItems() const { const QList<MissionItem *> &WimaPlanData::missionItems() const {
return _missionItems; return _missionItems;
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "Geometry/WimaJoinedAreaData.h" #include "Geometry/WimaJoinedAreaData.h"
#include "Geometry/WimaMeasurementAreaData.h" #include "Geometry/WimaMeasurementAreaData.h"
#include "Geometry/WimaServiceAreaData.h" #include "Geometry/WimaServiceAreaData.h"
#include "MissionItem.h"
class WimaPlanData : public QObject { class WimaPlanData : public QObject {
Q_OBJECT Q_OBJECT
...@@ -20,6 +21,7 @@ public: ...@@ -20,6 +21,7 @@ public:
void append(const WimaJoinedAreaData &areaData); void append(const WimaJoinedAreaData &areaData);
void append(const WimaServiceAreaData &areaData); void append(const WimaServiceAreaData &areaData);
void append(const WimaCorridorData &areaData); void append(const WimaCorridorData &areaData);
void append(const WimaMeasurementAreaData &areaData);
void setTransects(const QList<QList<QGeoCoordinate>> &transects); void setTransects(const QList<QList<QGeoCoordinate>> &transects);
//! //!
...@@ -31,6 +33,7 @@ public: ...@@ -31,6 +33,7 @@ public:
const QList<const WimaAreaData *> &areaList() const; const QList<const WimaAreaData *> &areaList() const;
const QList<QList<QGeoCoordinate>> &transects() const; const QList<QList<QGeoCoordinate>> &transects() const;
const QList<MissionItem *> &missionItems() const;
signals: signals:
void areaListChanged(); void areaListChanged();
...@@ -43,4 +46,5 @@ private: ...@@ -43,4 +46,5 @@ private:
QList<const WimaAreaData *> _areaList; QList<const WimaAreaData *> _areaList;
QList<QList<QGeoCoordinate>> _transects; QList<QList<QGeoCoordinate>> _transects;
QList<MissionItem *> _missionItems;
}; };
#include "WimaPlanData.h"
WimaPlanData::WimaPlanData(QObject *parent) : QObject(parent) {}
WimaPlanData::WimaPlanData(const WimaPlanData &other, QObject *parent)
: QObject(parent) {
*this = other;
}
/*!
* \fn WimaPlanData &WimaPlanData::operator=(const WimaPlanData &other)
*
* Copies the data area list of \a other to the calling \c WimaPlanData object.
* Returns a reference to the calling \c WimaPlanData object.
*/
WimaPlanData &WimaPlanData::operator=(const WimaPlanData &other) {
// copy wima areas
QList<const WimaAreaData *> areaList = other.areaList();
_areaList.clear();
for (int i = 0; i < areaList.size(); i++) {
const WimaAreaData *areaData = areaList[i];
// determine area type and append
if (areaData->type() == WimaJoinedAreaData::typeString) {
this->append(*qobject_cast<const WimaJoinedAreaData *>(areaData));
} else if (areaData->type() == WimaServiceAreaData::typeString) {
this->append(*qobject_cast<const WimaServiceAreaData *>(areaData));
} else if (areaData->type() == WimaMeasurementAreaData::typeString) {
this->append(*qobject_cast<const WimaMeasurementAreaData *>(areaData));
} else if (areaData->type() == WimaCorridorData::typeString) {
this->append(*qobject_cast<const WimaCorridorData *>(areaData));
}
}
// copy mission items
_missionItems = other.missionItems();
return *this;
}
/*!
* \fn void WimaPlanData::append(const WimaAreaData &areaData)
*
* Adds a WimaAreaData item.
*/
void WimaPlanData::append(const WimaJoinedAreaData &areaData) {
_joinedArea = areaData;
if (!_areaList.contains(&_joinedArea)) {
_areaList.append(&_joinedArea);
}
}
/*!
* \fn void WimaPlanData::append(const WimaServiceAreaData &areaData)
*
* Adds a WimaServiceAreaData item.
*/
void WimaPlanData::append(const WimaServiceAreaData &areaData) {
_serviceArea = areaData;
if (!_areaList.contains(&_serviceArea)) {
_areaList.append(&_serviceArea);
}
}
/*!
* \fn void WimaPlanData::append(const WimaServiceAreaData &areaData)
*
* Adds a WimaCorridorData item.
*/
void WimaPlanData::append(const WimaCorridorData &areaData) {
_corridor = areaData;
if (!_areaList.contains(&_corridor)) {
_areaList.append(&_corridor);
}
}
/*!
* \fn void WimaPlanData::append(const WimaServiceAreaData &areaData)
*
* Adds a WimaMeasurementAreaData item.
*/
void WimaPlanData::append(const WimaMeasurementAreaData &areaData) {
_measurementArea = areaData;
if (!_areaList.contains(&_measurementArea)) {
_areaList.append(&_measurementArea);
}
}
void WimaPlanData::append(const QList<MissionItem *> &missionItems) {
for (auto *item : missionItems) {
item->setParent(this);
_missionItems.append(item);
}
}
/*!
* \fn void WimaPlanData::append(const WimaServiceAreaData &areaData)
*
* Clears all stored objects
*/
void WimaPlanData::clear() {
_areaList.clear();
_missionItems.clear();
}
const QList<const WimaAreaData *> &WimaPlanData::areaList() const {
return _areaList;
}
const QList<MissionItem> &WimaPlanData::missionItems() const {
return _missionItems;
}
/*!
* \class WimaPlanData
* \brief Class storing data generated by the \c WimaPlaner class.
*
* This class is designed to store data generated by the \c WimaPlaner class and
* meant for data exchange between the \c WimaController and the \c WimaPlanner.
* It stores a QList of \c WimaAreaData objects, called area data list,
* containing the data of serveral \c WimaAreas generated by the \c WimaPlaner.
*
* \sa QList
*/
...@@ -741,7 +741,14 @@ QSharedPointer<WimaPlanData> WimaPlaner::toPlanData() { ...@@ -741,7 +741,14 @@ QSharedPointer<WimaPlanData> WimaPlaner::toPlanData() {
planData->append(WimaJoinedAreaData(_joinedArea)); planData->append(WimaJoinedAreaData(_joinedArea));
// convert mission items to mavlink commands // convert mission items to mavlink commands
planData->setTransects(this->_TSComplexItem->rawTransects()); QList<MissionItem *> missionItems;
_TSComplexItem->appendMissionItems(missionItems, nullptr);
// store mavlink commands
qWarning() << "WimaPlaner";
for (auto *item : missionItems) {
qWarning() << item->coordinate();
}
planData->append(missionItems);
return planData; return planData;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment