Commit dfceedc3 authored by Valentin Platzgummer's avatar Valentin Platzgummer

wima planer, plan data, wima controller edited

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