Commit dd135422 authored by Valentin Platzgummer's avatar Valentin Platzgummer

editing added to RouteComplexItem

parent 0877c5b7
......@@ -421,6 +421,8 @@ INCLUDEPATH += \
src/Vehicle \
src/Audio \
src/comm \
src/RouteMissionItem \
src/RouteMissionItem/geometry \
src/comm/ros_bridge \
src/input \
src/lib/qmapcontrol \
......@@ -445,7 +447,11 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
HEADERS += \
src/QmlControls/QmlUnitsConversion.h \
src/RouteMissionItem/geometry/GeoArea.h \
src/RouteMissionItem/geometry/MeasurementArea.h \
src/RouteMissionItem/geometry/SafeArea.h \
src/Vehicle/VehicleEscStatusFactGroup.h \
src/RouteMissionItem/AreaData.h \
src/RouteMissionItem/RouteComplexItem.h \
src/RouteMissionItem/GenericSingelton.h \
src/RouteMissionItem/geometry/GenericCircle.h \
......@@ -492,12 +498,6 @@ HEADERS += \
src/api/QGCSettings.h \
src/api/QmlComponentInfo.h \
src/GPS/Drivers/src/base_station.h \
src/RouteMissionItem/geometry/WimaArea.h \
src/RouteMissionItem/geometry/WimaServiceArea.h \
src/RouteMissionItem/geometry/WimaMeasurementArea.h \
src/RouteMissionItem/geometry/PlanimetryCalculus.h \
src/RouteMissionItem/geometry/PolygonCalculus.h \
src/RouteMissionItem/OptimisationTools.h \
src/Settings/WimaSettings.h \
src/comm/ros_bridge/include/RosBridgeClient.h \
src/comm/ros_bridge/include/com_private.h \
......@@ -522,6 +522,9 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
}
SOURCES += \
src/RouteMissionItem/geometry/GeoArea.cc \
src/RouteMissionItem/geometry/MeasurementArea.cc \
src/RouteMissionItem/geometry/SafeArea.cc \
src/Vehicle/VehicleEscStatusFactGroup.cc \
src/RouteMissionItem/AreaData.cc \
src/api/QGCCorePlugin.cc \
......@@ -554,12 +557,6 @@ SOURCES += \
src/comm/ros_bridge/include/server.cpp \
src/comm/ros_bridge/include/topic_publisher.cpp \
src/comm/ros_bridge/include/topic_subscriber.cpp \
src/RouteMissionItem/geometry/WimaArea.cc \
src/RouteMissionItem/geometry/WimaServiceArea.cc \
src/RouteMissionItem/geometry/WimaMeasurementArea.cc \
src/RouteMissionItem/geometry/PlanimetryCalculus.cc \
src/RouteMissionItem/OptimisationTools.cc \
src/RouteMissionItem/geometry/PolygonCalculus.cc \
src/Settings/WimaSettings.cc \
src/comm/ros_bridge/src/ros_bridge.cpp
......
......@@ -261,7 +261,6 @@
<file alias="QmlTest.qml">src/QmlControls/QmlTest.qml</file>
<file alias="RadioComponent.qml">src/AutoPilotPlugins/Common/RadioComponent.qml</file>
<file alias="SerialSettings.qml">src/ui/preferences/SerialSettings.qml</file>
<file alias="Wima/WimaAreaNoVisual.qml">src/Wima/Snake/WimaAreaNoVisual.qml</file>
<file alias="CircularGeneratorEditor.qml">src/WimaView/CircularGeneratorEditor.qml</file>
<file alias="QGroundControl/Controls/CircularGeneratorMapVisual.qml">src/WimaView/CircularGeneratorMapVisual.qml</file>
<file alias="CircularSurveyItemEditor.qml">src/WimaView/CircularSurveyItemEditor.qml</file>
......@@ -273,21 +272,14 @@
<file alias="Wima/ProgressIndicator.qml">src/WimaView/ProgressIndicator.qml</file>
<file alias="Wima/qmldir">src/WimaView/Wima.qmldir</file>
<file alias="Wima/WimaAreaMapVisual.qml">src/WimaView/WimaAreaMapVisual.qml</file>
<file alias="Wima/WimaCorridorDataVisual.qml">src/WimaView/WimaCorridorDataVisual.qml</file>
<file alias="Wima/WimaCorridorEditor.qml">src/WimaView/WimaCorridorEditor.qml</file>
<file alias="Wima/WimaCorridorMapVisual.qml">src/WimaView/WimaCorridorMapVisual.qml</file>
<file alias="Wima/WimaItemEditor.qml">src/WimaView/WimaItemEditor.qml</file>
<file alias="Wima/WimaJoinedAreaDataVisual.qml">src/WimaView/WimaJoinedAreaDataVisual.qml</file>
<file alias="Wima/WimaJoinedAreaMapVisual.qml">src/WimaView/WimaJoinedAreaMapVisual.qml</file>
<file alias="Wima/WimaMapPolygonVisuals.qml">src/WimaView/WimaMapPolygonVisuals.qml</file>
<file alias="Wima/WimaMapPolylineVisuals.qml">src/WimaView/WimaMapPolylineVisuals.qml</file>
<file alias="Wima/WimaMapVisual.qml">src/WimaView/WimaMapVisual.qml</file>
<file alias="Wima/WimaMeasurementAreaDataVisual.qml">src/WimaView/WimaMeasurementAreaDataVisual.qml</file>
<file alias="Wima/WimaMeasurementAreaEditor.qml">src/WimaView/WimaMeasurementAreaEditor.qml</file>
<file alias="Wima/WimaMeasurementAreaMapVisual.qml">src/WimaView/WimaMeasurementAreaMapVisual.qml</file>
<file alias="Wima/WimaServiceAreaDataVisual.qml">src/WimaView/WimaServiceAreaDataVisual.qml</file>
<file alias="Wima/WimaServiceAreaEditor.qml">src/WimaView/WimaServiceAreaEditor.qml</file>
<file alias="Wima/WimaServiceAreaMapVisual.qml">src/WimaView/WimaServiceAreaMapVisual.qml</file>
<file alias="Wima/WimaMeasurementAreaEditor.qml">src/WimaView/MeasurementAreaEditor.qml</file>
<file alias="Wima/WimaMeasurementAreaMapVisual.qml">src/WimaView/MeasurementAreaMapVisual.qml</file>
<file alias="Wima/WimaServiceAreaEditor.qml">src/WimaView/SafeAreaEditor.qml</file>
<file alias="Wima/WimaServiceAreaMapVisual.qml">src/WimaView/SafeAreaMapVisual.qml</file>
<file alias="Wima/WimaToolBar.qml">src/WimaView/WimaToolBar.qml</file>
<file alias="SetupParameterEditor.qml">src/VehicleSetup/SetupParameterEditor.qml</file>
<file alias="SetupView.qml">src/VehicleSetup/SetupView.qml</file>
......@@ -360,9 +352,9 @@
<file alias="Video.SettingsGroup.json">src/Settings/Video.SettingsGroup.json</file>
<file alias="VTOLLandingPattern.FactMetaData.json">src/MissionManager/VTOLLandingPattern.FactMetaData.json</file>
<file alias="Wima.SettingsGroup.json">src/Settings/Wima.SettingsGroup.json</file>
<file alias="CircularSurvey.SettingsGroup.json">src/Wima/json/CircularSurvey.SettingsGroup.json</file>
<file alias="LinearGenerator.SettingsGroup.json">src/Wima/Snake/json/LinearGenerator.SettingsGroup.json</file>
<file alias="CircularGenerator.SettingsGroup.json">src/Wima/Snake/json/CircularGenerator.SettingsGroup.json</file>
<file alias="RouteComplexItem.SettingsGroup.json">src/RouteMissionItem/json/RouteComplexItem.SettingsGroup.json</file>
<file alias="LinearGenerator.SettingsGroup.json">src/RouteMissionItem/json/LinearGenerator.SettingsGroup.json</file>
<file alias="CircularGenerator.SettingsGroup.json">src/RouteMissionItem/json/CircularGenerator.SettingsGroup.json</file>
</qresource>
<qresource prefix="/MockLink">
<file alias="APMArduSubMockLink.params">src/comm/APMArduSubMockLink.params</file>
......
This diff is collapsed.
......@@ -26,7 +26,7 @@
#include "QmlObjectListModel.h"
class SurveyComplexItem;
class CircularSurvey;
class RouteComplexItem;
class SimpleMissionItem;
class MissionController;
#ifdef UNITTEST_BUILD
......@@ -153,7 +153,7 @@ private:
static const char* _jsonParam4Key;
friend class SurveyComplexItem;
friend class CircularSurvey;
friend class RouteComplexItem;
friend class SimpleMissionItem;
friend class MissionController;
#ifdef UNITTEST_BUILD
......
This diff is collapsed.
#include "WimaPlanData.h"
#include "AreaData.h"
AreaData::AreaData(QObject *parent) : QObject(parent) {}
#include "geometry/MeasurementArea.h"
#include "geometry/SafeArea.h"
AreaData::AreaData(const AreaData &other, QObject *parent)
: QObject(parent) {
*this = other;
}
#include "QGCLoggingCategory.h"
#include "QGCQGeoCoordinate.h"
AreaData &AreaData::operator=(const AreaData &other) {
this->append(other.measurementArea());
this->append(other.serviceArea());
this->append(other.joinedArea());
this->append(other.corridor());
QGC_LOGGING_CATEGORY(AreaDataLog, "AreaDataLog")
return *this;
}
AreaData::AreaData(QObject *parent) : QObject(parent) {}
void AreaData::append(const WimaJoinedAreaData &areaData) {
if (_joinedArea != areaData) {
_joinedArea = areaData;
emit joinedAreaChanged();
}
}
AreaData::~AreaData() {}
void AreaData::append(const WimaServiceAreaData &areaData) {
if (_serviceArea != areaData) {
_serviceArea = areaData;
emit serviceAreaChanged();
AreaData::AreaData(const AreaData &other, QObject *parent) : QObject(parent) {
if (!copyAreaList(other._areaList, _areaList, this)) {
qCWarning(AreaDataLog) << "AreaData(): not able to copy other._areaList";
} else {
_origin = other._origin;
}
}
void AreaData::append(const WimaCorridorData &areaData) {
if (_corridor != areaData) {
_corridor = areaData;
emit corridorChanged();
AreaData &AreaData::operator=(const AreaData &other) {
if (!copyAreaList(other._areaList, _areaList, this)) {
qCWarning(AreaDataLog) << "operator=(): not able to copy other._areaList";
} else {
_origin = other._origin;
}
return *this;
}
void AreaData::append(const WimaMeasurementAreaData &areaData) {
if (_measurementArea != areaData) {
_measurementArea = areaData;
emit measurementAreaChanged();
if (_measurementArea.coordinateList().size() > 0) {
setOrigin(_measurementArea.coordinateList().first());
} else {
setOrigin(QGeoCoordinate());
bool AreaData::insert(GeoArea *areaData) {
{
SafeArea *area = qobject_cast<SafeArea *>(areaData);
if (area != nullptr) {
if (Q_LIKELY(!this->_areaList.contains(area))) {
_areaList.append(area);
emit areaList();
return true;
} else {
return false;
}
}
}
}
void AreaData::append(const WimaJoinedArea &areaData) {
if (_joinedArea != areaData) {
_joinedArea = areaData;
emit joinedAreaChanged();
{
MeasurementArea *area = qobject_cast<MeasurementArea *>(areaData);
if (area != nullptr) {
if (Q_LIKELY(!this->_areaList.contains(area))) {
_areaList.append(area);
emit areaList();
return true;
} else {
return false;
}
}
}
}
void AreaData::append(const WimaArea &areaData) {
if (_serviceArea != areaData) {
_serviceArea = areaData;
emit serviceAreaChanged();
}
return false;
}
void AreaData::append(const WimaCorridor &areaData) {
if (_corridor != areaData) {
_corridor = areaData;
emit corridorChanged();
}
}
void AreaData::remove(GeoArea *areaData) {
int index = _areaList.indexOf(areaData);
if (index >= 0) {
QObject *obj = _areaList.removeAt(index);
void AreaData::append(const WimaMeasurementArea &areaData) {
if (_measurementArea != areaData) {
_measurementArea = areaData;
emit measurementAreaChanged();
_setOrigin(_newOrigin());
if (_measurementArea.coordinateList().size() > 0) {
setOrigin(_measurementArea.coordinateList().first());
} else {
setOrigin(QGeoCoordinate());
if (obj->parent() == nullptr) {
obj->deleteLater();
}
}
}
void AreaData::clear() { *this = AreaData(); }
const QGeoCoordinate &AreaData::origin() const { return _origin; }
bool AreaData::isValid() {
return _measurementArea.coordinateList().size() >= 3 &&
_serviceArea.coordinateList().size() >= 3 && _origin.isValid();
emit areaListChanged();
}
}
const WimaJoinedAreaData &AreaData::joinedArea() const {
return this->_joinedArea;
void AreaData::clear() {
if (_areaList.count() > 0) {
for (int i = 0; i < _areaList.count(); ++i) {
remove(_areaList.value<GeoArea *>(i));
}
emit areaListChanged();
}
}
const WimaServiceAreaData &AreaData::serviceArea() const {
return this->_serviceArea;
}
QmlObjectListModel *AreaData::areaList() { return &_areaList; }
const WimaCorridorData &AreaData::corridor() const {
return this->_corridor;
}
const QmlObjectListModel *AreaData::areaList() const { return &_areaList; }
const WimaMeasurementAreaData &AreaData::measurementArea() const {
return this->_measurementArea;
}
const QGeoCoordinate &AreaData::origin() const { return _origin; }
WimaJoinedAreaData &AreaData::joinedArea() { return this->_joinedArea; }
bool AreaData::isValid() const {
qWarning("AreaData::isValid(): impl. incomplete.");
auto *measurementArea = getGeoArea<const MeasurementArea *>(_areaList);
auto *safeArea = getGeoArea<const SafeArea *>(_areaList);
return measurementArea != nullptr && safeArea != nullptr &&
measurementArea->count() >= 3 && safeArea->count() >= 3 &&
_origin.isValid();
}
bool AreaData::tryMakeValid() {
qWarning("AreaData::tryMakeValid(): impl. missing.");
return true;
}
bool AreaData::initialize(const QGeoCoordinate &bottomLeft,
const QGeoCoordinate &topRight) {
// bottomLeft and topRight define the bounding box.
if (bottomLeft.isValid() && topRight.isValid() && bottomLeft != topRight) {
auto *measurementArea = getGeoArea<MeasurementArea *>(_areaList);
auto *safeArea = getGeoArea<SafeArea *>(_areaList);
if (safeArea == nullptr) {
if (!insert(new SafeArea())) {
qCCritical(AreaDataLog)
<< "initialize(): safeArea == nullptr, but insert() failed.";
return false;
}
}
WimaServiceAreaData &AreaData::serviceArea() { return this->_serviceArea; }
if (measurementArea == nullptr) {
if (!insert(new MeasurementArea())) {
qCCritical(AreaDataLog) << "initialize(): measurementArea == nullptr, "
"but insert() failed.";
return false;
}
}
WimaCorridorData &AreaData::corridor() { return this->_corridor; }
// Fit safe area to bounding box.
safeArea->clear();
safeArea->appendVertex(bottomLeft);
safeArea->appendVertex(
QGeoCoordinate(topRight.latitude(), bottomLeft.longitude()));
safeArea->appendVertex(topRight);
safeArea->appendVertex(
QGeoCoordinate(bottomLeft.latitude(), topRight.longitude()));
// Put measurement area inside safeArea;
measurementArea->clear();
measurementArea->appendVertex(QGeoCoordinate(
0.8 * bottomLeft.latitude() + 0.2 * topRight.latitude(),
0.8 * bottomLeft.longitude() + 0.2 * topRight.longitude()));
measurementArea->appendVertex(QGeoCoordinate(
0.2 * bottomLeft.latitude() + 0.8 * topRight.latitude(),
0.8 * bottomLeft.longitude() + 0.2 * topRight.longitude()));
measurementArea->appendVertex(QGeoCoordinate(
0.2 * bottomLeft.latitude() + 0.8 * topRight.latitude(),
0.2 * bottomLeft.longitude() + 0.8 * topRight.longitude()));
measurementArea->appendVertex(QGeoCoordinate(
0.8 * bottomLeft.latitude() + 0.2 * topRight.latitude(),
0.2 * bottomLeft.longitude() + 0.8 * topRight.longitude()));
return true;
} else {
qCWarning(AreaDataLog)
<< "initialize(): bounding box invaldid (bottomLeft, topRight) "
<< bottomLeft << "," << topRight;
return false;
}
}
WimaMeasurementAreaData &AreaData::measurementArea() {
return this->_measurementArea;
bool AreaData::initialized() {
auto *measurementArea = getGeoArea<MeasurementArea *>(_areaList);
auto *safeArea = getGeoArea<SafeArea *>(_areaList);
return measurementArea != nullptr && safeArea != nullptr &&
measurementArea->count() >= 3 && safeArea->count() >= 3;
}
bool AreaData::operator==(const AreaData &other) const {
return this->_joinedArea == other._joinedArea &&
this->_measurementArea == other._measurementArea &&
this->_corridor == other._corridor &&
this->_serviceArea == other._serviceArea;
if (_areaList.count() == other._areaList.count()) {
for (int i = 0; i < _areaList.count(); ++i) {
if (_areaList[i] != other._areaList[i]) {
return false;
}
}
return true;
} else {
return false;
}
}
bool AreaData::operator!=(const AreaData &other) const {
return !(*this == other);
}
void AreaData::setOrigin(const QGeoCoordinate &origin) {
void AreaData::_setOrigin(const QGeoCoordinate &origin) {
if (this->_origin != origin) {
this->_origin = origin;
emit originChanged();
}
}
QGeoCoordinate AreaData::_newOrigin() {
auto *measurementArea = getGeoArea<MeasurementArea *>(_areaList);
auto *safeArea = getGeoArea<SafeArea *>(_areaList);
if (measurementArea != nullptr && measurementArea->pathModel().count() > 0) {
QGCQGeoCoordinate *ori =
measurementArea->pathModel().value<QGCQGeoCoordinate *>(0);
if (ori != nullptr && ori->coordinate().isValid()) {
return ori->coordinate();
}
}
if (safeArea != nullptr && safeArea->pathModel().count() > 0) {
QGCQGeoCoordinate *ori =
measurementArea->pathModel().value<QGCQGeoCoordinate *>(0);
if (ori != nullptr && ori->coordinate().isValid()) {
return ori->coordinate();
}
}
return QGeoCoordinate();
}
#pragma once
#include <QGeoCoordinate>
#include <QObject>
#include "QmlObjectListModel.h"
class GeoArea;
class SafeArea;
class MeasurementArea;
class AreaData : public QObject {
Q_OBJECT
public:
AreaData(QObject *parent = nullptr);
~AreaData();
AreaData(const AreaData &other, QObject *parent = nullptr);
AreaData &operator=(const AreaData &other);
// Member Methodes
//!
//! \brief insert Inserts the area if areaList does not contain it.
//! \param areaData
bool insert(GeoArea *areaData);
//!
//! \brief remove
//! \param areaData Removes the area.
//! \note Deletes the area if it has no parent.
void remove(GeoArea *areaData);
void clear();
//!
//! \brief areaList
//! \return Returns the list of areas.
//! \note For Qml use only, don't alter the list, or risk to break invariants.
QmlObjectListModel *areaList();
//!
//! \brief areaList
//! \return Returns the list of areas.
const QmlObjectListModel *areaList() const;
//!
//! \brief origin
//! \return Returns an origin near one of the areas.
//! \note Origin might change if the list of areas changes.
const QGeoCoordinate &origin() const;
Q_INVOKABLE bool isValid() const;
Q_INVOKABLE bool tryMakeValid();
//!
//! \brief initialize Initializes the areas in a valid way, such that they
//! area inside the bounding box. \param bottomLeft bottom left corner of the
//! bounding box. \param topRight top right corner of the bounding box. \note
//! Behavior is undefined, if \p bottomLeft and \p topRight are not the bottom
//! left and the top right corner of the bounding box. \return Returns true on
//! succes, false either.
//!
Q_INVOKABLE bool initialize(const QGeoCoordinate &bottomLeft,
const QGeoCoordinate &topRight);
//!
//! \brief initialized Checks if area data is initialized
//! \return Returns true if area list contains a SafeArea and a
//! MeasurementArea and both areas have atleast three vertices, returns false
//! either.
//!
Q_INVOKABLE bool initialized();
bool operator==(const AreaData &other) const;
bool operator!=(const AreaData &other) const;
signals:
void areaListChanged();
void originChanged();
private:
void _setOrigin(const QGeoCoordinate &origin);
QGeoCoordinate _newOrigin();
QGeoCoordinate _origin;
QmlObjectListModel _areaList;
};
#include "CircularGenerator.h"
#include "QGCLoggingCategory.h"
QGC_LOGGING_CATEGORY(CircularGeneratorLog, "CircularGeneratorLog")
#include "SettingsFact.h"
#define CLIPPER_SCALE 1000000
#include "Wima/Geometry/GenericCircle.h"
#include "clipper/clipper.hpp"
#include "RoutingThread.h"
#include "geometry/GenericCircle.h"
#include "geometry/MeasurementArea.h"
#include "geometry/SafeArea.h"
#include "geometry/clipper/clipper.hpp"
#include "nemo_interface/SnakeTile.h"
QGC_LOGGING_CATEGORY(CircularGeneratorLog, "CircularGeneratorLog")
using namespace ClipperLib;
template <> inline auto get<0>(const IntPoint &p) { return p.X; }
template <> inline auto get<1>(const IntPoint &p) { return p.Y; }
#include "SnakeTile.h"
#include "Wima/RoutingThread.h"
namespace routing {
bool circularTransects(const snake::FPoint &reference,
......@@ -77,7 +80,13 @@ bool CircularGenerator::get(Generator &generator) {
snake::FPoint reference;
snake::toENU(origin, ref, reference);
auto geoPolygon = this->_d->measurementArea().coordinateList();
auto measurementArea =
getGeoArea<const MeasurementArea *>(*this->_d->areaList());
if (measurementArea == nullptr) {
qCDebug(CircularGeneratorLog) << "get(): measurement area == nullptr";
return false;
}
auto geoPolygon = measurementArea->coordinateList();
for (auto &v : geoPolygon) {
if (v.isValid()) {
v.setAltitude(0);
......@@ -93,8 +102,8 @@ bool CircularGenerator::get(Generator &generator) {
snake::areaToEnu(origin, geoPolygon, *pPolygon);
// Progress and tiles.
const auto &progress = this->_d->measurementArea().progress();
const auto *tiles = this->_d->measurementArea().tiles();
const auto &progress = measurementArea->progress();
const auto *tiles = measurementArea->tiles();
auto pTiles = std::make_shared<std::vector<snake::FPolygon>>();
if (progress.size() == tiles->count()) {
for (int i = 0; i < tiles->count(); ++i) {
......@@ -119,7 +128,12 @@ bool CircularGenerator::get(Generator &generator) {
return false;
}
auto geoDepot = this->_d->serviceArea().depot();
auto serviceArea = getGeoArea<const SafeArea *>(*this->_d->areaList());
if (measurementArea == nullptr) {
qCDebug(CircularGeneratorLog) << "get(): measurement area == nullptr";
return false;
}
auto geoDepot = serviceArea->depot();
if (!geoDepot.isValid()) {
qCDebug(CircularGeneratorLog) << "get(): depot invalid." << geoDepot;
return false;
......@@ -169,73 +183,85 @@ void CircularGenerator::resetReferenceIfInvalid() {
}
void CircularGenerator::resetReference() {
if (this->_d->measurementArea().center().isValid()) {
setReference(this->_d->measurementArea().center());
auto measurementArea =
getGeoArea<const MeasurementArea *>(*this->_d->areaList());
if (measurementArea != nullptr) {
if (measurementArea->center().isValid()) {
setReference(measurementArea->center());
} else {
qCWarning(CircularGeneratorLog)
<< "measurement area center" << measurementArea->center();
}
} else {
qCWarning(CircularGeneratorLog)
<< "measurement area center" << this->_d->measurementArea().center();
qCDebug(CircularGeneratorLog)
<< "resetReference(): measurement area == nullptr";
}
}
void CircularGenerator::establishConnections() {
if (this->_d && !this->_connectionsEstablished) {
connect(this->_d.get(), &AreaData::originChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::progressChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::tileDataChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::centerChanged, this,
&CircularGenerator::resetReferenceIfInvalid);
connect(&this->_d->measurementArea(), &WimaMeasurementAreaData::pathChanged,
this, &GeneratorBase::generatorChanged);
connect(&this->_d->serviceArea(), &WimaServiceAreaData::depotChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->joinedArea(), &WimaJoinedAreaData::pathChanged, this,
&GeneratorBase::generatorChanged);
connect(this->distance(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->deltaAlpha(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->minLength(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this, &CircularGenerator::referenceChanged, this,
&GeneratorBase::generatorChanged);
this->_connectionsEstablished = true;
auto measurementArea =
getGeoArea<const MeasurementArea *>(*this->_d->areaList());
auto serviceArea = getGeoArea<const SafeArea *>(*this->_d->areaList());
if (measurementArea != nullptr && serviceArea != nullptr) {
GeneratorBase::establishConnections();
connect(this->_d, &AreaData::originChanged, this,
&GeneratorBase::generatorChanged);
connect(measurementArea, &MeasurementArea::progressChanged, this,
&GeneratorBase::generatorChanged);
connect(measurementArea, &MeasurementArea::tilesChanged, this,
&GeneratorBase::generatorChanged);
connect(measurementArea, &MeasurementArea::centerChanged, this,
&CircularGenerator::resetReferenceIfInvalid);
connect(measurementArea, &MeasurementArea::pathChanged, this,
&GeneratorBase::generatorChanged);
connect(serviceArea, &SafeArea::depotChanged, this,
&GeneratorBase::generatorChanged);
connect(this->distance(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->deltaAlpha(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->minLength(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this, &CircularGenerator::referenceChanged, this,
&GeneratorBase::generatorChanged);
this->_connectionsEstablished = true;
}
}
}
void CircularGenerator::deleteConnections() {
if (this->_d && this->_connectionsEstablished) {
disconnect(this->_d.get(), &AreaData::originChanged, this,
&GeneratorBase::generatorChanged);
disconnect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::progressChanged, this,
&GeneratorBase::generatorChanged);
disconnect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::tileDataChanged, this,
&GeneratorBase::generatorChanged);
disconnect(&this->_d->measurementArea(), &WimaMeasurementAreaData::center,
this, &CircularGenerator::resetReferenceIfInvalid);
disconnect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::pathChanged, this,
&GeneratorBase::generatorChanged);
disconnect(&this->_d->serviceArea(), &WimaServiceAreaData::depotChanged,
this, &GeneratorBase::generatorChanged);
disconnect(&this->_d->joinedArea(), &WimaJoinedAreaData::pathChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this->distance(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this->deltaAlpha(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this->minLength(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this, &CircularGenerator::referenceChanged, this,
&GeneratorBase::generatorChanged);
this->_connectionsEstablished = false;
auto measurementArea =
getGeoArea<const MeasurementArea *>(*this->_d->areaList());
auto serviceArea = getGeoArea<const SafeArea *>(*this->_d->areaList());
if (measurementArea != nullptr && serviceArea != nullptr) {
GeneratorBase::deleteConnections();
disconnect(this->_d, &AreaData::originChanged, this,
&GeneratorBase::generatorChanged);
disconnect(measurementArea, &MeasurementArea::progressChanged, this,
&GeneratorBase::generatorChanged);
disconnect(measurementArea, &MeasurementArea::tilesChanged, this,
&GeneratorBase::generatorChanged);
disconnect(measurementArea, &MeasurementArea::centerChanged, this,
&CircularGenerator::resetReferenceIfInvalid);
disconnect(measurementArea, &MeasurementArea::pathChanged, this,
&GeneratorBase::generatorChanged);
disconnect(serviceArea, &SafeArea::depotChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this->distance(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this->deltaAlpha(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this->minLength(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this, &CircularGenerator::referenceChanged, this,
&GeneratorBase::generatorChanged);
this->_connectionsEstablished = true;
}
}
}
......
......@@ -2,6 +2,8 @@
#include <QGeoCoordinate>
#include "SettingsFact.h"
namespace routing {
class CircularGenerator : public GeneratorBase {
......
......@@ -12,10 +12,6 @@ GeneratorBase::GeneratorBase(GeneratorBase::Data d, QObject *parent)
GeneratorBase::~GeneratorBase() {}
QString GeneratorBase::editorQml() { return QStringLiteral(""); }
QString GeneratorBase::mapVisualQml() { return QStringLiteral(""); }
GeneratorBase::Data GeneratorBase::data() const { return _d; }
void GeneratorBase::setData(const Data &d) {
......@@ -28,4 +24,9 @@ void GeneratorBase::establishConnections() {}
void GeneratorBase::deleteConnections() {}
void GeneratorBase::_areaListChangedHandler() {
deleteConnections();
establishConnections();
}
} // namespace routing
......@@ -5,16 +5,16 @@
#include <functional>
#include <memory>
#include "snake.h"
#include "geometry/snake.h"
#include "Wima/WimaPlanData.h"
#include "AreaData.h"
namespace routing {
class GeneratorBase : public QObject {
Q_OBJECT
public:
using Data = std::shared_ptr<AreaData>;
using Data = AreaData *;
using Generator = std::function<bool(snake::Transects &)>;
explicit GeneratorBase(QObject *parent = nullptr);
......@@ -24,8 +24,8 @@ public:
Q_PROPERTY(QString editorQml READ editorQml CONSTANT)
Q_PROPERTY(QString mapVisualQml READ mapVisualQml CONSTANT)
virtual QString editorQml();
virtual QString mapVisualQml();
virtual QString editorQml() = 0;
virtual QString mapVisualQml() = 0;
virtual QString name() = 0;
virtual QString abbreviation() = 0;
......@@ -42,6 +42,9 @@ protected:
virtual void establishConnections();
virtual void deleteConnections();
Data _d;
private:
void _areaListChangedHandler();
};
} // namespace routing
......@@ -4,10 +4,12 @@
QGC_LOGGING_CATEGORY(LinearGeneratorLog, "LinearGeneratorLog")
#define CLIPPER_SCALE 1000000
#include "clipper/clipper.hpp"
#include "geometry/MeasurementArea.h"
#include "geometry/SafeArea.h"
#include "geometry/clipper/clipper.hpp"
#include "SnakeTile.h"
#include "Wima/RoutingThread.h"
#include "RoutingThread.h"
#include "nemo_interface/SnakeTile.h"
namespace routing {
......@@ -38,6 +40,8 @@ QString LinearGenerator::editorQml() {
return QStringLiteral("LinearGeneratorEditor.qml");
}
QString LinearGenerator::mapVisualQml() { return QStringLiteral(""); }
QString LinearGenerator::name() { return QStringLiteral("Linear Generator"); }
QString LinearGenerator::abbreviation() { return QStringLiteral("L. Gen."); }
......@@ -52,7 +56,13 @@ bool LinearGenerator::get(Generator &generator) {
qCDebug(LinearGeneratorLog) << "get(): origin invalid." << origin;
}
auto geoPolygon = this->_d->measurementArea().coordinateList();
auto measurementArea =
getGeoArea<const MeasurementArea *>(*this->_d->areaList());
if (measurementArea == nullptr) {
qCDebug(LinearGeneratorLog) << "get(): measurement area == nullptr";
return false;
}
auto geoPolygon = measurementArea->coordinateList();
for (auto &v : geoPolygon) {
if (v.isValid()) {
v.setAltitude(0);
......@@ -68,8 +78,8 @@ bool LinearGenerator::get(Generator &generator) {
snake::areaToEnu(origin, geoPolygon, *pPolygon);
// Progress and tiles.
const auto &progress = this->_d->measurementArea().progress();
const auto *tiles = this->_d->measurementArea().tiles();
const auto &progress = measurementArea->progress();
const auto *tiles = measurementArea->tiles();
auto pTiles = std::make_shared<std::vector<snake::FPolygon>>();
if (progress.size() == tiles->count()) {
for (int i = 0; i < tiles->count(); ++i) {
......@@ -93,7 +103,12 @@ bool LinearGenerator::get(Generator &generator) {
return false;
}
auto geoDepot = this->_d->serviceArea().depot();
auto serviceArea = getGeoArea<const SafeArea *>(*this->_d->areaList());
if (serviceArea == nullptr) {
qCDebug(LinearGeneratorLog) << "get(): service area == nullptr";
return false;
}
auto geoDepot = serviceArea->depot();
if (!geoDepot.isValid()) {
qCDebug(LinearGeneratorLog) << "get(): depot invalid." << geoDepot;
return false;
......@@ -134,53 +149,61 @@ Fact *LinearGenerator::minLength() { return &_minLength; }
void LinearGenerator::establishConnections() {
if (this->_d && !this->_connectionsEstablished) {
connect(this->_d.get(), &AreaData::originChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::progressChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::tileDataChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->measurementArea(), &WimaMeasurementAreaData::pathChanged,
this, &GeneratorBase::generatorChanged);
connect(&this->_d->serviceArea(), &WimaServiceAreaData::depotChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->joinedArea(), &WimaJoinedAreaData::pathChanged, this,
&GeneratorBase::generatorChanged);
connect(this->distance(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->alpha(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->minLength(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
this->_connectionsEstablished = true;
auto measurementArea =
getGeoArea<const MeasurementArea *>(*this->_d->areaList());
auto serviceArea = getGeoArea<const SafeArea *>(*this->_d->areaList());
if (measurementArea != nullptr && serviceArea != nullptr) {
GeneratorBase::establishConnections();
connect(this->_d, &AreaData::originChanged, this,
&GeneratorBase::generatorChanged);
connect(measurementArea, &MeasurementArea::progressChanged, this,
&GeneratorBase::generatorChanged);
connect(measurementArea, &MeasurementArea::tilesChanged, this,
&GeneratorBase::generatorChanged);
connect(measurementArea, &MeasurementArea::pathChanged, this,
&GeneratorBase::generatorChanged);
connect(serviceArea, &SafeArea::depotChanged, this,
&GeneratorBase::generatorChanged);
connect(this->distance(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->alpha(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->minLength(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
this->_connectionsEstablished = true;
}
}
}
void LinearGenerator::deleteConnections() {
if (this->_d && this->_connectionsEstablished) {
connect(this->_d.get(), &AreaData::originChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::progressChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->measurementArea(),
&WimaMeasurementAreaData::tileDataChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->measurementArea(), &WimaMeasurementAreaData::pathChanged,
this, &GeneratorBase::generatorChanged);
connect(&this->_d->serviceArea(), &WimaServiceAreaData::depotChanged, this,
&GeneratorBase::generatorChanged);
connect(&this->_d->joinedArea(), &WimaJoinedAreaData::pathChanged, this,
&GeneratorBase::generatorChanged);
connect(this->distance(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->alpha(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
connect(this->minLength(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
this->_connectionsEstablished = false;
auto measurementArea =
getGeoArea<const MeasurementArea *>(*this->_d->areaList());
auto serviceArea = getGeoArea<const SafeArea *>(*this->_d->areaList());
if (measurementArea != nullptr && serviceArea != nullptr) {
GeneratorBase::deleteConnections();
disconnect(this->_d, &AreaData::originChanged, this,
&GeneratorBase::generatorChanged);
disconnect(measurementArea, &MeasurementArea::progressChanged, this,
&GeneratorBase::generatorChanged);
disconnect(measurementArea, &MeasurementArea::tilesChanged, this,
&GeneratorBase::generatorChanged);
disconnect(measurementArea, &MeasurementArea::pathChanged, this,
&GeneratorBase::generatorChanged);
disconnect(serviceArea, &SafeArea::depotChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this->distance(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this->alpha(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
disconnect(this->minLength(), &Fact::rawValueChanged, this,
&GeneratorBase::generatorChanged);
this->_connectionsEstablished = true;
}
}
}
......
......@@ -2,6 +2,8 @@
#include <QGeoCoordinate>
#include "SettingsFact.h"
namespace routing {
class LinearGenerator : public GeneratorBase {
......@@ -15,6 +17,7 @@ public:
Q_PROPERTY(Fact *minLength READ minLength CONSTANT)
virtual QString editorQml() override;
virtual QString mapVisualQml() override;
virtual QString name() override;
virtual QString abbreviation() override;
......
#include "NemoInterface.h"
#include "SnakeTilesLocal.h"
#include "nemo_interface/SnakeTilesLocal.h"
#include "QGCApplication.h"
#include "QGCLoggingCategory.h"
......@@ -12,11 +12,11 @@
#include <QTimer>
#include "QNemoHeartbeat.h"
#include "QNemoProgress.h"
#include "Wima/Geometry/WimaMeasurementArea.h"
#include "Wima/Snake/SnakeTile.h"
#include "Wima/Snake/snake.h"
#include "geometry/MeasurementArea.h"
#include "geometry/snake.h"
#include "nemo_interface/QNemoHeartbeat.h"
#include "nemo_interface/QNemoProgress.h"
#include "nemo_interface/SnakeTile.h"
#include "ros_bridge/include/messages/geographic_msgs/geopoint.h"
#include "ros_bridge/include/messages/jsk_recognition_msgs/polygon_array.h"
......
#include "OptimisationTools.h"
namespace OptimisationTools {
namespace {
} // end anonymous namespace
bool dijkstraAlgorithm(const int numElements, int startIndex, int endIndex, QVector<int> &elementPath, std::function<double (const int, const int)> distanceDij)
{
if ( numElements < 0
|| startIndex < 0
|| endIndex < 0
|| startIndex >= numElements
|| endIndex >= numElements
|| endIndex == startIndex) {
return false;
}
// Node struct
// predecessorIndex is the index of the predecessor node (nodeList[predecessorIndex])
// distance is the distance between the node and the start node
// node number is stored by the position in nodeList
struct Node{
int predecessorIndex = -1;
double distance = std::numeric_limits<qreal>::infinity();
};
// The list with all Nodes (elements)
QVector<Node> nodeList(numElements);
// This list will be initalized with indices referring to the elements of nodeList.
// Elements will be successively remove during the execution of the Dijkstra Algorithm.
QVector<int> workingSet(numElements);
//append elements to node list
for (int i = 0; i < numElements; ++i) workingSet[i] = i;
nodeList[startIndex].distance = 0;
// qDebug() << "nodeList" ;
// for (auto node : nodeList) {
// qDebug() << "predecessor: " << node.predecessorIndex;
// qDebug() << "distance: " << node.distance;
// }
// qDebug() << "workingSet";
// for (auto node : workingSet) {
// qDebug() << "index: " << node;
// }
// Dijkstra Algorithm
// https://de.wikipedia.org/wiki/Dijkstra-Algorithmus
while (workingSet.size() > 0) {
// serach Node with minimal distance
double minDist = std::numeric_limits<qreal>::infinity();
int minDistIndex_WS = -1; // WS = workinSet
for (int i = 0; i < workingSet.size(); ++i) {
const int nodeIndex = workingSet.at(i);
const double dist = nodeList.at(nodeIndex).distance;
if (dist < minDist) {
minDist = dist;
minDistIndex_WS = i;
}
}
if (minDistIndex_WS == -1)
return false;
int indexU_NL = workingSet.takeAt(minDistIndex_WS); // NL = nodeList
if (indexU_NL == endIndex) // shortest path found
break;
const double distanceU = nodeList.at(indexU_NL).distance;
//update distance
for (int i = 0; i < workingSet.size(); ++i) {
int indexV_NL = workingSet[i]; // NL = nodeList
Node* v = &nodeList[indexV_NL];
double dist = distanceDij(indexU_NL, indexV_NL);
// is ther an alternative path which is shorter?
double alternative = distanceU + dist;
if (alternative < v->distance) {
v->distance = alternative;
v->predecessorIndex = indexU_NL;
}
}
}
// end Djikstra Algorithm
// reverse assemble path
int e = endIndex;
while (1) {
if (e == -1) {
if (elementPath[0] == startIndex)// check if starting point was reached
break;
return false;
}
elementPath.prepend(e);
//Update Node
e = nodeList[e].predecessorIndex;
}
return true;
}
} // end OptimisationTools namespace
#pragma once
#include <QObject>
#include <QDebug>
#include <functional>
#include <QVector>
namespace OptimisationTools {
bool dijkstraAlgorithm(const int numElements, int startIndex, int endIndex, QVector<int> &elementPath, std::function<double(const int, const int)> distanceDij);
}
This diff is collapsed.
......@@ -7,9 +7,7 @@
#include "SettingsFact.h"
#include "TransectStyleComplexItem.h"
#include "Geometry/WimaJoinedAreaData.h"
#include "Geometry/WimaMeasurementAreaData.h"
#include "WimaPlanData.h"
#include "AreaData.h"
class RoutingThread;
class RoutingData;
......@@ -18,21 +16,22 @@ namespace routing {
class GeneratorBase;
}
class CircularSurvey : public TransectStyleComplexItem {
class RouteComplexItem : public TransectStyleComplexItem {
Q_OBJECT
using PtrGenerator = std::shared_ptr<routing::GeneratorBase>;
using PtrGenerator = routing::GeneratorBase *;
using PtrAreaData = AreaData *;
using PtrRoutingData = std::shared_ptr<RoutingData>;
using PtrWorker = std::unique_ptr<RoutingThread>;
using PtrWorker = RoutingThread *;
using Transects = QList<QList<CoordInfo_t>>;
using Variant = Transects;
enum class STATE { IDLE, ROUTING, SKIPP, REVERT_PATH, CHANGE_VARIANT };
public:
CircularSurvey(PlanMasterController *masterController, bool flyView,
const QString &kmlOrShpFile, QObject *parent);
~CircularSurvey();
RouteComplexItem(PlanMasterController *masterController, bool flyView,
const QString &kmlOrShpFile, QObject *parent);
~RouteComplexItem();
Q_PROPERTY(Fact *variant READ variant CONSTANT)
Q_PROPERTY(
......@@ -43,14 +42,18 @@ public:
Q_PROPERTY(
routing::GeneratorBase *generator READ generator NOTIFY generatorChanged)
Q_PROPERTY(int generatorIndex READ generatorIndex NOTIFY generatorChanged)
Q_PROPERTY(bool editing READ editing NOTIFY editingChanged)
Q_PROPERTY(AreaData *areaData READ areaData NOTIFY areaDataChanged)
Q_INVOKABLE void revert_path(void);
Q_INVOKABLE void revertPath(void);
// Property getters
const AreaData &planData() const;
const AreaData *areaData() const;
AreaData *areaData();
Fact *variant();
QStringList variantNames() const;
bool calculating() const;
bool editing() const;
// Overrides
virtual bool load(const QJsonObject &complexObject, int sequenceNumber,
......@@ -67,8 +70,7 @@ public:
virtual QString patternName(void) const override;
// Generator
bool registerGenerator(const QString &name,
std::shared_ptr<routing::GeneratorBase> g);
bool registerGenerator(const QString &name, routing::GeneratorBase *g);
bool unregisterGenerator(const QString &name);
bool unregisterGenerator(int index);
Q_INVOKABLE bool switchToGenerator(const QString &name);
......@@ -77,6 +79,22 @@ public:
routing::GeneratorBase *generator();
int generatorIndex();
// Editing.
//!
//! \brief editingStart Starts area data editing.
//!
//! Starts area data editing. Transects will not be updated bewteen a call
//! sequence of editingStart() and editingStop().
//!
void editingStart();
//!
//! \brief editingStop Stops area editing.
//!
//! Stops area editing. Will reset area data to the state before
//! editingStart() if it is invalid. Triggers a transect update.
//!
void editingStop();
static const char *settingsGroup;
static const char *variantName;
static const char *jsonComplexItemTypeValue;
......@@ -87,6 +105,8 @@ signals:
void variantNamesChanged();
void generatorNameListChanged();
void generatorChanged();
void editingChanged();
void areaDataChanged();
private slots:
// Overrides from TransectStyleComplexItem
......@@ -101,20 +121,25 @@ private slots:
void _reverseWorker();
private:
bool _switchToGenerator(const PtrGenerator &newG);
bool _setGenerator(PtrGenerator newG);
void _setState(STATE state);
bool _calculating(STATE state) const;
void _setEditing(bool editing);
void _setAreaData(PtrAreaData data);
// State.
STATE _state;
// center of the circular lanes, e.g. base station
// Facts
QMap<QString, FactMetaData *> _metaDataMap;
SettingsFact _variant;
QStringList _variantNames;
// Area data
AreaData _areaData;
PtrAreaData _areaData;
PtrAreaData _editorData;
PtrAreaData _currentData;
bool _editing;
// Generators
QList<PtrGenerator> _generatorList;
......
......@@ -4,7 +4,7 @@
#include <QSharedPointer>
#include <QThread>
#include "snake.h"
#include "geometry/snake.h"
#include <atomic>
#include <condition_variable>
#include <functional>
......
#include "GeoArea.h"
#include <QDebug>
const char *GeoArea::wimaAreaName = "GeoArea";
const char *GeoArea::areaTypeName = "AreaType";
const char *GeoArea::settingsGroup = "GeoArea";
// Constructors
GeoArea::GeoArea(QObject *parent) : QGCMapPolygon(parent) { init(); }
GeoArea::GeoArea(const GeoArea &other, QObject *parent)
: QGCMapPolygon(other, parent) {
init();
}
GeoArea &GeoArea::operator=(const GeoArea &other) {
QGCMapPolygon::operator=(other);
return *this;
}
void GeoArea::saveToJson(QJsonObject &json) {
this->QGCMapPolygon::saveToJson(json);
}
bool GeoArea::loadFromJson(const QJsonObject &json, QString &errorString) {
if (!this->QGCMapPolygon::loadFromJson(json, false /*no poly required*/,
errorString)) {
qWarning() << errorString;
return false;
}
return true;
}
bool GeoArea::isSimplePolygon() {
qWarning() << "WimaArea::isSimplePolygon: impl. missing.";
return false;
}
void GeoArea::init() { this->setObjectName(wimaAreaName); }
bool copyAreaList(const QmlObjectListModel &from, QmlObjectListModel &to,
QObject *parent) {
// Check if elements are valid.
for (int i = 0; i < from.count(); ++i) {
auto obj = from[i];
auto area = qobject_cast<const GeoArea *>(obj);
if (area == nullptr) {
return false;
}
}
// Clone elements.
for (int i = 0; i < from.count(); ++i) {
auto obj = from[i];
auto area = qobject_cast<const GeoArea *>(obj);
to.append(area->clone(parent));
}
return true;
}
#pragma once
#include <QObject>
#include "QGCMapPolygon.h"
class GeoArea : public QGCMapPolygon {
Q_OBJECT
public:
GeoArea(QObject *parent = nullptr);
GeoArea(const GeoArea &other, QObject *parent = nullptr);
GeoArea &operator=(const GeoArea &other);
Q_PROPERTY(QString mapVisualQML READ mapVisualQML CONSTANT)
Q_PROPERTY(QString editorQML READ editorQML CONSTANT)
virtual QString mapVisualQML(void) const = 0;
virtual QString editorQML(void) const = 0;
virtual void saveToJson(QJsonObject &jsonObject);
virtual bool loadFromJson(const QJsonObject &jsonObject,
QString &errorString);
virtual GeoArea *clone(QObject *parent = nullptr) const = 0;
bool isSimplePolygon();
// static Members
static const char *wimaAreaName;
static const char *areaTypeName;
static const char *settingsGroup;
private:
void init();
};
// Example usage:
// QmlObjecListModel list;
// .... add areas ....
// auto area = getArea<WimaMeasurementArea *>(list); // returns the first
// WimaMeasurementArea or nullptr
template <class AreaPtr, class QObjectList>
inline AreaPtr getGeoArea(QObjectList &list) {
static_assert(std::is_pointer<AreaPtr>::value,
"AreaPtr must be a pointer type.");
for (int i = 0; i < list.count(); ++i) {
auto obj = list[i];
auto area = qobject_cast<AreaPtr>(obj);
if (area != nullptr) {
return area;
}
}
return nullptr;
}
bool copyAreaList(const QmlObjectListModel &from, QmlObjectListModel &to,
QObject *parent);
......@@ -2,9 +2,10 @@
#include <QFutureWatcher>
#include <QObject>
#include <QSharedPointer>
#include <QTimer>
#include "WimaArea.h"
#include "GeoArea.h"
#include "SettingsFact.h"
......@@ -24,17 +25,16 @@ public:
std::size_t size() const;
};
class WimaMeasurementArea : public WimaArea {
class MeasurementArea : public GeoArea {
Q_OBJECT
enum class STATE { IDLE, DEFERED, UPDATEING, RESTARTING, STOP };
using DataPtr = QSharedPointer<TileData>;
public:
WimaMeasurementArea(QObject *parent = nullptr);
WimaMeasurementArea(const WimaMeasurementArea &other,
QObject *parent = nullptr);
WimaMeasurementArea &operator=(const WimaMeasurementArea &other);
~WimaMeasurementArea();
MeasurementArea(QObject *parent = nullptr);
MeasurementArea(const MeasurementArea &other, QObject *parent = nullptr);
MeasurementArea &operator=(const MeasurementArea &other);
~MeasurementArea();
Q_PROPERTY(Fact *tileHeight READ tileHeight CONSTANT)
Q_PROPERTY(Fact *tileWidth READ tileWidth CONSTANT)
......@@ -44,9 +44,12 @@ public:
Q_PROPERTY(int maxTiles READ maxTiles NOTIFY maxTilesChanged)
Q_PROPERTY(QVector<int> progress READ progressQml NOTIFY progressChanged)
// Overrides from WimaPolygon
QString mapVisualQML(void) const;
QString editorQML(void) const;
// Overrides from GeoArea
QString mapVisualQML(void) const override;
QString editorQML(void) const override;
MeasurementArea *clone(QObject *parent = nullptr) const;
void saveToJson(QJsonObject &json) override;
bool loadFromJson(const QJsonObject &json, QString &errorString) override;
// Property getters.
Fact *tileHeight();
......@@ -62,17 +65,13 @@ public:
int maxTiles() const;
bool ready() const;
// Member Methodes
void saveToJson(QJsonObject &json);
bool loadFromJson(const QJsonObject &json, QString &errorString);
// Static Variables
static const char *settingsGroup;
static const char *tileHeightName;
static const char *tileWidthName;
static const char *minTileAreaName;
static const char *showTilesName;
static const char *WimaMeasurementAreaName;
static const char *MeasurementAreaName;
signals:
void tilesChanged();
......@@ -109,7 +108,6 @@ private:
// Tile stuff.
// Tile stuff.
mutable QTimer _timer;
using DataPtr = std::shared_ptr<TileData>;
mutable STATE _state;
mutable TileData _tileData;
mutable QFutureWatcher<DataPtr> _watcher;
......
This diff is collapsed.
#pragma once
#include <QLineF>
#include <QPointF>
#include <QPolygonF>
#include <QtMath>
#include "GenericCircle.h"
#include "PolygonCalculus.h"
using Circle = GenericCircle<qreal, QPointF>;
namespace PlanimetryCalculus {
enum IntersectType {
InsideNoIntersection,
InsideTouching,
InsideIntersection,
OutsideIntersection,
OutsideTouching,
OutsideNoIntersection,
CirclesEqual, // Circle Circle intersection
Tangent,
Secant, // Circle Line Intersetion
EdgeCornerIntersection,
EdgeEdgeIntersection,
CornerCornerIntersection,
LinesParallel,
LinesEqual, // Line Line intersection
Interior, // Polygon contains
NoIntersection,
Error // general
};
typedef QVector<QPair<int, int>> NeighbourVector;
typedef QVector<QPointF> QPointFVector;
typedef QVector<IntersectType> IntersectVector;
void rotateReference(QPointF &point, double alpha);
void rotateReference(QPointFVector &points, double alpha);
void rotateReference(QLineF &line, double alpha);
// void rotateReference(QPolygonF &polygon, double alpha);
QPointF rotateReturn(QPointF point, double alpha);
QPointFVector rotateReturn(QPointFVector points, double alpha);
QLineF rotateReturn(QLineF line, double alpha);
// QPolygonF rotateReturn(QPolygonF &polygon, double alpha);
bool intersects(const Circle &circle1, const Circle &circle2);
bool intersects(const Circle &circle1, const Circle &circle2,
IntersectType &type);
bool intersects(const Circle &circle1, const Circle &circle2,
QPointFVector &intersectionPoints);
bool intersects(const Circle &circle1, const Circle &circle2,
QPointFVector &intersectionPoints, IntersectType &type);
bool intersects(const Circle &circle, const QLineF &line);
bool intersects(const Circle &circle, const QLineF &line, IntersectType &type);
bool intersects(const Circle &circle, const QLineF &line,
QPointFVector &intersectionPoints);
bool intersects(const Circle &circle, const QLineF &line,
QPointFVector &intersectionPoints, IntersectType &type);
bool intersects(const Circle &circle, const QPolygonF &polygon);
bool intersects(const Circle &circle, const QPolygonF &polygon,
QVector<QPointFVector> &intersectionPoints);
bool intersects(const Circle &circle, const QPolygonF &polygon,
QVector<QPointFVector> &intersectionPoints,
IntersectVector &typeList);
bool intersects(const Circle &circle, const QPolygonF &polygon,
QVector<QPointFVector> &intersectionPoints,
NeighbourVector &neighbourList);
bool intersects(const Circle &circle, const QPolygonF &polygon,
QVector<QPointFVector> &intersectionPoints,
NeighbourVector &neighbourList, IntersectVector &typeList);
bool intersects(const QLineF &line1, const QLineF &line2);
bool intersects(const QLineF &line1, const QLineF &line2,
QPointF &intersectionPt);
bool intersects(const QLineF &line1, const QLineF &line2,
QPointF &intersectionPt, IntersectType &type);
// bool intersectsFast(const QLineF &line1, const QLineF &line2, QPointF
// &intersectionPt, IntersectType &type);
bool intersects(const QPolygonF &polygon, const QLineF &line,
QPointFVector &intersectionList);
bool intersects(const QPolygonF &polygon, const QLineF &line,
QPointFVector &intersectionList, IntersectVector &typeList);
bool intersects(const QPolygonF &polygon, const QLineF &line,
QPointFVector &intersectionList,
NeighbourVector &neighbourList);
bool intersects(const QPolygonF &polygon, const QLineF &line,
QPointFVector &intersectionList, NeighbourVector &neighbourList,
IntersectVector &typeList);
bool intersectsFast(const QPolygonF &polygon, const QLineF &line);
bool contains(const QLineF &line, const QPointF &point);
bool contains(const QLineF &line, const QPointF &point, IntersectType &type);
bool contains(const QPolygonF &polygon, const QPointF &point);
bool contains(const QPolygonF &polygon, const QPointF &point,
IntersectType &type);
double distance(const QPointF &p1, const QPointF p2);
double norm(double x, double y);
double norm(const QPointF &p);
double angle(const QPointF &p1, const QPointF p2);
double angle(const QPointF &p1);
double angle(const QLineF &line);
double angleDegree(const QPointF &p1, const QPointF p2);
double truncateAngle(double angle);
double truncateAngleDegree(double angle);
/*!
* \fntemplate <typename T> int signum(T val)
* Returns the signum of a value \a val.
*
* \sa QPair, QVector
*/
template <typename T> int signum(T val) { return (T(0) < val) - (val < T(0)); }
} // namespace PlanimetryCalculus
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#pragma once
#include "Wima/Geometry/GenericPolygon.h"
#include "geometry/GenericPolygon.h"
using SnakeTileLocal = GenericPolygon<QPointF, std::vector>;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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