diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 84ad18bd83952763bc46eea7d68f18e7dec7037d..f62752ad4e8646e5392396fd545a35c60a250933 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -384,7 +384,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin { src/FactSystem/FactSystemTestGeneric.h \ src/FactSystem/FactSystemTestPX4.h \ src/FactSystem/ParameterManagerTest.h \ - src/MissionManager/ComplexMissionItemTest.h \ + src/MissionManager/SurveyMissionItemTest.h \ src/MissionManager/MissionCommandTreeTest.h \ src/MissionManager/MissionControllerManagerTest.h \ src/MissionManager/MissionControllerTest.h \ @@ -412,7 +412,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin { src/FactSystem/FactSystemTestGeneric.cc \ src/FactSystem/FactSystemTestPX4.cc \ src/FactSystem/ParameterManagerTest.cc \ - src/MissionManager/ComplexMissionItemTest.cc \ + src/MissionManager/SurveyMissionItemTest.cc \ src/MissionManager/MissionCommandTreeTest.cc \ src/MissionManager/MissionControllerManagerTest.cc \ src/MissionManager/MissionControllerTest.cc \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 79aa7115226633485b0b0a933101fa3957e51958..ca4446574d1051f2e2de0b6744da596fae0e2130 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -85,6 +85,7 @@ src/QmlControls/QGCLabel.qml src/QmlControls/QGCListView.qml src/QmlControls/QGCMapLabel.qml + src/MissionManager/QGCMapPolygonVisuals.qml src/QmlControls/QGCMouseArea.qml src/QmlControls/QGCMovableItem.qml src/QmlControls/QGCPipable.qml diff --git a/src/MissionManager/QGCMapPolygon.cc b/src/MissionManager/QGCMapPolygon.cc index cdc31d2917bc213332d0c91210093d915e6a2f70..61017ef5bd92a5ef6666c40d3e8e133964e05162 100644 --- a/src/MissionManager/QGCMapPolygon.cc +++ b/src/MissionManager/QGCMapPolygon.cc @@ -16,15 +16,17 @@ #include #include -const char* QGCMapPolygon::_jsonPolygonKey = "polygon"; +const char* QGCMapPolygon::jsonPolygonKey = "polygon"; QGCMapPolygon::QGCMapPolygon(QObject* newCoordParent, QObject* parent) : QObject(parent) , _newCoordParent(newCoordParent) , _dirty(false) + , _ignoreCenterUpdates(false) { connect(&_polygonModel, &QmlObjectListModel::dirtyChanged, this, &QGCMapPolygon::_polygonModelDirtyChanged); connect(&_polygonModel, &QmlObjectListModel::countChanged, this, &QGCMapPolygon::_polygonModelCountChanged); + connect(&_polygonModel, &QmlObjectListModel::countChanged, this, &QGCMapPolygon::_updateCenter); } void QGCMapPolygon::clear(void) @@ -43,6 +45,8 @@ void QGCMapPolygon::clear(void) _polygonModel.clearAndDeleteContents(); + emit cleared(); + setDirty(true); } @@ -53,6 +57,10 @@ void QGCMapPolygon::adjustVertex(int vertexIndex, const QGeoCoordinate coordinat _polygonModel.value(vertexIndex)->setCoordinate(coordinate); + if (!_ignoreCenterUpdates) { + _updateCenter(); + } + setDirty(true); } @@ -111,16 +119,6 @@ bool QGCMapPolygon::containsCoordinate(const QGeoCoordinate& coordinate) const } } -QGeoCoordinate QGCMapPolygon::center(void) const -{ - if (_polygonPath.count() > 2) { - QPointF centerPoint = _toPolygonF().boundingRect().center(); - return _coordFromPointF(centerPoint); - } else { - return QGeoCoordinate(); - } -} - void QGCMapPolygon::setPath(const QList& path) { _polygonPath.clear(); @@ -152,7 +150,7 @@ void QGCMapPolygon::saveToJson(QJsonObject& json) QJsonValue jsonValue; JsonHelper::saveGeoCoordinateArray(_polygonPath, false /* writeAltitude*/, jsonValue); - json.insert(_jsonPolygonKey, jsonValue); + json.insert(jsonPolygonKey, jsonValue); setDirty(false); } @@ -162,14 +160,14 @@ bool QGCMapPolygon::loadFromJson(const QJsonObject& json, bool required, QString clear(); if (required) { - if (!JsonHelper::validateRequiredKeys(json, QStringList(_jsonPolygonKey), errorString)) { + if (!JsonHelper::validateRequiredKeys(json, QStringList(jsonPolygonKey), errorString)) { return false; } - } else if (!json.contains(_jsonPolygonKey)) { + } else if (!json.contains(jsonPolygonKey)) { return true; } - if (!JsonHelper::loadGeoCoordinateArray(json[_jsonPolygonKey], false /* altitudeRequired */, _polygonPath, errorString)) { + if (!JsonHelper::loadGeoCoordinateArray(json[jsonPolygonKey], false /* altitudeRequired */, _polygonPath, errorString)) { return false; } setDirty(false); @@ -249,3 +247,38 @@ void QGCMapPolygon::_polygonModelCountChanged(int count) { emit countChanged(count); } + +void QGCMapPolygon::_updateCenter(void) +{ + if (!_ignoreCenterUpdates) { + QGeoCoordinate center; + + if (_polygonPath.count() > 2) { + QPointF centerPoint = _toPolygonF().boundingRect().center(); + center = _coordFromPointF(centerPoint); + } + + _center = center; + emit centerChanged(center); + } +} + +void QGCMapPolygon::setCenter(QGeoCoordinate newCenter) +{ + if (newCenter != _center) { + _ignoreCenterUpdates = true; + + // Adjust polygon vertices to new center + double distance = _center.distanceTo(newCenter); + double azimuth = _center.azimuthTo(newCenter); + + for (int i=0; i(); + QGeoCoordinate newVertex = oldVertex.atDistanceAndAzimuth(distance, azimuth); + adjustVertex(i, newVertex); + } + + _ignoreCenterUpdates = false; + _updateCenter(); + } +} diff --git a/src/MissionManager/QGCMapPolygon.h b/src/MissionManager/QGCMapPolygon.h index 4e534f01848bfcf24f8580e09a84439d2d674a0b..4a4f7f2f7c97d4883879462b8eab66b891577eba 100644 --- a/src/MissionManager/QGCMapPolygon.h +++ b/src/MissionManager/QGCMapPolygon.h @@ -26,10 +26,11 @@ class QGCMapPolygon : public QObject public: QGCMapPolygon(QObject* newCoordParent, QObject* parent = NULL); - Q_PROPERTY(int count READ count NOTIFY countChanged) - Q_PROPERTY(QVariantList path READ path NOTIFY pathChanged) - Q_PROPERTY(QmlObjectListModel* pathModel READ qmlPathModel CONSTANT) - Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) + Q_PROPERTY(int count READ count NOTIFY countChanged) + Q_PROPERTY(QVariantList path READ path NOTIFY pathChanged) + Q_PROPERTY(QmlObjectListModel* pathModel READ qmlPathModel CONSTANT) + Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) + Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter NOTIFY centerChanged) Q_INVOKABLE void clear(void); Q_INVOKABLE void appendVertex(const QGeoCoordinate& coordinate); @@ -43,9 +44,6 @@ public: /// Splits the segment comprised of vertextIndex -> vertexIndex + 1 Q_INVOKABLE void splitPolygonSegment(int vertexIndex); - /// Returns the center point coordinate for the polygon - Q_INVOKABLE QGeoCoordinate center(void) const; - /// Returns true if the specified coordinate is within the polygon Q_INVOKABLE bool containsCoordinate(const QGeoCoordinate& coordinate) const; @@ -65,9 +63,11 @@ public: // Property methods - int count (void) const { return _polygonPath.count(); } - bool dirty (void) const { return _dirty; } - void setDirty(bool dirty); + int count (void) const { return _polygonPath.count(); } + bool dirty (void) const { return _dirty; } + void setDirty(bool dirty); + QGeoCoordinate center (void) const { return _center; } + QVariantList path (void) const { return _polygonPath; } QmlObjectListModel* qmlPathModel(void) { return &_polygonModel; } @@ -75,15 +75,21 @@ public: void setPath(const QList& path); void setPath(const QVariantList& path); + void setCenter(QGeoCoordinate newCenter); + + static const char* jsonPolygonKey; signals: - void countChanged(int count); - void pathChanged(void); - void dirtyChanged(bool dirty); + void countChanged (int count); + void pathChanged (void); + void dirtyChanged (bool dirty); + void cleared (void); + void centerChanged (QGeoCoordinate center); private slots: void _polygonModelCountChanged(int count); void _polygonModelDirtyChanged(bool dirty); + void _updateCenter(void); private: QPolygonF _toPolygonF(void) const; @@ -94,8 +100,8 @@ private: QVariantList _polygonPath; QmlObjectListModel _polygonModel; bool _dirty; - - static const char* _jsonPolygonKey; + QGeoCoordinate _center; + bool _ignoreCenterUpdates; }; #endif diff --git a/src/MissionManager/QGCMapPolygonVisuals.qml b/src/MissionManager/QGCMapPolygonVisuals.qml new file mode 100644 index 0000000000000000000000000000000000000000..9e5b0d5123e98876b4854666ae2c552d4d305f36 --- /dev/null +++ b/src/MissionManager/QGCMapPolygonVisuals.qml @@ -0,0 +1,251 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtLocation 5.3 +import QtPositioning 5.3 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightMap 1.0 + +/// QGCMapPolygon map visuals +Item { + id: _root + + property var mapControl ///< Map control to place item in + property var mapPolygon ///< QGCMapPolygon object + + property var _polygonComponent + property var _dragHandlesComponent + property var _splitHandlesComponent + property var _centerDragHandleComponent + + function addVisuals() { + _polygonComponent = polygonComponent.createObject(mapControl) + mapControl.addMapItem(_polygonComponent) + } + + function removeVisuals() { + _polygonComponent.destroy() + } + + function addHandles() { + _dragHandlesComponent = dragHandlesComponent.createObject(mapControl) + _splitHandlesComponent = splitHandlesComponent.createObject(mapControl) + _centerDragHandleComponent = centerDragHandleComponent.createObject(mapControl) + } + + function removeHandles() { + if (_dragHandlesComponent) { + _dragHandlesComponent.destroy() + _dragHandlesComponent = undefined + } + if (_splitHandlesComponent) { + _splitHandlesComponent.destroy() + _splitHandlesComponent = undefined + } + if (_centerDragHandleComponent) { + _centerDragHandleComponent.destroy() + _centerDragHandleComponent = undefined + } + } + + Component.onDestruction: { + removeVisuals() + removeHandles() + } + + Component { + id: polygonComponent + + MapPolygon { + color: "green" + opacity: 0.5 + path: mapPolygon.path + } + } + + Component { + id: splitHandleComponent + + MapQuickItem { + id: mapQuickItem + anchorPoint.x: dragHandle.width / 2 + anchorPoint.y: dragHandle.height / 2 + z: QGroundControl.zOrderMapItems + 1 + + property int vertexIndex + + sourceItem: Rectangle { + id: dragHandle + width: ScreenTools.defaultFontPixelHeight * 1.5 + height: width + radius: width / 2 + color: "white" + opacity: .50 + + QGCLabel { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + text: "+" + } + + QGCMouseArea { + fillItem: parent + onClicked: mapPolygon.splitPolygonSegment(mapQuickItem.vertexIndex) + } + } + } + } + + Component { + id: splitHandlesComponent + + Repeater { + model: mapPolygon.path + + delegate: Item { + property var _splitHandle + property var _vertices: mapPolygon.path + + function _setHandlePosition() { + var nextIndex = index + 1 + if (nextIndex > _vertices.length - 1) { + nextIndex = 0 + } + var distance = _vertices[index].distanceTo(_vertices[nextIndex]) + var azimuth = _vertices[index].azimuthTo(_vertices[nextIndex]) + _splitHandle.coordinate = _vertices[index].atDistanceAndAzimuth(distance / 2, azimuth) + } + + Component.onCompleted: { + _splitHandle = splitHandleComponent.createObject(mapControl) + _splitHandle.vertexIndex = index + _setHandlePosition() + mapControl.addMapItem(_splitHandle) + } + + Component.onDestruction: { + if (_splitHandle) { + _splitHandle.destroy() + } + } + } + } + } + + // Control which is used to drag polygon vertices + Component { + id: dragAreaComponent + + MissionItemIndicatorDrag { + id: dragArea + + property int polygonVertex + + property bool _creationComplete: false + + Component.onCompleted: _creationComplete = true + + onItemCoordinateChanged: { + if (_creationComplete) { + // During component creation some bad coordinate values got through which screws up polygon draw + mapPolygon.adjustVertex(polygonVertex, itemCoordinate) + } + } + + onClicked: mapPolygon.removeVertex(polygonVertex) + } + } + + Component { + id: dragHandleComponent + + MapQuickItem { + id: mapQuickItem + anchorPoint.x: dragHandle.width / 2 + anchorPoint.y: dragHandle.height / 2 + z: QGroundControl.zOrderMapItems + 2 + + sourceItem: Rectangle { + id: dragHandle + width: ScreenTools.defaultFontPixelHeight * 1.5 + height: width + radius: width / 2 + color: "white" + opacity: .90 + } + } + } + + // Add all polygon vertex drag handles to the map + Component { + id: dragHandlesComponent + + Repeater { + model: mapPolygon.pathModel + + delegate: Item { + property var _visuals: [ ] + + Component.onCompleted: { + var dragHandle = dragHandleComponent.createObject(mapControl) + dragHandle.coordinate = Qt.binding(function() { return object.coordinate }) + mapControl.addMapItem(dragHandle) + var dragArea = dragAreaComponent.createObject(mapControl, { "itemIndicator": dragHandle, "itemCoordinate": object.coordinate }) + dragArea.polygonVertex = Qt.binding(function() { return index }) + _visuals.push(dragHandle) + _visuals.push(dragArea) + } + + Component.onDestruction: { + for (var i=0; i<_visuals.length; i++) { + _visuals[i].destroy() + } + _visuals = [ ] + } + } + } + } + + Component { + id: centerDragAreaComponent + + MissionItemIndicatorDrag { + onItemCoordinateChanged: mapPolygon.center = itemCoordinate + } + } + + Component { + id: centerDragHandleComponent + + Item { + property var dragHandle + property var dragArea + + Component.onCompleted: { + dragHandle = dragHandleComponent.createObject(mapControl) + dragHandle.coordinate = Qt.binding(function() { return mapPolygon.center }) + mapControl.addMapItem(dragHandle) + dragArea = centerDragAreaComponent.createObject(mapControl, { "itemIndicator": dragHandle, "itemCoordinate": mapPolygon.center }) + } + + Component.onDestruction: { + dragHandle.destroy() + dragArea.destroy() + } + } + } +} + + diff --git a/src/MissionManager/SurveyMissionItem.cc b/src/MissionManager/SurveyMissionItem.cc index 1478a297563e06de3839a2c512f1aea815088480..350aaaad3bec63f939c99df6b89ee9315b0c2158 100644 --- a/src/MissionManager/SurveyMissionItem.cc +++ b/src/MissionManager/SurveyMissionItem.cc @@ -21,7 +21,6 @@ QGC_LOGGING_CATEGORY(SurveyMissionItemLog, "SurveyMissionItemLog") const char* SurveyMissionItem::jsonComplexItemTypeValue = "survey"; -const char* SurveyMissionItem::_jsonPolygonObjectKey = "polygon"; const char* SurveyMissionItem::_jsonGridObjectKey = "grid"; const char* SurveyMissionItem::_jsonGridAltitudeKey = "altitude"; const char* SurveyMissionItem::_jsonGridAltitudeRelativeKey = "relativeAltitude"; @@ -74,6 +73,7 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent) : ComplexMissionItem(vehicle, parent) , _sequenceNumber(0) , _dirty(false) + , _mapPolygon(this) , _cameraOrientationFixed(false) , _missionCommandCount(0) , _refly90Degrees(false) @@ -134,6 +134,9 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent) connect(&_cameraOrientationLandscapeFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged); connect(&_cameraTriggerDistanceFact, &Fact::valueChanged, this, &SurveyMissionItem::timeBetweenShotsChanged); + + connect(&_mapPolygon, &QGCMapPolygon::dirtyChanged, this, &SurveyMissionItem::_polygonDirtyChanged); + connect(&_mapPolygon, &QGCMapPolygon::pathChanged, this, &SurveyMissionItem::_generateGrid); } void SurveyMissionItem::_setSurveyDistance(double surveyDistance) @@ -160,115 +163,24 @@ void SurveyMissionItem::_setCoveredArea(double coveredArea) } } - -void SurveyMissionItem::clearPolygon(void) +void SurveyMissionItem::_clearInternal(void) { - // Bug workaround, see below - while (_polygonPath.count() > 1) { - _polygonPath.takeLast(); + // Bug workaround + while (_simpleGridPoints.count() > 1) { + _simpleGridPoints.takeLast(); } - emit polygonPathChanged(); - - // Although this code should remove the polygon from the map it doesn't. There appears - // to be a bug in MapPolygon which causes it to not be redrawn if the list is empty. So - // we work around it by using the code above to remove all but the last point which in turn - // will cause the polygon to go away. - _polygonPath.clear(); + emit gridPointsChanged(); + _simpleGridPoints.clear(); + _transectSegments.clear(); - _polygonModel.clearAndDeleteContents(); + _missionCommandCount = 0; - _clearGrid(); setDirty(true); emit specifiesCoordinateChanged(); emit lastSequenceNumberChanged(lastSequenceNumber()); } -void SurveyMissionItem::addPolygonCoordinate(const QGeoCoordinate coordinate) -{ - _polygonModel.append(new QGCQGeoCoordinate(coordinate, this)); - - _polygonPath << QVariant::fromValue(coordinate); - emit polygonPathChanged(); - - int pointCount = _polygonPath.count(); - if (pointCount >= 3) { - if (pointCount == 3) { - emit specifiesCoordinateChanged(); - } - _generateGrid(); - } - setDirty(true); -} - -void SurveyMissionItem::adjustPolygonCoordinate(int vertexIndex, const QGeoCoordinate coordinate) -{ - if (vertexIndex < 0 && vertexIndex > _polygonPath.length() - 1) { - qWarning() << "Call to adjustPolygonCoordinate with bad vertexIndex:count" << vertexIndex << _polygonPath.length(); - return; - } - - _polygonModel.value(vertexIndex)->setCoordinate(coordinate); - _polygonPath[vertexIndex] = QVariant::fromValue(coordinate); - emit polygonPathChanged(); - _generateGrid(); - setDirty(true); -} - -void SurveyMissionItem::splitPolygonSegment(int vertexIndex) -{ - int nextIndex = vertexIndex + 1; - if (nextIndex > _polygonPath.length() - 1) { - nextIndex = 0; - } - - QGeoCoordinate firstVertex = _polygonPath[vertexIndex].value(); - QGeoCoordinate nextVertex = _polygonPath[nextIndex].value(); - - double distance = firstVertex.distanceTo(nextVertex); - double azimuth = firstVertex.azimuthTo(nextVertex); - QGeoCoordinate newVertex = firstVertex.atDistanceAndAzimuth(distance / 2, azimuth); - - if (nextIndex == 0) { - addPolygonCoordinate(newVertex); - } else { - _polygonModel.insert(nextIndex, new QGCQGeoCoordinate(newVertex, this)); - _polygonPath.insert(nextIndex, QVariant::fromValue(newVertex)); - emit polygonPathChanged(); - - int pointCount = _polygonPath.count(); - if (pointCount >= 3) { - if (pointCount == 3) { - emit specifiesCoordinateChanged(); - } - _generateGrid(); - } - setDirty(true); - } -} - -void SurveyMissionItem::removePolygonVertex(int vertexIndex) -{ - if (vertexIndex < 0 && vertexIndex > _polygonPath.length() - 1) { - qWarning() << "Call to removePolygonCoordinate with bad vertexIndex:count" << vertexIndex << _polygonPath.length(); - return; - } - - if (_polygonPath.length() <= 3) { - // Don't allow the user to trash the polygon - return; - } - - QObject* coordObj = _polygonModel.removeAt(vertexIndex); - coordObj->deleteLater(); - - _polygonPath.removeAt(vertexIndex); - emit polygonPathChanged(); - - _generateGrid(); - setDirty(true); -} - int SurveyMissionItem::lastSequenceNumber(void) const { return _sequenceNumber + _missionCommandCount; @@ -333,9 +245,7 @@ void SurveyMissionItem::save(QJsonArray& missionItems) } // Polygon shape - QJsonArray polygonArray; - JsonHelper::savePolygon(_polygonModel, polygonArray); - saveObject[_jsonPolygonObjectKey] = polygonArray; + _mapPolygon.saveToJson(saveObject); missionItems.append(saveObject); } @@ -349,13 +259,6 @@ void SurveyMissionItem::setSequenceNumber(int sequenceNumber) } } -void SurveyMissionItem::_clear(void) -{ - clearPolygon(); - _clearGrid(); -} - - bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumber, QString& errorString) { QJsonObject v2Object = complexObject; @@ -385,7 +288,7 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumbe { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, { VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, { ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true }, - { _jsonPolygonObjectKey, QJsonValue::Array, true }, + { QGCMapPolygon::jsonPolygonKey, QJsonValue::Array, true }, { _jsonGridObjectKey, QJsonValue::Object, true }, { _jsonCameraObjectKey, QJsonValue::Object, false }, { _jsonCameraTriggerKey, QJsonValue::Bool, true }, @@ -406,7 +309,7 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumbe return false; } - _clear(); + _mapPolygon.clear(); setSequenceNumber(sequenceNumber); @@ -487,16 +390,15 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumbe } // Polygon shape - QJsonArray polygonArray(v2Object[_jsonPolygonObjectKey].toArray()); - if (!JsonHelper::loadPolygon(polygonArray, _polygonModel, this, errorString)) { - _clear(); + /// Load a polygon from json + /// @param json Json object to load from + /// @param required true: no polygon in object will generate error + /// @param errorString Error string if return is false + /// @return true: success, false: failure (errorString set) + if (!_mapPolygon.loadFromJson(v2Object, true /* required */, errorString)) { + _mapPolygon.clear(); return false; } - for (int i=0; i<_polygonModel.count(); i++) { - _polygonPath << QVariant::fromValue(_polygonModel.value(i)->coordinate()); - } - - _generateGrid(); return true; } @@ -524,20 +426,7 @@ void SurveyMissionItem::_setExitCoordinate(const QGeoCoordinate& coordinate) bool SurveyMissionItem::specifiesCoordinate(void) const { - return _polygonPath.count() > 2; -} - -void SurveyMissionItem::_clearGrid(void) -{ - // Bug workaround - while (_simpleGridPoints.count() > 1) { - _simpleGridPoints.takeLast(); - } - emit gridPointsChanged(); - _simpleGridPoints.clear(); - _transectSegments.clear(); - - _missionCommandCount = 0; + return _mapPolygon.count() > 2; } void _calcCameraShots() @@ -578,8 +467,8 @@ void SurveyMissionItem::_convertPointsToGeo(const QList& pointsNED, con void SurveyMissionItem::_generateGrid(void) { - if (_polygonPath.count() < 3 || _gridSpacingFact.rawValue().toDouble() <= 0) { - _clearGrid(); + if (_mapPolygon.count() < 3 || _gridSpacingFact.rawValue().toDouble() <= 0) { + _clearInternal(); return; } @@ -593,12 +482,13 @@ void SurveyMissionItem::_generateGrid(void) // Convert polygon to Qt coordinate system (y positive is down) qCDebug(SurveyMissionItemLog) << "Convert polygon"; - QGeoCoordinate tangentOrigin = _polygonPath[0].value(); - for (int i=0; i<_polygonPath.count(); i++) { + QGeoCoordinate tangentOrigin = _mapPolygon.path()[0].value(); + for (int i=0; i<_mapPolygon.count(); i++) { double y, x, down; - convertGeoToNed(_polygonPath[i].value(), tangentOrigin, &y, &x, &down); + QGeoCoordinate vertex = _mapPolygon.pathModel().value(i)->coordinate(); + convertGeoToNed(vertex, tangentOrigin, &y, &x, &down); polygonPoints += QPointF(x, -y); - qCDebug(SurveyMissionItemLog) << _polygonPath[i].value() << polygonPoints.last().x() << polygonPoints.last().y(); + qCDebug(SurveyMissionItemLog) << vertex << polygonPoints.last().x() << polygonPoints.last().y(); } double coveredArea = 0.0; @@ -1176,3 +1066,10 @@ void SurveyMissionItem::setRefly90Degrees(bool refly90Degrees) emit refly90DegreesChanged(refly90Degrees); } } + +void SurveyMissionItem::_polygonDirtyChanged(bool dirty) +{ + if (dirty) { + setDirty(true); + } +} diff --git a/src/MissionManager/SurveyMissionItem.h b/src/MissionManager/SurveyMissionItem.h index 0eda140421137017efed8c6563df148f99a14be3..9c8073097aeea53a9ec6d1184760f9df1c6a2276 100644 --- a/src/MissionManager/SurveyMissionItem.h +++ b/src/MissionManager/SurveyMissionItem.h @@ -15,6 +15,7 @@ #include "MissionItem.h" #include "SettingsFact.h" #include "QGCLoggingCategory.h" +#include "QGCMapPolygon.h" Q_DECLARE_LOGGING_CATEGORY(SurveyMissionItemLog) @@ -52,25 +53,18 @@ public: Q_PROPERTY(bool refly90Degrees READ refly90Degrees WRITE setRefly90Degrees NOTIFY refly90DegreesChanged) Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged) - Q_PROPERTY(QVariantList polygonPath READ polygonPath NOTIFY polygonPathChanged) Q_PROPERTY(QVariantList gridPoints READ gridPoints NOTIFY gridPointsChanged) Q_PROPERTY(int cameraShots READ cameraShots NOTIFY cameraShotsChanged) Q_PROPERTY(double coveredArea READ coveredArea NOTIFY coveredAreaChanged) + Q_PROPERTY(QGCMapPolygon* mapPolygon READ mapPolygon CONSTANT) + +#if 0 // The polygon vertices are also exposed as a list mode since MapItemView will only work with a QAbstractItemModel as // opposed to polygonPath which is a QVariantList. Q_PROPERTY(QmlObjectListModel* polygonModel READ polygonModel CONSTANT) - - Q_INVOKABLE void clearPolygon(void); - Q_INVOKABLE void addPolygonCoordinate(const QGeoCoordinate coordinate); - Q_INVOKABLE void adjustPolygonCoordinate(int vertexIndex, const QGeoCoordinate coordinate); - Q_INVOKABLE void removePolygonVertex(int vertexIndex); - - // Splits the segment between vertextIndex and the next vertex in half - Q_INVOKABLE void splitPolygonSegment(int vertexIndex); - - QVariantList polygonPath (void) { return _polygonPath; } - QmlObjectListModel* polygonModel(void) { return &_polygonModel; } + Q_PROPERTY(QVariantList polygonPath READ polygonPath NOTIFY polygonPathChanged) +#endif QVariantList gridPoints (void) { return _simpleGridPoints; } @@ -96,11 +90,12 @@ public: Fact* fixedValueIsAltitude (void) { return &_fixedValueIsAltitudeFact; } Fact* camera (void) { return &_cameraFact; } - int cameraShots (void) const; - double coveredArea (void) const { return _coveredArea; } - double timeBetweenShots (void) const; - bool hoverAndCaptureAllowed (void) const; - bool refly90Degrees (void) const { return _refly90Degrees; } + int cameraShots (void) const; + double coveredArea (void) const { return _coveredArea; } + double timeBetweenShots (void) const; + bool hoverAndCaptureAllowed (void) const; + bool refly90Degrees (void) const { return _refly90Degrees; } + QGCMapPolygon* mapPolygon (void) { return &_mapPolygon; } void setRefly90Degrees(bool refly90Degrees); @@ -179,6 +174,8 @@ signals: private slots: void _setDirty(void); + void _polygonDirtyChanged(bool dirty); + void _clearInternal(void); private: enum CameraTriggerCode { @@ -188,9 +185,7 @@ private: CameraTriggerHoverAndCapture }; - void _clear(void); void _setExitCoordinate(const QGeoCoordinate& coordinate); - void _clearGrid(void); void _generateGrid(void); void _updateCoordinateAltitude(void); int _gridGenerator(const QList& polygonPoints, QList& simpleGridPoints, QList>& transectSegments, bool refly); @@ -216,8 +211,7 @@ private: int _sequenceNumber; bool _dirty; - QVariantList _polygonPath; - QmlObjectListModel _polygonModel; + QGCMapPolygon _mapPolygon; QVariantList _simpleGridPoints; ///< Grid points for drawing simple grid visuals QList> _transectSegments; ///< Internal transect segments including grid exit, turnaround and internal camera points QList> _reflyTransectSegments; ///< Refly segments @@ -257,7 +251,6 @@ private: SettingsFact _fixedValueIsAltitudeFact; SettingsFact _cameraFact; - static const char* _jsonPolygonObjectKey; static const char* _jsonGridObjectKey; static const char* _jsonGridAltitudeKey; static const char* _jsonGridAltitudeRelativeKey; diff --git a/src/MissionManager/ComplexMissionItemTest.cc b/src/MissionManager/SurveyMissionItemTest.cc similarity index 78% rename from src/MissionManager/ComplexMissionItemTest.cc rename to src/MissionManager/SurveyMissionItemTest.cc index a91e37dda22d1c7c6b6703f6e67f837fa720c502..0fbef43266c544dad642bae4a9e7e7bab572ad18 100644 --- a/src/MissionManager/ComplexMissionItemTest.cc +++ b/src/MissionManager/SurveyMissionItemTest.cc @@ -8,15 +8,15 @@ ****************************************************************************/ -#include "ComplexMissionItemTest.h" +#include "SurveyMissionItemTest.h" -ComplexMissionItemTest::ComplexMissionItemTest(void) +SurveyMissionItemTest::SurveyMissionItemTest(void) { _polyPoints << QGeoCoordinate(47.633550640000003, -122.08982199) << QGeoCoordinate(47.634129020000003, -122.08887249) << QGeoCoordinate(47.633619320000001, -122.08811074) << QGeoCoordinate(47.633189139999999, -122.08900124); } -void ComplexMissionItemTest::init(void) +void SurveyMissionItemTest::init(void) { _rgComplexMissionItemSignals[polygonPathChangedIndex] = SIGNAL(polygonPathChanged()); _rgComplexMissionItemSignals[lastSequenceNumberChangedIndex] = SIGNAL(lastSequenceNumberChanged(int)); @@ -45,7 +45,8 @@ void ComplexMissionItemTest::init(void) _rgComplexMissionItemSignals[exitCoordinateHasRelativeAltitudeChangedIndex] = SIGNAL(exitCoordinateHasRelativeAltitudeChanged(bool)); _rgComplexMissionItemSignals[exitCoordinateSameAsEntryChangedIndex] = SIGNAL(exitCoordinateSameAsEntryChanged(bool)); - _complexItem = new SurveyMissionItem(NULL /* Vehicle */, this); + _surveyItem = new SurveyMissionItem(NULL /* Vehicle */, this); + _mapPolygon = _surveyItem->mapPolygon(); // It's important to check that the right signals are emitted at the right time since that drives ui change. // It's also important to check that things are not being over-signalled when they should not be, since that can lead @@ -53,66 +54,66 @@ void ComplexMissionItemTest::init(void) _multiSpy = new MultiSignalSpy(); Q_CHECK_PTR(_multiSpy); - QCOMPARE(_multiSpy->init(_complexItem, _rgComplexMissionItemSignals, _cComplexMissionItemSignals), true); + QCOMPARE(_multiSpy->init(_surveyItem, _rgComplexMissionItemSignals, _cComplexMissionItemSignals), true); } -void ComplexMissionItemTest::cleanup(void) +void SurveyMissionItemTest::cleanup(void) { - delete _complexItem; + delete _surveyItem; delete _multiSpy; } -void ComplexMissionItemTest::_testDirty(void) +void SurveyMissionItemTest::_testDirty(void) { - QVERIFY(!_complexItem->dirty()); - _complexItem->setDirty(false); - QVERIFY(!_complexItem->dirty()); + QVERIFY(!_surveyItem->dirty()); + _surveyItem->setDirty(false); + QVERIFY(!_surveyItem->dirty()); QVERIFY(_multiSpy->checkNoSignals()); - _complexItem->setDirty(true); - QVERIFY(_complexItem->dirty()); + _surveyItem->setDirty(true); + QVERIFY(_surveyItem->dirty()); QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask)); QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex)); _multiSpy->clearAllSignals(); - _complexItem->setDirty(false); - QVERIFY(!_complexItem->dirty()); + _surveyItem->setDirty(false); + QVERIFY(!_surveyItem->dirty()); QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask)); QVERIFY(!_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex)); } -void ComplexMissionItemTest::_testAddPolygonCoordinate(void) +void SurveyMissionItemTest::_testAddPolygonCoordinate(void) { - QCOMPARE(_complexItem->polygonPath().count(), 0); + QCOMPARE(_mapPolygon->count(), 0); // First call to addPolygonCoordinate should trigger: // polygonPathChanged // dirtyChanged - _complexItem->addPolygonCoordinate(_polyPoints[0]); + _mapPolygon->appendVertex(_polyPoints[0]); QVERIFY(_multiSpy->checkOnlySignalByMask(polygonPathChangedMask | dirtyChangedMask)); // Validate object data - QVariantList polyList = _complexItem->polygonPath(); + QVariantList polyList = _mapPolygon->path(); QCOMPARE(polyList.count(), 1); QCOMPARE(polyList[0].value(), _polyPoints[0]); // Reset - _complexItem->setDirty(false); + _surveyItem->setDirty(false); _multiSpy->clearAllSignals(); // Second call to addPolygonCoordinate should only trigger: // polygonPathChanged // dirtyChanged - _complexItem->addPolygonCoordinate(_polyPoints[1]); + _mapPolygon->appendVertex(_polyPoints[1]); QVERIFY(_multiSpy->checkOnlySignalByMask(polygonPathChangedMask | dirtyChangedMask)); - polyList = _complexItem->polygonPath(); + polyList = _mapPolygon->path(); QCOMPARE(polyList.count(), 2); for (int i=0; i(), _polyPoints[i]); } - _complexItem->setDirty(false); + _surveyItem->setDirty(false); _multiSpy->clearAllSignals(); // Third call to addPolygonCoordinate should trigger: @@ -126,33 +127,33 @@ void ComplexMissionItemTest::_testAddPolygonCoordinate(void) // lastSequenceNumberChanged - number of internal mission items changes // gridPointsChanged - grid points show up for the first time - _complexItem->addPolygonCoordinate(_polyPoints[2]); + _mapPolygon->appendVertex(_polyPoints[2]); QVERIFY(_multiSpy->checkOnlySignalByMask(polygonPathChangedMask | lastSequenceNumberChangedMask | gridPointsChangedMask | coordinateChangedMask | exitCoordinateChangedMask | specifiesCoordinateChangedMask | dirtyChangedMask)); int seqNum = _multiSpy->pullIntFromSignalIndex(lastSequenceNumberChangedIndex); QVERIFY(seqNum > 0); - polyList = _complexItem->polygonPath(); + polyList = _mapPolygon->path(); QCOMPARE(polyList.count(), 3); for (int i=0; i(), _polyPoints[i]); } // Test that number of waypoints is doubled when using turnaround waypoints - _complexItem->setTurnaroundDist(60.0); - QVariantList gridPoints = _complexItem->gridPoints(); - _complexItem->setTurnaroundDist(0.0); - QVariantList gridPointsNoT = _complexItem->gridPoints(); + _surveyItem->setTurnaroundDist(60.0); + QVariantList gridPoints = _surveyItem->gridPoints(); + _surveyItem->setTurnaroundDist(0.0); + QVariantList gridPointsNoT = _surveyItem->gridPoints(); QCOMPARE(gridPoints.count(), 2 * gridPointsNoT.count()); } -void ComplexMissionItemTest::_testClearPolygon(void) +void SurveyMissionItemTest::_testClearPolygon(void) { for (int i=0; i<3; i++) { - _complexItem->addPolygonCoordinate(_polyPoints[i]); + _mapPolygon->appendVertex(_polyPoints[i]); } - _complexItem->setDirty(false); + _surveyItem->setDirty(false); _multiSpy->clearAllSignals(); // Call to clearPolygon should trigger: @@ -163,49 +164,49 @@ void ComplexMissionItemTest::_testClearPolygon(void) // dirtyChangedMask // specifiesCoordinateChangedMask - _complexItem->clearPolygon(); + _mapPolygon->clear(); QVERIFY(_multiSpy->checkOnlySignalByMask(polygonPathChangedMask | lastSequenceNumberChangedMask | gridPointsChangedMask | dirtyChangedMask | specifiesCoordinateChangedMask)); QVERIFY(!_multiSpy->pullBoolFromSignalIndex(specifiesCoordinateChangedIndex)); QCOMPARE(_multiSpy->pullIntFromSignalIndex(lastSequenceNumberChangedIndex), 0); - QCOMPARE(_complexItem->polygonPath().count(), 0); - QCOMPARE(_complexItem->gridPoints().count(), 0); + QCOMPARE(_mapPolygon->path().count(), 0); + QCOMPARE(_surveyItem->gridPoints().count(), 0); - _complexItem->setDirty(false); + _surveyItem->setDirty(false); _multiSpy->clearAllSignals(); } -void ComplexMissionItemTest::_testCameraTrigger(void) +void SurveyMissionItemTest::_testCameraTrigger(void) { - QCOMPARE(_complexItem->property("cameraTrigger").toBool(), true); + QCOMPARE(_surveyItem->property("cameraTrigger").toBool(), true); // Set up a grid for (int i=0; i<3; i++) { - _complexItem->addPolygonCoordinate(_polyPoints[i]); + _mapPolygon->appendVertex(_polyPoints[i]); } - _complexItem->setDirty(false); + _surveyItem->setDirty(false); _multiSpy->clearAllSignals(); - int lastSeq = _complexItem->lastSequenceNumber(); + int lastSeq = _surveyItem->lastSequenceNumber(); QVERIFY(lastSeq > 0); // Turning off camera triggering should remove two camera trigger mission items, this should trigger: // lastSequenceNumberChanged // dirtyChanged - _complexItem->setProperty("cameraTrigger", false); + _surveyItem->setProperty("cameraTrigger", false); QVERIFY(_multiSpy->checkOnlySignalByMask(lastSequenceNumberChangedMask | dirtyChangedMask | cameraTriggerChangedMask)); QCOMPARE(_multiSpy->pullIntFromSignalIndex(lastSequenceNumberChangedIndex), lastSeq - 2); - _complexItem->setDirty(false); + _surveyItem->setDirty(false); _multiSpy->clearAllSignals(); // Turn on camera triggering and make sure things go back to previous count - _complexItem->setProperty("cameraTrigger", true); + _surveyItem->setProperty("cameraTrigger", true); QVERIFY(_multiSpy->checkOnlySignalByMask(lastSequenceNumberChangedMask | dirtyChangedMask | cameraTriggerChangedMask)); QCOMPARE(_multiSpy->pullIntFromSignalIndex(lastSequenceNumberChangedIndex), lastSeq); } diff --git a/src/MissionManager/ComplexMissionItemTest.h b/src/MissionManager/SurveyMissionItemTest.h similarity index 94% rename from src/MissionManager/ComplexMissionItemTest.h rename to src/MissionManager/SurveyMissionItemTest.h index a2524399cfcb38f88fac7c3dfe02845ccb70a8cb..9da27b567332365e1aa7646501f6a9ea15948899 100644 --- a/src/MissionManager/ComplexMissionItemTest.h +++ b/src/MissionManager/SurveyMissionItemTest.h @@ -8,8 +8,8 @@ ****************************************************************************/ -#ifndef ComplexMissionItemTest_H -#define ComplexMissionItemTest_H +#ifndef SurveyMissionItemTest_H +#define SurveyMissionItemTest_H #include "UnitTest.h" #include "TCPLink.h" @@ -19,12 +19,12 @@ #include /// Unit test for SimpleMissionItem -class ComplexMissionItemTest : public UnitTest +class SurveyMissionItemTest : public UnitTest { Q_OBJECT public: - ComplexMissionItemTest(void); + SurveyMissionItemTest(void); protected: void init(void) final; @@ -95,7 +95,8 @@ private: const char* _rgComplexMissionItemSignals[_cComplexMissionItemSignals]; MultiSignalSpy* _multiSpy; - SurveyMissionItem* _complexItem; + SurveyMissionItem* _surveyItem; + QGCMapPolygon* _mapPolygon; QList _polyPoints; }; diff --git a/src/PlanView/SurveyMapVisual.qml b/src/PlanView/SurveyMapVisual.qml index 18c16c525faaa8a425c05d21e2bdab9daffacad4..00d1d511288ad03b49a4ca6e72980c51b482348d 100644 --- a/src/PlanView/SurveyMapVisual.qml +++ b/src/PlanView/SurveyMapVisual.qml @@ -25,56 +25,31 @@ Item { property var map ///< Map control to place item in property var _missionItem: object - property var _polygon - property var _grid + property var _mapPolygon: object.mapPolygon + property var _gridComponent property var _entryCoordinate property var _exitCoordinate - property var _dragHandles - property var _splitHandles signal clicked(int sequenceNumber) function _addVisualElements() { - _polygon = polygonComponent.createObject(map) - _grid = gridComponent.createObject(map) + _gridComponent = gridComponent.createObject(map) _entryCoordinate = entryPointComponent.createObject(map) _exitCoordinate = exitPointComponent.createObject(map) - map.addMapItem(_polygon) - map.addMapItem(_grid) + map.addMapItem(_gridComponent) map.addMapItem(_entryCoordinate) map.addMapItem(_exitCoordinate) } function _destroyVisualElements() { - _polygon.destroy() - _grid.destroy() + _gridComponent.destroy() _entryCoordinate.destroy() _exitCoordinate.destroy() } - function _addDragHandles() { - if (!_dragHandles) { - _dragHandles = dragHandlesComponent.createObject(map) - } - if (!_splitHandles) { - _splitHandles = splitHandlesComponent.createObject(map) - } - } - - function _destroyDragHandles() { - if (_dragHandles) { - _dragHandles.destroy() - _dragHandles = undefined - } - if (_splitHandles) { - _splitHandles.destroy() - _splitHandles = undefined - } - } - /// Add an initial 4 sided polygon if there is none function _addInitialPolygon() { - if (_missionItem.polygonPath.length < 3) { + if (_mapPolygon.count < 3) { // Initial polygon is inset to take 2/3rds space var rect = Qt.rect(map.centerViewport.x, map.centerViewport.y, map.centerViewport.width, map.centerViewport.height) console.log(map.centerViewport) @@ -87,46 +62,44 @@ Item { var topRight = Qt.point(rect.x + rect.width, rect.y) var bottomLeft = Qt.point(rect.x, rect.y + rect.height) var bottomRight = Qt.point(rect.x + rect.width, rect.y + rect.height) - _missionItem.addPolygonCoordinate(map.toCoordinate(topLeft, false /* clipToViewPort */)) - _missionItem.addPolygonCoordinate(map.toCoordinate(topRight, false /* clipToViewPort */)) - _missionItem.addPolygonCoordinate(map.toCoordinate(bottomRight, false /* clipToViewPort */)) - _missionItem.addPolygonCoordinate(map.toCoordinate(bottomLeft, false /* clipToViewPort */)) + _mapPolygon.appendVertex(map.toCoordinate(topLeft, false /* clipToViewPort */)) + _mapPolygon.appendVertex(map.toCoordinate(topRight, false /* clipToViewPort */)) + _mapPolygon.appendVertex(map.toCoordinate(bottomRight, false /* clipToViewPort */)) + _mapPolygon.appendVertex(map.toCoordinate(bottomLeft, false /* clipToViewPort */)) } } Component.onCompleted: { _addInitialPolygon() _addVisualElements() - if (_missionItem.isCurrentItem) { - _addDragHandles() - } } Component.onDestruction: { _destroyVisualElements() - _destroyDragHandles() } - Connections { - target: _missionItem + QGCMapPolygonVisuals { + id: mapPolygonVisuals + mapControl: map + mapPolygon: _mapPolygon - onIsCurrentItemChanged: { + Component.onCompleted: { + mapPolygonVisuals.addVisuals() if (_missionItem.isCurrentItem) { - _addDragHandles() - } else { - _destroyDragHandles() + mapPolygonVisuals.addHandles() } } - } - // Survey area polygon - Component { - id: polygonComponent + Connections { + target: _missionItem - MapPolygon { - color: "green" - opacity: 0.5 - path: _missionItem.polygonPath + onIsCurrentItemChanged: { + if (_missionItem.isCurrentItem) { + mapPolygonVisuals.addHandles() + } else { + mapPolygonVisuals.removeHandles() + } + } } } @@ -180,148 +153,4 @@ Item { } } } - - Component { - id: splitHandleComponent - - MapQuickItem { - id: mapQuickItem - anchorPoint.x: dragHandle.width / 2 - anchorPoint.y: dragHandle.height / 2 - z: QGroundControl.zOrderMapItems + 1 - - property int vertexIndex - - sourceItem: Rectangle { - id: dragHandle - width: ScreenTools.defaultFontPixelHeight * 1.5 - height: width - radius: width / 2 - color: "white" - opacity: .50 - - QGCLabel { - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - text: "+" - } - - QGCMouseArea { - fillItem: parent - onClicked: _missionItem.splitPolygonSegment(mapQuickItem.vertexIndex) - } - } - } - } - - Component { - id: splitHandlesComponent - - Repeater { - model: _missionItem.polygonPath - - delegate: Item { - property var _splitHandle - property var _vertices: _missionItem.polygonPath - - function _setHandlePosition() { - var nextIndex = index + 1 - if (nextIndex > _vertices.length - 1) { - nextIndex = 0 - } - var distance = _vertices[index].distanceTo(_vertices[nextIndex]) - var azimuth = _vertices[index].azimuthTo(_vertices[nextIndex]) - _splitHandle.coordinate = _vertices[index].atDistanceAndAzimuth(distance / 2, azimuth) - } - - Component.onCompleted: { - _splitHandle = splitHandleComponent.createObject(map) - _splitHandle.vertexIndex = index - _setHandlePosition() - map.addMapItem(_splitHandle) - } - - Component.onDestruction: { - if (_splitHandle) { - _splitHandle.destroy() - } - } - } - } - } - - // Control which is used to drag polygon vertices - Component { - id: dragAreaComponent - - MissionItemIndicatorDrag { - id: dragArea - - property int polygonVertex - - property bool _creationComplete: false - - Component.onCompleted: _creationComplete = true - - onItemCoordinateChanged: { - if (_creationComplete) { - // During component creation some bad coordinate values got through which screws up polygon draw - _missionItem.adjustPolygonCoordinate(polygonVertex, itemCoordinate) - } - } - - onClicked: _missionItem.removePolygonVertex(polygonVertex) - } - } - - Component { - id: dragHandleComponent - - MapQuickItem { - id: mapQuickItem - anchorPoint.x: dragHandle.width / 2 - anchorPoint.y: dragHandle.height / 2 - z: QGroundControl.zOrderMapItems + 2 - - sourceItem: Rectangle { - id: dragHandle - width: ScreenTools.defaultFontPixelHeight * 1.5 - height: width - radius: width / 2 - color: "white" - opacity: .90 - } - } - } - - // Add all polygon vertex drag handles to the map - Component { - id: dragHandlesComponent - - Repeater { - model: _missionItem.polygonModel - - delegate: Item { - property var _visuals: [ ] - - Component.onCompleted: { - var dragHandle = dragHandleComponent.createObject(map) - dragHandle.coordinate = Qt.binding(function() { return object.coordinate }) - map.addMapItem(dragHandle) - var dragArea = dragAreaComponent.createObject(map, { "itemIndicator": dragHandle, "itemCoordinate": object.coordinate }) - dragArea.polygonVertex = Qt.binding(function() { return index }) - _visuals.push(dragHandle) - _visuals.push(dragArea) - } - - Component.onDestruction: { - for (var i=0; i<_visuals.length; i++) { - _visuals[i].destroy() - } - _visuals = [ ] - } - } - } - } } - diff --git a/src/QmlControls/QGroundControl.Controls.qmldir b/src/QmlControls/QGroundControl.Controls.qmldir index dbd7b9d671f96adb1ac75599f7eb8e019f6b900a..11503bb22a357c0e11c247ed9e62c72c6db792f2 100644 --- a/src/QmlControls/QGroundControl.Controls.qmldir +++ b/src/QmlControls/QGroundControl.Controls.qmldir @@ -39,6 +39,7 @@ QGCGroupBox 1.0 QGCGroupBox.qml QGCLabel 1.0 QGCLabel.qml QGCListView 1.0 QGCListView.qml QGCMapLabel 1.0 QGCMapLabel.qml +QGCMapPolygonVisuals 1.0 QGCMapPolygonVisuals.qml QGCMouseArea 1.0 QGCMouseArea.qml QGCMovableItem 1.0 QGCMovableItem.qml QGCPipable 1.0 QGCPipable.qml diff --git a/src/qgcunittest/UnitTestList.cc b/src/qgcunittest/UnitTestList.cc index 61a11dd1e0828071f6c92511b14f560369c36b2b..92e8b39e9e14733f3d92cd7f079b5ac243dddbe6 100644 --- a/src/qgcunittest/UnitTestList.cc +++ b/src/qgcunittest/UnitTestList.cc @@ -20,7 +20,7 @@ #include "MessageBoxTest.h" #include "MissionItemTest.h" #include "SimpleMissionItemTest.h" -#include "ComplexMissionItemTest.h" +#include "SurveyMissionItemTest.h" #include "MissionControllerTest.h" #include "MissionManagerTest.h" #include "RadioConfigTest.h" @@ -61,5 +61,5 @@ UT_REGISTER_TEST(SendMavCommandTest) //UT_REGISTER_TEST(FileManagerTest) // Needs to be update for latest changes -//UT_REGISTER_TEST(ComplexMissionItemTest) +//UT_REGISTER_TEST(SurveyMissionItemTest) //UT_REGISTER_TEST(MavlinkLogTest)