Commit 0877c5b7 authored by Valentin Platzgummer's avatar Valentin Platzgummer

clearup temp commit 2

parent 458ab210
...@@ -416,7 +416,6 @@ INCLUDEPATH += \ ...@@ -416,7 +416,6 @@ INCLUDEPATH += \
src/QtLocationPlugin \ src/QtLocationPlugin \
src/QtLocationPlugin/QMLControl \ src/QtLocationPlugin/QMLControl \
src/Settings \ src/Settings \
src/Wima/Snake \
src/Wima \ src/Wima \
src/Terrain \ src/Terrain \
src/Vehicle \ src/Vehicle \
...@@ -447,74 +446,58 @@ contains (DEFINES, QGC_ENABLE_PAIRING) { ...@@ -447,74 +446,58 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
HEADERS += \ HEADERS += \
src/QmlControls/QmlUnitsConversion.h \ src/QmlControls/QmlUnitsConversion.h \
src/Vehicle/VehicleEscStatusFactGroup.h \ src/Vehicle/VehicleEscStatusFactGroup.h \
src/Wima/CircularSurvey.h \ src/RouteMissionItem/RouteComplexItem.h \
src/Wima/GenericSingelton.h \ src/RouteMissionItem/GenericSingelton.h \
src/Wima/Geometry/GenericCircle.h \ src/RouteMissionItem/geometry/GenericCircle.h \
src/Wima/RoutingThread.h \ src/RouteMissionItem/RoutingThread.h \
src/Wima/Snake/CircularGenerator.h \ src/RouteMissionItem/CircularGenerator.h \
src/Wima/Snake/GeneratorBase.h \ src/RouteMissionItem/GeneratorBase.h \
src/Wima/Snake/LinearGenerator.h \ src/RouteMissionItem/LinearGenerator.h \
src/Wima/Snake/clipper/clipper.hpp \ src/RouteMissionItem/geometry/clipper/clipper.hpp \
src/Wima/Snake/mapbox/feature.hpp \ src/RouteMissionItem/geometry/mapbox/feature.hpp \
src/Wima/Snake/mapbox/geometry.hpp \ src/RouteMissionItem/geometry/mapbox/geometry.hpp \
src/Wima/Snake/mapbox/geometry/box.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/box.hpp \
src/Wima/Snake/mapbox/geometry/empty.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/empty.hpp \
src/Wima/Snake/mapbox/geometry/envelope.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/envelope.hpp \
src/Wima/Snake/mapbox/geometry/for_each_point.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/for_each_point.hpp \
src/Wima/Snake/mapbox/geometry/geometry.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/geometry.hpp \
src/Wima/Snake/mapbox/geometry/line_string.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/line_string.hpp \
src/Wima/Snake/mapbox/geometry/multi_line_string.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/multi_line_string.hpp \
src/Wima/Snake/mapbox/geometry/multi_point.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/multi_point.hpp \
src/Wima/Snake/mapbox/geometry/multi_polygon.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/multi_polygon.hpp \
src/Wima/Snake/mapbox/geometry/point.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/point.hpp \
src/Wima/Snake/mapbox/geometry/point_arithmetic.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/point_arithmetic.hpp \
src/Wima/Snake/mapbox/geometry/polygon.hpp \ src/RouteMissionItem/geometry/mapbox/geometry/polygon.hpp \
src/Wima/Snake/mapbox/geometry_io.hpp \ src/RouteMissionItem/geometry/mapbox/geometry_io.hpp \
src/Wima/Snake/mapbox/optional.hpp \ src/RouteMissionItem/geometry/mapbox/optional.hpp \
src/Wima/Snake/mapbox/polylabel.hpp \ src/RouteMissionItem/geometry/mapbox/polylabel.hpp \
src/Wima/Snake/mapbox/recursive_wrapper.hpp \ src/RouteMissionItem/geometry/mapbox/recursive_wrapper.hpp \
src/Wima/Snake/mapbox/variant.hpp \ src/RouteMissionItem/geometry/mapbox/variant.hpp \
src/Wima/Snake/mapbox/variant_io.hpp \ src/RouteMissionItem/geometry/mapbox/variant_io.hpp \
src/Wima/Snake/snake.h \ src/RouteMissionItem/geometry/snake.h \
src/Wima/Geometry/GenericPolygon.h \ src/RouteMissionItem/geometry/GenericPolygon.h \
src/Wima/Geometry/GenericPolygonArray.h \ src/RouteMissionItem/geometry/GenericPolygonArray.h \
src/Wima/Geometry/GeoPoint3D.h \ src/RouteMissionItem/geometry/GeoPoint3D.h \
src/Wima/Snake/NemoInterface.h \ src/RouteMissionItem/NemoInterface.h \
src/Wima/Snake/QNemoHeartbeat.h \ src/RouteMissionItem/nemo_interface/QNemoHeartbeat.h \
src/Wima/Snake/QNemoProgress.h \ src/RouteMissionItem/nemo_interface/QNemoProgress.h \
src/Wima/Snake/QNemoProgress.h \ src/RouteMissionItem/nemo_interface/QNemoProgress.h \
src/Wima/Snake/SnakeTile.h \ src/RouteMissionItem/nemo_interface/SnakeTile.h \
src/Wima/Snake/SnakeTileLocal.h \ src/RouteMissionItem/nemo_interface/SnakeTileLocal.h \
src/Wima/Snake/SnakeTiles.h \ src/RouteMissionItem/nemo_interface/SnakeTiles.h \
src/Wima/Snake/SnakeTilesLocal.h \ src/RouteMissionItem/nemo_interface/SnakeTilesLocal.h \
src/Wima/Utils.h \ src/RouteMissionItem/call_once.h \
src/Wima/WimaBridge.h \
src/Wima/WimaStateMachine.h \
src/Wima/call_once.h \
src/api/QGCCorePlugin.h \ src/api/QGCCorePlugin.h \
src/api/QGCOptions.h \ src/api/QGCOptions.h \
src/api/QGCSettings.h \ src/api/QGCSettings.h \
src/api/QmlComponentInfo.h \ src/api/QmlComponentInfo.h \
src/GPS/Drivers/src/base_station.h \ src/GPS/Drivers/src/base_station.h \
src/Wima/Geometry/WimaArea.h \ src/RouteMissionItem/geometry/WimaArea.h \
src/Wima/Geometry/WimaServiceArea.h \ src/RouteMissionItem/geometry/WimaServiceArea.h \
src/Wima/Geometry/WimaTrackerPolyline.h \ src/RouteMissionItem/geometry/WimaMeasurementArea.h \
src/Wima/WimaPlaner.h \ src/RouteMissionItem/geometry/PlanimetryCalculus.h \
src/Wima/Geometry/WimaMeasurementArea.h \ src/RouteMissionItem/geometry/PolygonCalculus.h \
src/Wima/Geometry/WimaCorridor.h \ src/RouteMissionItem/OptimisationTools.h \
src/Wima/Geometry/WimaAreaData.h \
src/Wima/Geometry/WimaServiceAreaData.h \
src/Wima/Geometry/WimaCorridorData.h \
src/Wima/Geometry/WimaMeasurementAreaData.h \
src/Wima/WimaPlanData.h \
src/Wima/Geometry/WimaJoinedArea.h \
src/Wima/Geometry/WimaJoinedAreaData.h \
src/Wima/Geometry/PlanimetryCalculus.h \
src/Wima/Geometry/PolygonCalculus.h \
src/Wima/OptimisationTools.h \
src/Wima/Geometry/GeoUtilities.h \
src/Wima/Geometry/TestPolygonCalculus.h \
src/Wima/Geometry/testplanimetrycalculus.h \
src/Settings/WimaSettings.h \ src/Settings/WimaSettings.h \
src/comm/ros_bridge/include/RosBridgeClient.h \ src/comm/ros_bridge/include/RosBridgeClient.h \
src/comm/ros_bridge/include/com_private.h \ src/comm/ros_bridge/include/com_private.h \
...@@ -540,25 +523,23 @@ contains (DEFINES, QGC_ENABLE_PAIRING) { ...@@ -540,25 +523,23 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
SOURCES += \ SOURCES += \
src/Vehicle/VehicleEscStatusFactGroup.cc \ src/Vehicle/VehicleEscStatusFactGroup.cc \
src/Wima/WimaStateMachine.cpp \ src/RouteMissionItem/AreaData.cc \
src/api/QGCCorePlugin.cc \ src/api/QGCCorePlugin.cc \
src/api/QGCOptions.cc \ src/api/QGCOptions.cc \
src/api/QGCSettings.cc \ src/api/QGCSettings.cc \
src/api/QmlComponentInfo.cc \ src/api/QmlComponentInfo.cc \
src/Wima/CircularSurvey.cc \ src/RouteMissionItem/RouteComplexItem.cc \
src/Wima/GenericSingelton.cpp \ src/RouteMissionItem/GenericSingelton.cpp \
src/Wima/RoutingThread.cpp \ src/RouteMissionItem/RoutingThread.cpp \
src/Wima/Snake/CircularGenerator.cpp \ src/RouteMissionItem/CircularGenerator.cpp \
src/Wima/Snake/GeneratorBase.cc \ src/RouteMissionItem/GeneratorBase.cc \
src/Wima/Snake/LinearGenerator.cpp \ src/RouteMissionItem/LinearGenerator.cpp \
src/Wima/Snake/clipper/clipper.cpp \ src/RouteMissionItem/geometry/clipper/clipper.cpp \
src/Wima/Snake/snake.cpp \ src/RouteMissionItem/geometry/snake.cpp \
src/Wima/Geometry/GeoPoint3D.cpp \ src/RouteMissionItem/geometry/GeoPoint3D.cpp \
src/Wima/Snake/NemoInterface.cpp \ src/RouteMissionItem/NemoInterface.cpp \
src/Wima/Snake/QNemoProgress.cc \ src/RouteMissionItem/nemo_interface/QNemoProgress.cc \
src/Wima/Snake/SnakeTile.cpp \ src/RouteMissionItem/nemo_interface/SnakeTile.cpp \
src/Wima/Utils.cpp \
src/Wima/WimaBridge.cc \
src/comm/ros_bridge/include/RosBridgeClient.cpp \ src/comm/ros_bridge/include/RosBridgeClient.cpp \
src/comm/ros_bridge/include/com_private.cpp \ src/comm/ros_bridge/include/com_private.cpp \
src/comm/ros_bridge/include/messages/geographic_msgs/geopoint.cpp \ src/comm/ros_bridge/include/messages/geographic_msgs/geopoint.cpp \
...@@ -573,25 +554,12 @@ SOURCES += \ ...@@ -573,25 +554,12 @@ SOURCES += \
src/comm/ros_bridge/include/server.cpp \ src/comm/ros_bridge/include/server.cpp \
src/comm/ros_bridge/include/topic_publisher.cpp \ src/comm/ros_bridge/include/topic_publisher.cpp \
src/comm/ros_bridge/include/topic_subscriber.cpp \ src/comm/ros_bridge/include/topic_subscriber.cpp \
src/Wima/Geometry/WimaArea.cc \ src/RouteMissionItem/geometry/WimaArea.cc \
src/Wima/Geometry/WimaServiceArea.cc \ src/RouteMissionItem/geometry/WimaServiceArea.cc \
src/Wima/Geometry/WimaTrackerPolyline.cc \ src/RouteMissionItem/geometry/WimaMeasurementArea.cc \
src/Wima/WimaPlaner.cc \ src/RouteMissionItem/geometry/PlanimetryCalculus.cc \
src/Wima/Geometry/WimaMeasurementArea.cc \ src/RouteMissionItem/OptimisationTools.cc \
src/Wima/Geometry/WimaCorridor.cc \ src/RouteMissionItem/geometry/PolygonCalculus.cc \
src/Wima/Geometry/WimaAreaData.cc \
src/Wima/Geometry/WimaServiceAreaData.cc \
src/Wima/Geometry/WimaCorridorData.cpp \
src/Wima/WimaPlanData.cc \
src/Wima/Geometry/WimaMeasurementAreaData.cc \
src/Wima/Geometry/WimaJoinedArea.cc \
src/Wima/Geometry/WimaJoinedAreaData.cc \
src/Wima/Geometry/PlanimetryCalculus.cc \
src/Wima/OptimisationTools.cc \
src/Wima/Geometry/GeoUtilities.cc \
src/Wima/Geometry/PolygonCalculus.cc \
src/Wima/Geometry/TestPolygonCalculus.cpp \
src/Wima/Geometry/testplanimetrycalculus.cpp \
src/Settings/WimaSettings.cc \ src/Settings/WimaSettings.cc \
src/comm/ros_bridge/src/ros_bridge.cpp src/comm/ros_bridge/src/ros_bridge.cpp
...@@ -1586,9 +1554,4 @@ contains (CONFIG, QGC_DISABLE_INSTALLER_SETUP) { ...@@ -1586,9 +1554,4 @@ contains (CONFIG, QGC_DISABLE_INSTALLER_SETUP) {
} }
DISTFILES += \ DISTFILES += \
src/Wima/Routing/json/CircularGenerator.SettingsGroup.json \
src/Wima/Snake/json/LinearGenerator.SettingsGroup.json \
src/Wima/json/CircularSurvey.SettingsGroup.json \
src/WimaView/WimaMeasurementAreaEditor.qml \
src/Settings/Wima.SettingsGroup.json \
src/QmlControls/QGroundControl/Specific/qmldir src/QmlControls/QGroundControl/Specific/qmldir
...@@ -289,7 +289,6 @@ ...@@ -289,7 +289,6 @@
<file alias="Wima/WimaServiceAreaEditor.qml">src/WimaView/WimaServiceAreaEditor.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/WimaServiceAreaMapVisual.qml">src/WimaView/WimaServiceAreaMapVisual.qml</file>
<file alias="Wima/WimaToolBar.qml">src/WimaView/WimaToolBar.qml</file> <file alias="Wima/WimaToolBar.qml">src/WimaView/WimaToolBar.qml</file>
<file alias="WimaView.qml">src/WimaView/WimaView.qml</file>
<file alias="SetupParameterEditor.qml">src/VehicleSetup/SetupParameterEditor.qml</file> <file alias="SetupParameterEditor.qml">src/VehicleSetup/SetupParameterEditor.qml</file>
<file alias="SetupView.qml">src/VehicleSetup/SetupView.qml</file> <file alias="SetupView.qml">src/VehicleSetup/SetupView.qml</file>
<file alias="SimpleItemEditor.qml">src/PlanView/SimpleItemEditor.qml</file> <file alias="SimpleItemEditor.qml">src/PlanView/SimpleItemEditor.qml</file>
......
...@@ -112,8 +112,6 @@ ...@@ -112,8 +112,6 @@
#include "Wima/Snake/CircularGenerator.h" #include "Wima/Snake/CircularGenerator.h"
#include "Wima/Snake/LinearGenerator.h" #include "Wima/Snake/LinearGenerator.h"
#include "Wima/Snake/NemoInterface.h" #include "Wima/Snake/NemoInterface.h"
#include "Wima/WimaController.h"
#include "Wima/WimaPlaner.h"
#if defined(QGC_ENABLE_PAIRING) #if defined(QGC_ENABLE_PAIRING)
#include "PairingManager.h" #include "PairingManager.h"
...@@ -596,8 +594,6 @@ void QGCApplication::_initCommon() ...@@ -596,8 +594,6 @@ void QGCApplication::_initCommon()
#endif #endif
// Wima // Wima
qmlRegisterType<WimaController>("Wima", 1, 0, "WimaController");
qmlRegisterType<WimaPlaner>("Wima", 1, 0, "WimaPlaner");
qmlRegisterType<NemoInterface>("Wima", 1, 0, "NemoInterface"); qmlRegisterType<NemoInterface>("Wima", 1, 0, "NemoInterface");
qmlRegisterInterface<routing::GeneratorBase>("GeneratorBase"); qmlRegisterInterface<routing::GeneratorBase>("GeneratorBase");
qmlRegisterType<routing::CircularGenerator>("Wima", 1, 0, qmlRegisterType<routing::CircularGenerator>("Wima", 1, 0,
......
...@@ -35,7 +35,7 @@ public: ...@@ -35,7 +35,7 @@ public:
Q_PROPERTY(double distanceBetween MEMBER _distanceBetween NOTIFY distanceBetweenChanged) Q_PROPERTY(double distanceBetween MEMBER _distanceBetween NOTIFY distanceBetweenChanged)
Q_PROPERTY(double finalDistanceBetween MEMBER _finalDistanceBetween NOTIFY finalDistanceBetweenChanged) Q_PROPERTY(double finalDistanceBetween MEMBER _finalDistanceBetween NOTIFY finalDistanceBetweenChanged)
Q_PROPERTY(double totalDistance MEMBER _totalDistance NOTIFY totalDistanceChanged) Q_PROPERTY(double totalDistance MEMBER _totalDistance NOTIFY totalDistanceChanged)
Q_PROPERTY(bool terrainCollision MEMBER _terrainCollision NOTIFY terrainCollisionChanged); Q_PROPERTY(bool terrainCollision MEMBER _terrainCollision NOTIFY terrainCollisionChanged)
QGeoCoordinate coordinate1 (void) const { return _coord1; } QGeoCoordinate coordinate1 (void) const { return _coord1; }
QGeoCoordinate coordinate2 (void) const { return _coord2; } QGeoCoordinate coordinate2 (void) const { return _coord2; }
......
[Dolphin]
Timestamp=2020,7,8,11,13,28
Version=4
ViewMode=1
This diff is collapsed.
#pragma once
#include <QFutureWatcher>
#include <QVector>
#include <memory>
#include "SettingsFact.h"
#include "TransectStyleComplexItem.h"
#include "Geometry/WimaJoinedAreaData.h"
#include "Geometry/WimaMeasurementAreaData.h"
#include "WimaPlanData.h"
class RoutingThread;
class RoutingData;
namespace routing {
class GeneratorBase;
}
class CircularSurvey : public TransectStyleComplexItem {
Q_OBJECT
using PtrGenerator = std::shared_ptr<routing::GeneratorBase>;
using PtrRoutingData = std::shared_ptr<RoutingData>;
using PtrWorker = std::unique_ptr<RoutingThread>;
using Transects = QList<QList<CoordInfo_t>>;
using Variant = Transects;
enum class STATE { IDLE, ROUTING, SKIPP, REVERSE, VARIANT_CHANGE };
public:
CircularSurvey(PlanMasterController *masterController, bool flyView,
const QString &kmlOrShpFile, QObject *parent);
~CircularSurvey();
Q_PROPERTY(Fact *variant READ variant CONSTANT)
Q_PROPERTY(
QStringList variantNames READ variantNames NOTIFY variantNamesChanged)
Q_PROPERTY(QStringList generatorNameList READ generatorNameList NOTIFY
generatorNameListChanged)
Q_PROPERTY(bool calculating READ calculating NOTIFY calculatingChanged)
Q_PROPERTY(
routing::GeneratorBase *generator READ generator NOTIFY generatorChanged)
Q_PROPERTY(int generatorIndex READ generatorIndex NOTIFY generatorChanged)
Q_INVOKABLE void reverse(void);
// Property setters
void setPlanData(const WimaPlanData &d);
// Property getters
const WimaPlanData &planData() const;
WimaPlanData &planData();
Fact *variant();
QStringList variantNames() const;
bool calculating() const;
// Overrides
virtual bool load(const QJsonObject &complexObject, int sequenceNumber,
QString &errorString) override final;
virtual QString mapVisualQML(void) const override final;
virtual void save(QJsonArray &planItems) override final;
virtual bool specifiesCoordinate(void) const override final;
virtual double timeBetweenShots(void) override final;
virtual QString commandDescription(void) const override final;
virtual QString commandName(void) const override final;
virtual QString abbreviation(void) const override final;
virtual ReadyForSaveState readyForSaveState(void) const override final;
virtual double additionalTimeDelay(void) const override final;
virtual QString patternName(void) const override;
// Generator
bool registerGenerator(const QString &name,
std::shared_ptr<routing::GeneratorBase> g);
bool unregisterGenerator(const QString &name);
bool unregisterGenerator(int index);
Q_INVOKABLE bool switchToGenerator(const QString &name);
Q_INVOKABLE bool switchToGenerator(int index);
QStringList generatorNameList();
routing::GeneratorBase *generator();
int generatorIndex();
static const char *settingsGroup;
static const char *variantName;
static const char *jsonComplexItemTypeValue;
static const QString name;
signals:
void calculatingChanged();
void variantNamesChanged();
void generatorNameListChanged();
void generatorChanged();
private slots:
// Overrides from TransectStyleComplexItem
virtual void _rebuildTransectsPhase1(void) override final;
virtual void _recalcCameraShots(void) override final;
// Worker functions.
void _setTransects(PtrRoutingData pRoute);
void _changeVariant();
bool _updateWorker();
void _changeVariantWorker();
void _reverseWorker();
private:
bool _switchToGenerator(const PtrGenerator &newG);
void _setState(STATE state);
bool _calculating(STATE state) const;
// State.
STATE _state;
// center of the circular lanes, e.g. base station
QMap<QString, FactMetaData *> _metaDataMap;
SettingsFact _variant;
QStringList _variantNames;
// Area data
std::shared_ptr<WimaPlanData> _pAreaData;
// Generators
QList<PtrGenerator> _generatorList;
QStringList _generatorNameList;
PtrGenerator _pGenerator;
// Routing.
QVector<Variant> _variantVector;
PtrWorker _pWorker;
};
#pragma once
#include "call_once.h"
#include <QScopedPointer>
#include <QtGlobal>
template <class T> class GenericSingelton {
private:
typedef T *(*CreateInstanceFunction)();
public:
static T *instance(CreateInstanceFunction create);
private:
static void init();
GenericSingelton();
~GenericSingelton();
Q_DISABLE_COPY(GenericSingelton)
static QBasicAtomicPointer<void> create;
static QBasicAtomicInt flag;
static QBasicAtomicPointer<void> tptr;
bool inited;
};
template <class T>
T *GenericSingelton<T>::instance(CreateInstanceFunction create) {
GenericSingelton::create.store(reinterpret_cast<void *>(create));
qCallOnce(init, flag);
return (T *)tptr.load();
}
template <class T> void GenericSingelton<T>::init() {
static GenericSingelton singleton;
if (singleton.inited) {
CreateInstanceFunction createFunction =
(CreateInstanceFunction)GenericSingelton::create.load();
tptr.store(createFunction());
}
}
template <class T> GenericSingelton<T>::GenericSingelton() { inited = true; }
template <class T> GenericSingelton<T>::~GenericSingelton() {
T *createdTptr = (T *)tptr.fetchAndStoreOrdered(nullptr);
if (createdTptr) {
delete createdTptr;
}
create.store(nullptr);
}
template <class T>
QBasicAtomicPointer<void>
GenericSingelton<T>::create = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
template <class T>
QBasicAtomicInt GenericSingelton<T>::flag =
Q_BASIC_ATOMIC_INITIALIZER(CallOnce::CO_Request);
template <class T>
QBasicAtomicPointer<void>
GenericSingelton<T>::tptr = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
#pragma once
#include <QObject>
#include <QPointF>
#include <cmath>
#include "boost/units/systems/angle/degrees.hpp"
#include "boost/units/systems/si.hpp"
template <int k, class Point> auto get(const Point &p);
namespace bu = boost::units;
namespace qty {
using Length = bu::quantity<bu::si::length>;
using Angle = bu::quantity<bu::si::plane_angle>;
using Degree = bu::quantity<bu::degree::plane_angle>;
using Radian = bu::quantity<bu::si::plane_angle>;
} // namespace qty
template <class NumberType, class Point> class GenericCircle {
public:
GenericCircle();
GenericCircle(NumberType rad, Point ori);
// Property setters
void setRadius(NumberType rad);
void setOrigin(const Point &ori);
// Property getters
NumberType radius() const;
const Point &origin() const;
Point &origin();
private:
NumberType _r;
Point _origin;
};
// Free functions.
template <class Circle, class Container>
void approximate(Circle &circ, long n, qty::Angle alpha1, qty::Angle alpha2,
Container &c);
template <class Circle, class Container>
void approximate(Circle &circ, long n, Container &c);
// Impl.
template <class NumberType, class Point>
GenericCircle<NumberType, Point>::GenericCircle() : _r(0), _origin(0, 0) {}
template <class NumberType, class Point>
GenericCircle<NumberType, Point>::GenericCircle(NumberType rad, Point ori)
: _r(rad), _origin(ori) {}
/*!
* Returns a polygon with \a n corners which approximates the
* circle.
*
* \sa Point
*/
template <class NumberType, class Point>
void GenericCircle<NumberType, Point>::setRadius(NumberType rad) {
if (rad >= 0) {
this->_r = rad;
}
}
template <class NumberType, class Point>
void GenericCircle<NumberType, Point>::setOrigin(const Point &ori) {
this->_origin = ori;
}
template <class NumberType, class Point>
NumberType GenericCircle<NumberType, Point>::radius() const {
return this->_r;
}
template <class NumberType, class Point>
const Point &GenericCircle<NumberType, Point>::origin() const {
return this->_origin;
}
template <class NumberType, class Point>
Point &GenericCircle<NumberType, Point>::origin() {
return this->_origin;
}
template <class Circle, class Container>
void approximate(Circle &circ, long n, qty::Angle alpha1, qty::Angle alpha2,
Container &c) {
auto clipp = [](double angle) {
while (angle < 0) {
angle += 2 * M_PI;
}
while (angle > 2 * M_PI) {
angle -= 2 * M_PI;
}
return angle;
};
double a1 = clipp(alpha1.value());
double a2 = clipp(alpha2.value());
double angleDisc = 0;
if (n > 0) {
angleDisc = (a2 - a1) / (n - 1);
} else {
angleDisc = (a2 - a1) / (n + 1);
n = n * (-1);
}
double a = a1;
using Point =
std::remove_cv_t<std::remove_reference_t<decltype(circ.origin())>>;
auto x0 = get<0>(circ.origin());
auto y0 = get<1>(circ.origin());
auto r = circ.radius();
using NumberType = std::remove_cv_t<std::remove_reference_t<decltype(x0)>>;
while (n--) {
auto x = NumberType(x0 + r * std::cos(a));
auto y = NumberType(y0 + r * std::sin(a));
c.push_back(Point(x, y));
a += angleDisc;
}
}
template <class Circle, class Container>
void approximate(Circle &circ, long n, Container &c) {
using namespace bu;
double angleDisc = 0;
if (n > 0) {
angleDisc = 2 * M_PI / (n - 1);
} else {
angleDisc = 2 * M_PI / (n + 1);
n = n * (-1);
}
double a = 0;
using Point =
std::remove_cv_t<std::remove_reference_t<decltype(circ.origin())>>;
auto x0 = get<0>(circ.origin());
auto y0 = get<1>(circ.origin());
auto r = circ.radius();
using NumberType = std::remove_cv_t<std::remove_reference_t<decltype(x0)>>;
while (n--) {
auto x = NumberType(x0 + r * std::cos(a));
auto y = NumberType(y0 + r * std::sin(a));
c.push_back(Point(x, y));
a += angleDisc;
}
}
#pragma once
#include <QPolygonF>
#include <QPointF>
#include "ros_bridge/include/messages/geometry_msgs/polygon_stamped.h"
template <class PointType = QPointF, template <class, class...> class ContainerType = QVector>
class GenericPolygon{ //
typedef ros_bridge::messages::geometry_msgs::polygon::GenericPolygon<PointType, ContainerType> Polygon;
public:
GenericPolygon(){}
GenericPolygon(const GenericPolygon &other) : _polygon(other._polygon){}
GenericPolygon& operator=(const GenericPolygon& other) {
this->_polygon = other._polygon;
return *this;
}
const Polygon &polygon() const {return _polygon;}
Polygon &polygon() {return _polygon;}
const ContainerType<PointType> &path() const {return _polygon.points();}
ContainerType<PointType> &path() {return _polygon.points();}
private:
Polygon _polygon;
};
#pragma once
#include "QmlObjectListModel.h"
#include <QVector>
#include <QString>
template <class PolygonType, template <class, class...> class ContainerType = QVector>
class GenericPolygonArray
{
public:
GenericPolygonArray() {}
GenericPolygonArray(const GenericPolygonArray &other) :
_polygons(other._polygons), _dirty(true)
{}
~GenericPolygonArray(){
_objs.clearAndDeleteContents();
}
class QmlObjectListModel *QmlObjectListModel(){
if (_dirty)
_updateObjects();
_dirty = false;
return &_objs;
}
const ContainerType<PolygonType> &polygons() const {
return _polygons;
}
ContainerType<PolygonType> &polygons(){
_dirty = true;
return _polygons;
}
GenericPolygonArray &operator =(const GenericPolygonArray &other){
this->_polygons = other._polygons;
this->_dirty = true;
return *this;
}
private:
void _updateObjects(void){
_objs.clearAndDeleteContents();
for (long i=0; i<_polygons.size(); ++i){
_objs.append(new PolygonType(_polygons[i]));
}
}
ContainerType<PolygonType> _polygons;
class QmlObjectListModel _objs;
bool _dirty;
};
#include "GeoPoint3D.h"
GeoPoint3D::GeoPoint3D(QObject *parent)
: QObject(parent), ROSGeoPoint() {}
GeoPoint3D::GeoPoint3D(double latitude, double longitude, double altitude, QObject *parent)
: QObject(parent), ROSGeoPoint(latitude, longitude, altitude)
{}
GeoPoint3D::GeoPoint3D(const GeoPoint3D &p, QObject *parent)
: QObject(parent), ROSGeoPoint(p.latitude(), p.longitude(), p.altitude())
{}
GeoPoint3D::GeoPoint3D(const ROSGeoPoint &p, QObject *parent)
: QObject(parent), ROSGeoPoint(p.latitude(), p.longitude(), p.altitude())
{}
GeoPoint3D::GeoPoint3D(const QGeoCoordinate &p, QObject *parent)
: QObject(parent), ROSGeoPoint(p.latitude(), p.longitude(), p.altitude())
{}
GeoPoint3D &GeoPoint3D::operator=(const GeoPoint3D &p)
{
this->setLatitude(p.latitude());
this->setLongitude(p.longitude());
this->setAltitude(p.altitude());
return *this;
}
GeoPoint3D &GeoPoint3D::operator=(const QGeoCoordinate &p)
{
this->setLatitude(p.latitude());
this->setLongitude(p.longitude());
this->setAltitude(p.altitude());
return *this;
}
#pragma once
#include <QGeoCoordinate>
#include <QObject>
#include "ros_bridge/include/messages/geographic_msgs/geopoint.h"
typedef ros_bridge::messages::geographic_msgs::geo_point::GeoPoint ROSGeoPoint;
class GeoPoint3D : public QObject, public ROSGeoPoint
{
Q_OBJECT
public:
GeoPoint3D(QObject *parent = nullptr);
GeoPoint3D(double latitude,
double longitude,
double altitude,
QObject *parent = nullptr);
GeoPoint3D(const GeoPoint3D& p,
QObject *parent = nullptr);
GeoPoint3D(const ROSGeoPoint& p,
QObject *parent = nullptr);
GeoPoint3D(const QGeoCoordinate& p,
QObject *parent = nullptr);
GeoPoint3D &operator=(const GeoPoint3D&p);
GeoPoint3D &operator=(const QGeoCoordinate&p);
};
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.
#pragma once
#include <QPointF>
#include <QPolygonF>
#include <QVector3D>
namespace PolygonCalculus {
enum JoinPolygonError { NotSimplePolygon, PolygonJoined, Disjoint, PathSizeLow, Error};
typedef QList<QVector3D> QVector3DList;
typedef QList<QPointF> QPointFList;
typedef QVector<QPointF> QPointFVector;
int closestVertexIndex (const QPolygonF &polygon, const QPointF &coordinate);
QPointF closestVertex (const QPolygonF &polygon, const QPointF &coordinate);
int nextVertexIndex (int pathsize, int index);
int previousVertexIndex (int pathsize, int index);
JoinPolygonError join (QPolygonF polygon1, QPolygonF polygon2, QPolygonF &joinedPolygon);
bool isSimplePolygon (const QPolygonF &polygon);
bool hasClockwiseWinding (const QPolygonF &path);
void reversePath (QPolygonF &path);
void reversePath (QPointFList &path);
void reversePath (QPointFVector &path);
void offsetPolygon (QPolygonF &polygon, double offset);
// returns true if the line c1-c2 is fully inside the polygon
bool containsPath (QPolygonF polygon, const QPointF &c1, const QPointF &c2);
// same as containsPath(), but works only if c1 and c2 are inside the polygon!
bool containsPathFast (QPolygonF polygon, const QPointF &c1, const QPointF &c2);
void decomposeToConvex (const QPolygonF &polygon, QList<QPolygonF> &convexPolygons);
bool shortestPath (const QPolygonF &polygon, const QPointF &startVertex, const QPointF &endVertex, QVector<QPointF> &shortestPath);
QPolygonF toQPolygonF(const QVector3DList &polygon);
QPolygonF toQPolygonF(const QPointFList &polygon);
QLineF toQLineF(const QVector3DList &line);
QPointFList toQPointFList(const QVector3DList &list);
QPointFList toQPointFList(const QPolygonF &list);
QVector3DList toQVector3DList(const QPointFList &listF);
QVector3DList toQVector3DList(const QPolygonF &listF);
}
#include "TestPolygonCalculus.h"
#include "PolygonCalculus.h"
#include <QPolygonF>
#include <QPointF>
namespace TestPolygonCalculus {
void test()
{
using namespace PolygonCalculus;
QPolygonF polygon;
polygon << QPointF(0, 0) << QPointF(1, 0) << QPointF(1, 1) << QPointF(0, 1);
bool retVal = containsPath(polygon, QPointF(0.1, 0.1), QPointF(0.2, 0.1));
qDebug("true %i", retVal);
retVal = containsPath(polygon, QPointF(0.2, 0.1), QPointF(0.2, 0.1));
qDebug("true %i", retVal);
retVal = containsPath(polygon, QPointF(1, 0.1), QPointF(0.2, 0.1));
qDebug("true %i", retVal);
retVal = containsPath(polygon, QPointF(0.1, 0.1), QPointF(1, 0.1));
qDebug("true %i", retVal);
retVal = containsPath(polygon, QPointF(2, 0.1), QPointF(0.2, 0.1));
qDebug("false %i", retVal);
retVal = containsPath(polygon, QPointF(-2, 0.1), QPointF(0.2, 0.1));
qDebug("false %i", retVal);
polygon << QPointF(0.5, 0.6) << QPointF(0.5, 0.4);
retVal = containsPath(polygon, QPointF(0.2, 0.1), QPointF(0.2, 0.9));
qDebug("false %i", retVal);
retVal = containsPath(polygon, QPointF(0.1, 0.05), QPointF(0.51, 0.6));
qDebug("false %i", retVal);
}
}
#ifndef TESTPOLYGONCALCULUS_H
#define TESTPOLYGONCALCULUS_H
namespace TestPolygonCalculus {
void test();
}
#endif // TESTPOLYGONCALCULUS_H
This diff is collapsed.
#pragma once
#include "QGCGeo.h"
#include "QGCMapPolygon.h"
#include "QGCMapPolyline.h"
#include "Vehicle.h"
#include "qobject.h"
#include <QLineF>
#include <QPair>
#include <QPointF>
#include "GeoUtilities.h"
#include "PlanimetryCalculus.h"
#include "PolygonCalculus.h"
class WimaArea : public QGCMapPolygon // abstract base class for all WimaAreas
{
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;
signals:
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);
private slots:
void recalcPolygons(void);
void updatePolygonConnections(QVariant value);
void recalcInteractivity(void);
private:
void init();
double _maxAltitude;
QMap<QString, FactMetaData *> _metaDataMap;
SettingsFact _borderPolygonOffset;
SettingsFact _showBorderPolygon;
QGCMapPolygon _borderPolygon;
bool _wimaAreaInteractive;
};
#include "WimaAreaData.h"
WimaAreaData::WimaAreaData(QObject *parent) : QObject(parent) {}
WimaAreaData::WimaAreaData(const WimaAreaData &other, QObject *parent)
: QObject(parent), _path(other._path), _list(other._list),
_center(other._center) {}
WimaAreaData::WimaAreaData(const WimaArea &otherData, QObject *parent)
: QObject(parent), _center(otherData.center()) {
_setPathImpl(otherData.path());
}
bool WimaAreaData::operator==(const WimaAreaData &data) const {
return this->_path == data._path && this->_center == data._center;
}
bool WimaAreaData::operator!=(const WimaAreaData &data) const {
return !this->operator==(data);
}
QVariantList WimaAreaData::path() const { return _path; }
QGeoCoordinate WimaAreaData::center() const { return _center; }
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 (this->coordinateList().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));
emit pathChanged();
}
void WimaAreaData::push_back(const QGeoCoordinate &c) { append(c); }
void WimaAreaData::clear() {
if (_list.size() > 0 || _path.size() > 0) {
_list.clear();
_path.clear();
emit pathChanged();
}
}
void WimaAreaData::setPath(const QVariantList &coordinateList) {
if (_path != coordinateList) {
_setPathImpl(coordinateList);
emit pathChanged();
}
}
void WimaAreaData::setCenter(const QGeoCoordinate &center) {
if (_center != center) {
_center = center;
emit centerChanged();
}
}
WimaAreaData &WimaAreaData::operator=(const WimaAreaData &otherData) {
setPath(otherData._list);
setCenter(otherData._center);
return *this;
}
WimaAreaData &WimaAreaData::operator=(const WimaArea &otherData) {
setPath(otherData.path());
setCenter(otherData.center());
return *this;
}
void WimaAreaData::_setPathImpl(const QList<QGeoCoordinate> &coordinateList) {
_list = coordinateList;
_path.clear();
// copy all coordinates to _path
for (const auto &vertex : coordinateList) {
_path.append(QVariant::fromValue(vertex));
}
}
void WimaAreaData::_setPathImpl(const QVariantList &coordinateList) {
_path = coordinateList;
_list.clear();
for (const auto &variant : coordinateList) {
_list.push_back(variant.value<QGeoCoordinate>());
}
}
/*!
* \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.
*/
void WimaAreaData::setPath(const QList<QGeoCoordinate> &coordinateList) {
if (_list != coordinateList) {
_setPathImpl(coordinateList);
emit pathChanged();
}
}
bool operator==(const WimaAreaData &m1, const WimaArea &m2) {
return m1.path() == m2.path() && m1.center() == m2.center();
}
bool operator!=(const WimaAreaData &m1, const WimaArea &m2) {
return !operator==(m1, m2);
}
bool operator==(const WimaArea &m1, const WimaAreaData &m2) { return m2 == m1; }
bool operator!=(const WimaArea &m1, const WimaAreaData &m2) {
return !operator==(m2, m1);
}
/*!
* \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
*
* \sa WimaArea
*/
#pragma once
#include <QObject>
#include "QGeoCoordinate"
#include "WimaArea.h"
class WimaAreaData
: public QObject // Abstract class for all WimaAreaData derived objects
{
Q_OBJECT
public:
WimaAreaData(QObject *parent = nullptr);
Q_PROPERTY(const QVariantList path READ path NOTIFY pathChanged)
Q_PROPERTY(QString type READ type CONSTANT)
Q_PROPERTY(QString mapVisualQML READ mapVisualQML CONSTANT)
bool operator==(const WimaAreaData &data) const;
bool operator!=(const WimaAreaData &data) const;
virtual QString mapVisualQML(void) const = 0;
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 pathChanged();
void centerChanged();
public slots:
void setPath(const QList<QGeoCoordinate> &coordinateList);
void setPath(const QVariantList &coordinateList);
void setCenter(const QGeoCoordinate &center);
protected:
WimaAreaData(const WimaAreaData &otherData, QObject *parent);
WimaAreaData(const WimaArea &otherData, QObject *parent);
WimaAreaData &operator=(const WimaAreaData &otherData);
WimaAreaData &operator=(const WimaArea &otherData);
private:
void _setPathImpl(const QList<QGeoCoordinate> &coordinateList);
void _setPathImpl(const QVariantList &coordinateList);
// Member Variables
mutable QVariantList _path;
QList<QGeoCoordinate> _list;
QGeoCoordinate _center;
};
bool operator==(const WimaAreaData &m1, const WimaArea &m2);
bool operator!=(const WimaAreaData &m1, const WimaArea &m2);
bool operator==(const WimaArea &m1, const WimaAreaData &m2);
bool operator!=(const WimaArea &m1, const WimaAreaData &m2);
#include "WimaCorridor.h"
const char* WimaCorridor::WimaCorridorName = "Corridor";
WimaCorridor::WimaCorridor(QObject *parent)
: WimaArea (parent)
{
init();
}
WimaCorridor::WimaCorridor(const WimaCorridor &other, QObject *parent)
: WimaArea (other, parent)
{
init();
}
/*!
* \overload operator=()
*
* Calls the inherited operator WimaArea::operator=().
*/
WimaCorridor &WimaCorridor::operator=(const WimaCorridor &other)
{
WimaArea::operator=(other);
return *this;
}
void WimaCorridor::saveToJson(QJsonObject &json)
{
this->WimaArea::saveToJson(json);
json[areaTypeName] = WimaCorridorName;
}
bool WimaCorridor::loadFromJson(const QJsonObject &json, QString &errorString)
{
if ( this->WimaArea::loadFromJson(json, errorString)) {
bool retVal = true;
// code for loading here
return retVal;
} else {
qWarning() << errorString;
return false;
}
}
void WimaCorridor::init()
{
this->setObjectName(WimaCorridorName);
}
/*!
\class WimaCorridor
\brief Corridor (derived from \c WimaArea) connecting the \c WimaMeasurementArea and the \c WimaServiceArea.
*/
#pragma once
#include "WimaArea.h"
#include <QObject>
class WimaCorridor : public WimaArea {
Q_OBJECT
public:
WimaCorridor(QObject *parent = nullptr);
WimaCorridor(const WimaCorridor &other, QObject *parent = nullptr);
WimaCorridor &operator=(const WimaCorridor &other);
// Overrides from WimaPolygon
QString mapVisualQML(void) const { return "WimaCorridorMapVisual.qml"; }
QString editorQML(void) const { return "WimaCorridorEditor.qml"; }
// Methodes
void saveToJson(QJsonObject &json);
bool loadFromJson(const QJsonObject &json, QString &errorString);
// static Members
static const char *WimaCorridorName;
signals:
public slots:
private:
void init();
};
This diff is collapsed.
#pragma once
#include <QFutureWatcher>
#include <QObject>
#include <QTimer>
#include "WimaArea.h"
#include "SettingsFact.h"
class TileData : public QObject {
public:
QmlObjectListModel tiles;
QVariantList tileCenterPoints;
TileData();
~TileData();
TileData &operator=(const TileData &other);
bool operator==(const TileData &other) const;
bool operator!=(const TileData &other) const;
void clear();
std::size_t size() const;
};
class WimaMeasurementArea : public WimaArea {
Q_OBJECT
enum class STATE { IDLE, DEFERED, UPDATEING, RESTARTING, STOP };
public:
WimaMeasurementArea(QObject *parent = nullptr);
WimaMeasurementArea(const WimaMeasurementArea &other,
QObject *parent = nullptr);
WimaMeasurementArea &operator=(const WimaMeasurementArea &other);
~WimaMeasurementArea();
Q_PROPERTY(Fact *tileHeight READ tileHeight CONSTANT)
Q_PROPERTY(Fact *tileWidth READ tileWidth CONSTANT)
Q_PROPERTY(Fact *minTileArea READ minTileArea CONSTANT)
Q_PROPERTY(Fact *showTiles READ showTiles CONSTANT)
Q_PROPERTY(QmlObjectListModel *tiles READ tiles NOTIFY tilesChanged)
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;
// Property getters.
Fact *tileHeight();
Fact *tileWidth();
Fact *minTileArea();
Fact *showTiles();
QmlObjectListModel *tiles();
const QVector<int> &progress() const;
QVector<int> progressQml() const;
const QmlObjectListModel *tiles() const;
const QVariantList &tileCenterPoints() const; // List of QGeoCoordinate
const TileData &tileData() const;
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;
signals:
void tilesChanged();
void maxTilesChanged();
void progressChanged();
void progressAccepted();
void progressNotAccepted();
void readyChanged();
public slots:
bool setProgress(const QVector<int> &p);
private slots:
void doUpdate();
void deferUpdate();
void storeTiles();
void disableUpdate();
void enableUpdate();
private:
// Member Methodes
void init();
void setState(STATE s);
// Members
QMap<QString, FactMetaData *> _metaDataMap;
SettingsFact _tileHeight;
SettingsFact _tileWidth;
SettingsFact _minTileAreaPercent; // 0..100
SettingsFact _showTiles;
QVector<int> _progress;
// Tile stuff.
// Tile stuff.
mutable QTimer _timer;
using DataPtr = std::shared_ptr<TileData>;
mutable STATE _state;
mutable TileData _tileData;
mutable QFutureWatcher<DataPtr> _watcher;
};
#include "WimaMeasurementAreaData.h"
#include "SnakeTile.h"
const char *WimaMeasurementAreaData::typeString = "WimaMeasurementAreaData";
WimaMeasurementAreaData::WimaMeasurementAreaData(QObject *parent)
: WimaAreaData(parent) {}
WimaMeasurementAreaData::WimaMeasurementAreaData(
const WimaMeasurementAreaData &other, QObject *parent)
: WimaAreaData(parent) {
*this = other;
}
WimaMeasurementAreaData::WimaMeasurementAreaData(
const WimaMeasurementArea &other, QObject *parent)
: WimaAreaData(parent) {
*this = other;
}
bool WimaMeasurementAreaData::
operator==(const WimaMeasurementAreaData &other) const {
return this->WimaAreaData::operator==(other) &&
this->_tileData == other.tileData() &&
this->_progress == other.progress() &&
this->center() == other.center();
}
bool WimaMeasurementAreaData::
operator!=(const WimaMeasurementAreaData &other) const {
return !(*this == other);
}
void WimaMeasurementAreaData::setTileData(const TileData &d) {
if (this->_tileData != d) {
this->_tileData = d;
this->_progress.fill(0, d.size());
emit progressChanged();
emit tileDataChanged();
}
}
void WimaMeasurementAreaData::setProgress(const QVector<int> &d) {
if (this->_progress != d && d.size() == this->_tileData.tiles.count()) {
this->_progress = d;
emit progressChanged();
}
}
/*!
* \overload operator=();
*
* Assigns \a other to the invoking object.
*/
WimaMeasurementAreaData &WimaMeasurementAreaData::
operator=(const WimaMeasurementAreaData &other) {
WimaAreaData::operator=(other);
setTileData(other._tileData);
setProgress(other._progress);
return *this;
}
/*!
* \overload operator=();
*
* Assigns \a other to the invoking object.
*/
WimaMeasurementAreaData &WimaMeasurementAreaData::
operator=(const WimaMeasurementArea &other) {
WimaAreaData::operator=(other);
if (other.ready()) {
setTileData(other.tileData());
setProgress(other.progress());
} else {
qWarning() << "WimaMeasurementAreaData::operator=(): WimaMeasurementArea "
"not ready.";
}
return *this;
}
QString WimaMeasurementAreaData::mapVisualQML() const {
return QStringLiteral("WimaMeasurementAreaDataVisual.qml");
}
QString WimaMeasurementAreaData::type() const { return this->typeString; }
QmlObjectListModel *WimaMeasurementAreaData::tiles() {
return &this->_tileData.tiles;
}
const QmlObjectListModel *WimaMeasurementAreaData::tiles() const {
return &this->_tileData.tiles;
}
const QVariantList &WimaMeasurementAreaData::tileCenterPoints() const {
return this->_tileData.tileCenterPoints;
}
QVariantList &WimaMeasurementAreaData::tileCenterPoints() {
return this->_tileData.tileCenterPoints;
}
const TileData &WimaMeasurementAreaData::tileData() const {
return this->_tileData;
}
TileData &WimaMeasurementAreaData::tileData() { return this->_tileData; }
const QVector<int> &WimaMeasurementAreaData::progress() const {
return this->_progress;
}
QVector<int> &WimaMeasurementAreaData::progress() { return this->_progress; }
bool operator==(const WimaMeasurementAreaData &m1,
const WimaMeasurementArea &m2) {
return operator==(*static_cast<const WimaAreaData *>(&m1),
*static_cast<const WimaArea *>(&m2)) &&
m1.tileData() == m2.tileData() && m1.progress() == m2.progress();
}
bool operator!=(const WimaMeasurementAreaData &m1,
const WimaMeasurementArea &m2) {
return !(m1 == m2);
}
bool operator==(const WimaMeasurementArea &m1,
const WimaMeasurementAreaData &m2) {
return m2 == m1;
}
bool operator!=(const WimaMeasurementArea &m1,
const WimaMeasurementAreaData &m2) {
return m2 != m1;
}
#pragma once
#include <QGeoCoordinate>
#include <QObject>
#include "WimaAreaData.h"
#include "WimaMeasurementArea.h"
class WimaMeasurementAreaData : public WimaAreaData {
Q_OBJECT
public:
WimaMeasurementAreaData(QObject *parent = nullptr);
WimaMeasurementAreaData(const WimaMeasurementAreaData &other,
QObject *parent = nullptr);
WimaMeasurementAreaData(const WimaMeasurementArea &other,
QObject *parent = nullptr);
WimaMeasurementAreaData &operator=(const WimaMeasurementAreaData &other);
WimaMeasurementAreaData &operator=(const WimaMeasurementArea &other);
Q_PROPERTY(QmlObjectListModel *tiles READ tiles NOTIFY tileDataChanged)
Q_PROPERTY(QVector<int> progress READ progress NOTIFY progressChanged)
virtual QString mapVisualQML() const override;
bool operator==(const WimaMeasurementAreaData &other) const;
bool operator!=(const WimaMeasurementAreaData &other) const;
// Property setters.
void setTileData(const TileData &d);
void setProgress(const QVector<int> &d);
// Property getters.
QString type() const;
WimaMeasurementAreaData *Clone() const {
return new WimaMeasurementAreaData(*this);
}
QmlObjectListModel *tiles();
const QmlObjectListModel *tiles() const;
const QVariantList &tileCenterPoints() const;
QVariantList &tileCenterPoints();
const TileData &tileData() const;
TileData &tileData();
const QVector<int> &progress() const;
QVector<int> &progress();
static const char *typeString;
signals:
void tileDataChanged();
void progressChanged();
private:
TileData _tileData;
QVector<int> _progress;
};
bool operator==(const WimaMeasurementAreaData &m1,
const WimaMeasurementArea &m2);
bool operator!=(const WimaMeasurementAreaData &m1,
const WimaMeasurementArea &m2);
bool operator==(const WimaMeasurementArea &m1,
const WimaMeasurementAreaData &m2);
bool operator!=(const WimaMeasurementArea &m1,
const WimaMeasurementAreaData &m2);
#include "WimaServiceArea.h"
#include "QGCLoggingCategory.h"
#include "QGCQGeoCoordinate.h"
QGC_LOGGING_CATEGORY(WimaServiceAreaLog, "WimaServiceAreaLog")
const char *WimaServiceArea::wimaServiceAreaName = "Service Area";
const char *WimaServiceArea::depotLatitudeName = "DepotLatitude";
const char *WimaServiceArea::depotLongitudeName = "DepotLongitude";
const char *WimaServiceArea::depotAltitudeName = "DepotAltitude";
WimaServiceArea::WimaServiceArea(QObject *parent) : WimaArea(parent) { init(); }
WimaServiceArea::WimaServiceArea(const WimaServiceArea &other, QObject *parent)
: WimaArea(other, parent), _depot(other.depot()) {
init();
}
/*!
* \overload operator=()
*
* Calls the inherited operator WimaArea::operator=().
*/
WimaServiceArea &WimaServiceArea::operator=(const WimaServiceArea &other) {
WimaArea::operator=(other);
this->setDepot(other.depot());
return *this;
}
const QGeoCoordinate &WimaServiceArea::depot() const { return _depot; }
QGeoCoordinate WimaServiceArea::depotQml() const { return _depot; }
bool WimaServiceArea::setDepot(const QGeoCoordinate &coordinate) {
if (_depot.latitude() != coordinate.latitude() ||
_depot.longitude() != coordinate.longitude()) {
if (this->containsCoordinate(coordinate)) {
_depot = coordinate;
_depot.setAltitude(0);
emit depotChanged();
return true;
}
}
return false;
}
void WimaServiceArea::saveToJson(QJsonObject &json) {
this->WimaArea::saveToJson(json);
json[areaTypeName] = wimaServiceAreaName;
json[depotLatitudeName] = _depot.latitude();
json[depotLongitudeName] = _depot.longitude();
json[depotAltitudeName] = _depot.altitude();
}
bool WimaServiceArea::loadFromJson(const QJsonObject &json,
QString &errorString) {
bool retVal = false;
if (this->WimaArea::loadFromJson(json, errorString)) {
double lat = 0;
if (json.contains(depotLatitudeName) &&
json[depotLatitudeName].isDouble()) {
lat = json[depotLatitudeName].toDouble();
double lon = 0;
if (json.contains(depotLongitudeName) &&
json[depotLongitudeName].isDouble()) {
lon = json[depotLongitudeName].toDouble();
double alt = 0;
if (json.contains(depotAltitudeName) &&
json[depotAltitudeName].isDouble()) {
alt = json[depotAltitudeName].toDouble();
this->setDepot(QGeoCoordinate(lat, lon, alt));
retVal = true;
} else {
errorString = "Not able to load depot altitude.";
}
} else {
errorString = "Not able to load depot longitude.";
}
} else {
errorString = "Not able to load depot latitude.";
}
retVal = true;
}
return retVal;
}
void WimaServiceArea::init() {
this->setObjectName(wimaServiceAreaName);
connect(this, &WimaArea::pathChanged, [this] {
if (!this->_depot.isValid() || !this->containsCoordinate(this->_depot)) {
if (this->containsCoordinate(this->center())) {
// Use center.
this->setDepot(this->center());
} else if (this->_depot.isValid()) {
// Use nearest coordinate.
auto minDist = std::numeric_limits<double>::infinity();
int minIndex = 0;
for (int idx = 0; idx < this->pathModel().count(); ++idx) {
const QObject *obj = this->pathModel()[idx];
const auto *vertex = qobject_cast<const QGCQGeoCoordinate *>(obj);
if (vertex != nullptr) {
auto d = vertex->coordinate().distanceTo(this->_depot);
if (d < minDist) {
minDist = d;
minIndex = idx;
}
} else {
qCCritical(WimaServiceAreaLog) << "init(): nullptr catched!";
}
}
this->setDepot(this->pathModel().value<QGCQGeoCoordinate *>(minIndex)->coordinate());
} else if (this->pathModel().count() > 0) {
// Use first coordinate.
this->setDepot(this->pathModel().value<QGCQGeoCoordinate *>(0)->coordinate());
}
}
});
}
#pragma once
#include "WimaArea.h"
#include "WimaTrackerPolyline.h"
#include <QObject>
class WimaServiceArea : public WimaArea {
Q_OBJECT
public:
WimaServiceArea(QObject *parent = nullptr);
WimaServiceArea(const WimaServiceArea &other, QObject *parent);
WimaServiceArea &operator=(const WimaServiceArea &other);
Q_PROPERTY(
QGeoCoordinate depot READ depotQml WRITE setDepot NOTIFY depotChanged)
// Overrides from WimaPolygon
QString mapVisualQML(void) const { return "WimaServiceAreaMapVisual.qml"; }
QString editorQML(void) const { return "WimaServiceAreaEditor.qml"; }
// Property acessors
const QGeoCoordinate &depot(void) const;
QGeoCoordinate depotQml(void) const;
// Member Methodes
void saveToJson(QJsonObject &json);
bool loadFromJson(const QJsonObject &json, QString &errorString);
// static Members
static const char *wimaServiceAreaName;
static const char *depotLatitudeName;
static const char *depotLongitudeName;
static const char *depotAltitudeName;
signals:
void depotChanged(void);
public slots:
bool setDepot(const QGeoCoordinate &coordinate);
private:
// Member Methodes
void init();
// Members
QGeoCoordinate _depot;
};
#include "WimaServiceAreaData.h"
const char *WimaServiceAreaData::typeString = "WimaServiceAreaData";
WimaServiceAreaData::WimaServiceAreaData(QObject *parent)
: WimaAreaData(parent) {}
WimaServiceAreaData::WimaServiceAreaData(const WimaServiceAreaData &other,
QObject *parent)
: WimaAreaData(other, parent), _depot(other._depot) {}
WimaServiceAreaData::WimaServiceAreaData(const WimaServiceArea &other,
QObject *parent)
: WimaAreaData(other, parent), _depot(other.depot()) {}
WimaServiceAreaData &WimaServiceAreaData::
operator=(const WimaServiceAreaData &otherData) {
WimaAreaData::operator=(otherData);
this->setDepot(otherData.depot());
return *this;
}
WimaServiceAreaData &WimaServiceAreaData::
operator=(const WimaServiceArea &otherArea) {
WimaAreaData::operator=(otherArea);
this->setDepot(otherArea.depot());
return *this;
}
QString WimaServiceAreaData::mapVisualQML() const {
return QStringLiteral("WimaServiceAreaDataVisual.qml");
}
/*!
* \fn const QGeoCoordinate &WimaServiceAreaData::takeOffPosition() const
* Returns a constant reference to the takeOffPosition.
*
*/
const QGeoCoordinate &WimaServiceAreaData::depot() const { return _depot; }
QString WimaServiceAreaData::type() const { return this->typeString; }
/*!
* \fn void WimaServiceAreaData::setTakeOffPosition(const QGeoCoordinate
* &newCoordinate) Sets the takeoff position to the \a newCoordinate and emits
* the takeOffPositionChanged() signal, if newCoordinate differs from the member
* value.
*
*/
void WimaServiceAreaData::setDepot(const QGeoCoordinate &newCoordinate) {
if (_depot != newCoordinate) {
_depot = newCoordinate;
emit depotChanged(_depot);
}
}
/*!
* \class WimaAreaData::WimaServiceAreaData
* \brief Class to store and exchange data of a \c WimaServiceArea Object.
* Class to store and exchange data of a \c WimaServiceArea Object. In contrast
* to \c WimaServiceArea this class does not provied any interface to a grafical
* user interface, neiter it uses the QGC Fact System. It is designed to
* exchange data between the \c WimaPlaner and the \c WimaController class. And
* it is the derived from WimaAreaData.
*
* \sa WimaServiceArea, WimaAreaData
*/
#pragma once
#include "QGeoCoordinate"
#include <QObject>
#include "WimaAreaData.h"
#include "WimaServiceArea.h"
class WimaServiceAreaData : public WimaAreaData {
Q_OBJECT
public:
WimaServiceAreaData(QObject *parent = nullptr);
WimaServiceAreaData(const WimaServiceAreaData &other,
QObject *parent = nullptr);
WimaServiceAreaData(const WimaServiceArea &other, QObject *parent = nullptr);
WimaServiceAreaData &operator=(const WimaServiceAreaData &otherData);
WimaServiceAreaData &operator=(const WimaServiceArea &otherArea);
virtual QString mapVisualQML() const override;
const QGeoCoordinate &depot() const;
QString type() const;
WimaServiceAreaData *Clone() const { return new WimaServiceAreaData(); }
static const char *typeString;
signals:
void depotChanged(const QGeoCoordinate &other);
public slots:
void setDepot(const QGeoCoordinate &newCoordinate);
private:
// see WimaServieArea.h for explanation
QGeoCoordinate _depot;
};
[
{
"name": "BorderPolygonOffset",
"shortDescription": "The distance between the measurement area and it's surrounding polygon",
"type": "double",
"units": "m",
"min": 0,
"decimalPlaces": 1,
"defaultValue": 5
},
{
"name": "ShowBorderPolygon",
"shortDescription": "Border polygon will be displayed if checked.",
"type": "bool",
"defaultValue": true
}
]
[
{
"name": "TileHeight",
"shortDescription": "The height of a tile",
"type": "double",
"units": "m",
"min": 0.3,
"decimalPlaces": 2,
"defaultValue": 5
},
{
"name": "TileWidth",
"shortDescription": "The height of a tile",
"type": "double",
"units": "m",
"min": 0.3,
"decimalPlaces": 2,
"defaultValue": 5
},
{
"name": "MinTileAreaPercent",
"shortDescription": "The minimal allowed area in percent (of width*height).",
"type": "double",
"units": "%",
"min": 0,
"max": 100,
"decimalPlaces": 2,
"defaultValue": 20
},
{
"name": "ShowTiles",
"shortDescription": "Show tiles",
"type": "bool",
"defaultValue": true
},
{
"name": "BorderPolygonOffset",
"shortDescription": "The distance between the measurement area and it's enclosing polygon",
"type": "double",
"units": "m",
"min": 0,
"decimalPlaces": 1,
"defaultValue": 5
}
]
#pragma once
#include "PlanimetryCalculus.h"
#include <QPointF>
#include <QLineF>
namespace TestPlanimetryCalculus {
void test();
}
This diff is collapsed.
#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.
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.
This diff is collapsed.
#pragma once
#include "ros_bridge/include/messages/nemo_msgs/heartbeat.h"
using QNemoHeartbeat = ros_bridge::messages::nemo_msgs::heartbeat::Heartbeat;
#pragma once
#include <QVector>
#include "ros_bridge/include/messages/nemo_msgs/progress.h"
namespace nemo = ros_bridge::messages::nemo_msgs;
typedef nemo::progress::GenericProgress<int, QVector> QNemoProgress;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#pragma once
#include "Wima/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.
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.
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.
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.
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.
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