From 28ebbf562da0aa72a652dc1f69d84f657a3481b4 Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Mon, 5 Jun 2017 14:47:13 -0700 Subject: [PATCH] Settable entry location --- src/MissionManager/Survey.SettingsGroup.json | 10 + src/MissionManager/SurveyMissionItem.cc | 218 +++++++++++++++++-- src/MissionManager/SurveyMissionItem.h | 18 ++ src/PlanView/SurveyItemEditor.qml | 14 ++ 4 files changed, 236 insertions(+), 24 deletions(-) diff --git a/src/MissionManager/Survey.SettingsGroup.json b/src/MissionManager/Survey.SettingsGroup.json index 59bbeac39..aaf1e28ba 100644 --- a/src/MissionManager/Survey.SettingsGroup.json +++ b/src/MissionManager/Survey.SettingsGroup.json @@ -24,6 +24,8 @@ "shortDescription": "Angle for parallel lines of grid.", "type": "double", "units": "deg", + "min": -360.0, + "max": 360.0, "decimalPlaces": 1, "defaultValue": 0 }, @@ -153,5 +155,13 @@ "shortDescription": "Camera selected for Survey.", "type": "string", "defaultValue": "" +}, +{ + "name": "GridEntryLocation", + "shortDescription": "Location for entry point into survey area", + "type": "uint32", + "enumStrings": "Top Left, Top Right, Bottom Left, Bottom Right", + "enumValues": "0,1,2,3", + "defaultValue": 0 } ] diff --git a/src/MissionManager/SurveyMissionItem.cc b/src/MissionManager/SurveyMissionItem.cc index 5d312e276..f79836fd8 100644 --- a/src/MissionManager/SurveyMissionItem.cc +++ b/src/MissionManager/SurveyMissionItem.cc @@ -26,6 +26,7 @@ const char* SurveyMissionItem::_jsonGridAltitudeKey = "altitude"; const char* SurveyMissionItem::_jsonGridAltitudeRelativeKey = "relativeAltitude"; const char* SurveyMissionItem::_jsonGridAngleKey = "angle"; const char* SurveyMissionItem::_jsonGridSpacingKey = "spacing"; +const char* SurveyMissionItem::_jsonGridEntryLocationKey = "entryLocation"; const char* SurveyMissionItem::_jsonTurnaroundDistKey = "turnAroundDistance"; const char* SurveyMissionItem::_jsonCameraTriggerDistanceKey = "cameraTriggerDistance"; const char* SurveyMissionItem::_jsonCameraTriggerInTurnaroundKey = "cameraTriggerInTurnaround"; @@ -51,6 +52,7 @@ const char* SurveyMissionItem::gridAltitudeName = "GridAltitude"; const char* SurveyMissionItem::gridAltitudeRelativeName = "GridAltitudeRelative"; const char* SurveyMissionItem::gridAngleName = "GridAngle"; const char* SurveyMissionItem::gridSpacingName = "GridSpacing"; +const char* SurveyMissionItem::gridEntryLocationName = "GridEntryLocation"; const char* SurveyMissionItem::turnaroundDistName = "TurnaroundDist"; const char* SurveyMissionItem::cameraTriggerDistanceName = "CameraTriggerDistance"; const char* SurveyMissionItem::cameraTriggerInTurnaroundName = "CameraTriggerInTurnaround"; @@ -87,6 +89,7 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent) , _gridAltitudeRelativeFact (settingsGroup, _metaDataMap[gridAltitudeRelativeName]) , _gridAngleFact (settingsGroup, _metaDataMap[gridAngleName]) , _gridSpacingFact (settingsGroup, _metaDataMap[gridSpacingName]) + , _gridEntryLocationFact (settingsGroup, _metaDataMap[gridEntryLocationName]) , _turnaroundDistFact (settingsGroup, _metaDataMap[turnaroundDistName]) , _cameraTriggerDistanceFact (settingsGroup, _metaDataMap[cameraTriggerDistanceName]) , _cameraTriggerInTurnaroundFact (settingsGroup, _metaDataMap[cameraTriggerInTurnaroundName]) @@ -112,6 +115,7 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent) connect(&_gridSpacingFact, &Fact::valueChanged, this, &SurveyMissionItem::_generateGrid); connect(&_gridAngleFact, &Fact::valueChanged, this, &SurveyMissionItem::_generateGrid); + connect(&_gridEntryLocationFact, &Fact::valueChanged, this, &SurveyMissionItem::_generateGrid); connect(&_turnaroundDistFact, &Fact::valueChanged, this, &SurveyMissionItem::_generateGrid); connect(&_cameraTriggerDistanceFact, &Fact::valueChanged, this, &SurveyMissionItem::_generateGrid); connect(&_cameraTriggerInTurnaroundFact, &Fact::valueChanged, this, &SurveyMissionItem::_generateGrid); @@ -220,6 +224,7 @@ void SurveyMissionItem::save(QJsonArray& missionItems) gridObject[_jsonGridAltitudeRelativeKey] = _gridAltitudeRelativeFact.rawValue().toBool(); gridObject[_jsonGridAngleKey] = _gridAngleFact.rawValue().toDouble(); gridObject[_jsonGridSpacingKey] = _gridSpacingFact.rawValue().toDouble(); + gridObject[_jsonGridEntryLocationKey] = _gridSpacingFact.rawValue().toDouble(); gridObject[_jsonTurnaroundDistKey] = _turnaroundDistFact.rawValue().toDouble(); saveObject[_jsonGridObjectKey] = gridObject; @@ -322,6 +327,7 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumbe { _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true }, { _jsonGridAngleKey, QJsonValue::Double, true }, { _jsonGridSpacingKey, QJsonValue::Double, true }, + { _jsonGridEntryLocationKey, QJsonValue::Double, false }, { _jsonTurnaroundDistKey, QJsonValue::Double, true }, }; QJsonObject gridObject = v2Object[_jsonGridObjectKey].toObject(); @@ -333,6 +339,11 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumbe _gridSpacingFact.setRawValue (gridObject[_jsonGridSpacingKey].toDouble()); _turnaroundDistFact.setRawValue (gridObject[_jsonTurnaroundDistKey].toDouble()); _cameraTriggerDistanceFact.setRawValue (v2Object[_jsonCameraTriggerDistanceKey].toDouble()); + if (gridObject.contains(_jsonGridEntryLocationKey)) { + _gridEntryLocationFact.setRawValue(gridObject[_jsonGridEntryLocationKey].toDouble()); + } else { + _gridEntryLocationFact.setRawValue(_gridEntryLocationFact.rawDefaultValue()); + } if (!_manualGridFact.rawValue().toBool()) { if (!v2Object.contains(_jsonCameraObjectKey)) { @@ -444,6 +455,29 @@ void SurveyMissionItem::_convertTransectToGeo(const QList>& trans } } +/// Reverse the order of the transects. First transect becomes last and so forth. +void SurveyMissionItem::_reverseTransectOrder(QList>& transects) +{ + QList> rgReversedTransects; + for (int i=transects.count() - 1; i>=0; i--) { + rgReversedTransects.append(transects[i]); + } + transects = rgReversedTransects; +} + +/// Reverse the order of all points withing each transect, First point becomes last and so forth. +void SurveyMissionItem::_reverseInternalTransectPoints(QList>& transects) +{ + for (int i=0; i rgReversedCoords; + QList& rgOriginalCoords = transects[i]; + for (int j=rgOriginalCoords.count()-1; j>=0; j--) { + rgReversedCoords.append(rgOriginalCoords[j]); + } + transects[i] = rgReversedCoords; + } +} + /// Reorders the transects such that the first transect is the shortest distance to the specified coordinate /// and the first point within that transect is the shortest distance to the specified coordinate. /// @param distanceCoord Coordinate to measure distance against @@ -467,27 +501,18 @@ void SurveyMissionItem::_optimizeTransectsForShortestDistance(const QGeoCoordina if (shortestIndex > 1) { // We need to reverse the order of segments - QList> rgReversedTransects; - for (int i=transects.count() - 1; i>=0; i--) { - rgReversedTransects.append(transects[i]); - } - transects = rgReversedTransects; + _reverseTransectOrder(transects); } if (shortestIndex & 1) { // We need to reverse the points within each segment - for (int i=0; i rgReversedCoords; - QList& rgOriginalCoords = transects[i]; - for (int j=rgOriginalCoords.count()-1; j>=0; j--) { - rgReversedCoords.append(rgOriginalCoords[j]); - } - transects[i] = rgReversedCoords; - } + _reverseInternalTransectPoints(transects); } } void SurveyMissionItem::_appendGridPointsFromTransects(QList>& rgTransectSegments) { + qCDebug(SurveyMissionItemLog) << "Entry point _appendGridPointsFromTransects" << rgTransectSegments.first().first(); + for (int i=0; i SurveyMissionItem::_convexPolygon(const QList& polygon) return workPolygon.mid(1, convexCount); } +/// Returns true if the current grid angle generates north/south oriented transects +bool SurveyMissionItem::_gridAngleIsNorthSouthTransects() +{ + // Grid angle ranges from -360<->360 + double gridAngle = qAbs(_gridAngleFact.rawValue().toDouble()); + return gridAngle < 45.0 || (gridAngle > 360.0 - 45.0) || (gridAngle > 90.0 + 45.0 && gridAngle < 270.0 - 45.0); +} + +void SurveyMissionItem::_adjustTransectsToEntryPointLocation(QList>& transects) +{ + if (transects.count() == 0) { + return; + } + + // First determine what location the current entry point is at + + QGeoCoordinate& firstTransectEntry = transects.first().first(); + QGeoCoordinate& firstTransectExit = transects.first().last(); + QGeoCoordinate& lastTransectExit = transects.last().last(); + + bool northSouthTransects = _gridAngleIsNorthSouthTransects(); + bool entryPointBottom; + bool entryPointLeft; + + qCDebug(SurveyMissionItemLog) << "Original entry point" << transects.first().first(); + qCDebug(SurveyMissionItemLog) << "northSouthTransects" << northSouthTransects; + + if (northSouthTransects) { + double firstTransectAzimuth = firstTransectEntry.azimuthTo(firstTransectExit); + qCDebug(SurveyMissionItemLog) << "firstTransectAzimuth" << firstTransectAzimuth; + entryPointBottom = (firstTransectAzimuth >= 0.0 && firstTransectAzimuth < 90.0) || (firstTransectAzimuth > 270.0 && firstTransectAzimuth <= 360.0); + qCDebug(SurveyMissionItemLog) << (entryPointBottom ? "Entry point is at bottom" : "Entry point is at top"); + + double entryToExitAzimuth = firstTransectEntry.azimuthTo(lastTransectExit); + qCDebug(SurveyMissionItemLog) << "entryToExitAzimuth" << entryToExitAzimuth; + entryPointLeft = entryToExitAzimuth <= 180.0; + qCDebug(SurveyMissionItemLog) << (entryPointLeft ? "Entry point is at left" : "Entry point is at right"); + } else { + double firstTransectAzimuth = firstTransectEntry.azimuthTo(firstTransectExit); + qCDebug(SurveyMissionItemLog) << "firstTransectAzimuth" << firstTransectAzimuth; + entryPointLeft = firstTransectAzimuth <= 180.0; + qCDebug(SurveyMissionItemLog) << (entryPointLeft ? "Entry point is at left" : "Entry point is at right"); + + double entryToExitAzimuth = firstTransectEntry.azimuthTo(lastTransectExit); + qCDebug(SurveyMissionItemLog) << "entryToExitAzimuth" << entryToExitAzimuth; + entryPointBottom = (entryToExitAzimuth >= 0.0 && entryToExitAzimuth < 90.0) || (entryToExitAzimuth > 270.0 && entryToExitAzimuth <= 360.0); + qCDebug(SurveyMissionItemLog) << (entryPointBottom ? "Entry point is at bottom" : "Entry point is at top"); + } + + // Now adjust the transects such that the entry point matches the requested location + + int entryLocation = _gridEntryLocationFact.rawValue().toInt(); + bool reverseTransects; + bool reversePoints; + if (northSouthTransects) { + reversePoints = ((entryLocation == EntryLocationTopLeft || entryLocation == EntryLocationTopRight) && entryPointBottom) || + ((entryLocation == EntryLocationBottomLeft || entryLocation == EntryLocationBottomRight) && !entryPointBottom); + reverseTransects = ((entryLocation == EntryLocationTopRight || entryLocation == EntryLocationBottomRight) && entryPointLeft) || + ((entryLocation == EntryLocationTopLeft || entryLocation == EntryLocationBottomLeft) && !entryPointLeft); + } else { + reverseTransects = ((entryLocation == EntryLocationTopLeft || entryLocation == EntryLocationTopRight) && entryPointBottom) || + ((entryLocation == EntryLocationBottomLeft || entryLocation == EntryLocationBottomRight) && !entryPointBottom); + reversePoints = ((entryLocation == EntryLocationTopRight || entryLocation == EntryLocationBottomRight) && entryPointLeft) || + ((entryLocation == EntryLocationTopLeft || entryLocation == EntryLocationBottomLeft) && !entryPointLeft); + } + if (reversePoints) { + qCDebug(SurveyMissionItemLog) << "Reverse Points"; + _reverseInternalTransectPoints(transects); + } + if (reverseTransects) { + // The only way we should end up here is if there is a bug in the original grid line generation + qCDebug(SurveyMissionItemLog) << "Not Reverse Transects"; + //_reverseTransectOrder(transects); + } + qCDebug(SurveyMissionItemLog) << "Modified entry point" << transects.first().first(); +} + void SurveyMissionItem::_generateGrid(void) { if (_ignoreRecalc) { @@ -608,9 +710,8 @@ void SurveyMissionItem::_generateGrid(void) int cameraShots = 0; cameraShots += _gridGenerator(polygonPoints, transectSegments, false /* refly */); _convertTransectToGeo(transectSegments, tangentOrigin, _transectSegments); - //_optimizeTransectsForShortestDistance(?, _transectSegments); + _adjustTransectsToEntryPointLocation(_transectSegments); _appendGridPointsFromTransects(_transectSegments); - qDebug() << _transectSegments.count(); if (_refly90Degrees) { QVariantList reflyPointsGeo; @@ -678,7 +779,7 @@ void SurveyMissionItem::_updateCoordinateAltitude(void) QPointF SurveyMissionItem::_rotatePoint(const QPointF& point, const QPointF& origin, double angle) { QPointF rotated; - double radians = (M_PI / 180.0) * angle; + double radians = (M_PI / 180.0) * -angle; rotated.setX(((point.x() - origin.x()) * cos(radians)) - ((point.y() - origin.y()) * sin(radians)) + origin.x()); rotated.setY(((point.x() - origin.x()) * sin(radians)) + ((point.y() - origin.y()) * cos(radians)) + origin.y()); @@ -794,13 +895,28 @@ void SurveyMissionItem::_adjustLineDirection(const QList& lineList, QLis } } +double SurveyMissionItem::_clampGridAngle90(double gridAngle) +{ + // Clamp grid angle to -90<->90. This prevents transects from being rotated to a reversed order. + if (gridAngle > 90.0) { + gridAngle -= 180.0; + } else if (gridAngle < -90.0) { + gridAngle += 180; + } + return gridAngle; +} + int SurveyMissionItem::_gridGenerator(const QList& polygonPoints, QList>& transectSegments, bool refly) { int cameraShots = 0; - double gridAngle = _gridAngleFact.rawValue().toDouble() + (refly ? 90 : 0); + double gridAngle = _gridAngleFact.rawValue().toDouble(); double gridSpacing = _gridSpacingFact.rawValue().toDouble(); + gridAngle = _clampGridAngle90(gridAngle); + gridAngle += refly ? 90 : 0; + qCDebug(SurveyMissionItemLog) << "Clamped grid angle" << gridAngle; + qCDebug(SurveyMissionItemLog) << "SurveyMissionItem::_gridGenerator gridSpacing:gridAngle:refly" << gridSpacing << gridAngle << refly; transectSegments.clear(); @@ -830,16 +946,70 @@ int SurveyMissionItem::_gridGenerator(const QList& polygonPoints, QLis // Create set of rotated parallel lines within the expanded bounding rect. Make the lines larger than the // bounding box to guarantee intersection. + QList lineList; - float x = largeBoundRect.topLeft().x() - (gridSpacing / 2); - while (x < largeBoundRect.bottomRight().x()) { - float yTop = largeBoundRect.topLeft().y() - 100.0; - float yBottom = largeBoundRect.bottomRight().y() + 100.0; + bool northSouthTransects = _gridAngleIsNorthSouthTransects(); + int entryLocation = _gridEntryLocationFact.rawValue().toInt(); + + if (northSouthTransects) { + qCDebug(SurveyMissionItemLog) << "Clamped grid angle" << gridAngle; + if (entryLocation == EntryLocationTopLeft || entryLocation == EntryLocationBottomLeft) { + // Generate transects from left to right + qCDebug(SurveyMissionItemLog) << "Generate left to right"; + float x = largeBoundRect.topLeft().x() - (gridSpacing / 2); + while (x < largeBoundRect.bottomRight().x()) { + float yTop = largeBoundRect.topLeft().y() - 100.0; + float yBottom = largeBoundRect.bottomRight().y() + 100.0; + + lineList += QLineF(_rotatePoint(QPointF(x, yTop), center, gridAngle), _rotatePoint(QPointF(x, yBottom), center, gridAngle)); + qCDebug(SurveyMissionItemLog) << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")"; + + x += gridSpacing; + } + } else { + // Generate transects from right to left + qCDebug(SurveyMissionItemLog) << "Generate right to left"; + float x = largeBoundRect.topRight().x() + (gridSpacing / 2); + while (x > largeBoundRect.bottomLeft().x()) { + float yTop = largeBoundRect.topRight().y() - 100.0; + float yBottom = largeBoundRect.bottomLeft().y() + 100.0; - lineList += QLineF(_rotatePoint(QPointF(x, yTop), center, gridAngle), _rotatePoint(QPointF(x, yBottom), center, gridAngle)); - qCDebug(SurveyMissionItemLog) << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")"; + lineList += QLineF(_rotatePoint(QPointF(x, yTop), center, gridAngle), _rotatePoint(QPointF(x, yBottom), center, gridAngle)); + qCDebug(SurveyMissionItemLog) << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")"; - x += gridSpacing; + x -= gridSpacing; + } + } + } else { + gridAngle = _clampGridAngle90(gridAngle - 90.0); + qCDebug(SurveyMissionItemLog) << "Clamped grid angle" << gridAngle; + if (entryLocation == EntryLocationTopLeft || entryLocation == EntryLocationTopRight) { + // Generate transects from top to bottom + qCDebug(SurveyMissionItemLog) << "Generate top to bottom"; + float y = largeBoundRect.bottomLeft().y() + (gridSpacing / 2); + while (y > largeBoundRect.topRight().y()) { + float xLeft = largeBoundRect.bottomLeft().x() - 100.0; + float xRight = largeBoundRect.topRight().x() + 100.0; + + lineList += QLineF(_rotatePoint(QPointF(xLeft, y), center, gridAngle), _rotatePoint(QPointF(xRight, y), center, gridAngle)); + qCDebug(SurveyMissionItemLog) << "y:xLeft:xRight" << y << xLeft << xRight << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")"; + + y -= gridSpacing; + } + } else { + // Generate transects from bottom to top + qCDebug(SurveyMissionItemLog) << "Generate bottom to top"; + float y = largeBoundRect.topLeft().y() - (gridSpacing / 2); + while (y < largeBoundRect.bottomRight().y()) { + float xLeft = largeBoundRect.topLeft().x() - 100.0; + float xRight = largeBoundRect.bottomRight().x() + 100.0; + + lineList += QLineF(_rotatePoint(QPointF(xLeft, y), center, gridAngle), _rotatePoint(QPointF(xRight, y), center, gridAngle)); + qCDebug(SurveyMissionItemLog) << "y:xLeft:xRight" << y << xLeft << xRight << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")"; + + y += gridSpacing; + } + } } // Now intersect the lines with the polygon diff --git a/src/MissionManager/SurveyMissionItem.h b/src/MissionManager/SurveyMissionItem.h index ce8496f11..2b486d7a9 100644 --- a/src/MissionManager/SurveyMissionItem.h +++ b/src/MissionManager/SurveyMissionItem.h @@ -30,6 +30,7 @@ public: Q_PROPERTY(Fact* gridAltitudeRelative READ gridAltitudeRelative CONSTANT) Q_PROPERTY(Fact* gridAngle READ gridAngle CONSTANT) Q_PROPERTY(Fact* gridSpacing READ gridSpacing CONSTANT) + Q_PROPERTY(Fact* gridEntryLocation READ gridEntryLocation CONSTANT) Q_PROPERTY(Fact* turnaroundDist READ turnaroundDist CONSTANT) Q_PROPERTY(Fact* cameraTriggerDistance READ cameraTriggerDistance CONSTANT) Q_PROPERTY(Fact* cameraTriggerInTurnaround READ cameraTriggerInTurnaround CONSTANT) @@ -65,6 +66,7 @@ public: Fact* gridAltitudeRelative (void) { return &_gridAltitudeRelativeFact; } Fact* gridAngle (void) { return &_gridAngleFact; } Fact* gridSpacing (void) { return &_gridSpacingFact; } + Fact* gridEntryLocation (void) { return &_gridEntryLocationFact; } Fact* turnaroundDist (void) { return &_turnaroundDistFact; } Fact* cameraTriggerDistance (void) { return &_cameraTriggerDistanceFact; } Fact* cameraTriggerInTurnaround (void) { return &_cameraTriggerInTurnaroundFact; } @@ -135,6 +137,7 @@ public: static const char* gridAltitudeRelativeName; static const char* gridAngleName; static const char* gridSpacingName; + static const char* gridEntryLocationName; static const char* turnaroundDistName; static const char* cameraTriggerDistanceName; static const char* cameraTriggerInTurnaroundName; @@ -175,6 +178,14 @@ private: CameraTriggerHoverAndCapture }; + // Must match json spec for GridEntryLocation + enum EntryLocation { + EntryLocationTopLeft, + EntryLocationTopRight, + EntryLocationBottomLeft, + EntryLocationBottomRight, + }; + void _setExitCoordinate(const QGeoCoordinate& coordinate); void _generateGrid(void); void _updateCoordinateAltitude(void); @@ -203,6 +214,11 @@ private: qreal _dp(QPointF pt1, QPointF pt2); void _swapPoints(QList& points, int index1, int index2); QList _convexPolygon(const QList& polygon); + void _reverseTransectOrder(QList>& transects); + void _reverseInternalTransectPoints(QList>& transects); + void _adjustTransectsToEntryPointLocation(QList>& transects); + bool _gridAngleIsNorthSouthTransects(); + double _clampGridAngle90(double gridAngle); int _sequenceNumber; bool _dirty; @@ -230,6 +246,7 @@ private: SettingsFact _gridAltitudeRelativeFact; SettingsFact _gridAngleFact; SettingsFact _gridSpacingFact; + SettingsFact _gridEntryLocationFact; SettingsFact _turnaroundDistFact; SettingsFact _cameraTriggerDistanceFact; SettingsFact _cameraTriggerInTurnaroundFact; @@ -251,6 +268,7 @@ private: static const char* _jsonGridAltitudeRelativeKey; static const char* _jsonGridAngleKey; static const char* _jsonGridSpacingKey; + static const char* _jsonGridEntryLocationKey; static const char* _jsonTurnaroundDistKey; static const char* _jsonCameraTriggerDistanceKey; static const char* _jsonCameraTriggerInTurnaroundKey; diff --git a/src/PlanView/SurveyItemEditor.qml b/src/PlanView/SurveyItemEditor.qml index 9cc905257..03b507ec5 100644 --- a/src/PlanView/SurveyItemEditor.qml +++ b/src/PlanView/SurveyItemEditor.qml @@ -439,6 +439,13 @@ Rectangle { Layout.fillWidth: true } + QGCLabel { text: qsTr("Entry") } + FactComboBox { + fact: missionItem.gridEntryLocation + indexModel: false + Layout.fillWidth: true + } + QGCCheckBox { text: qsTr("Refly at 90 degree offset") checked: missionItem.refly90Degrees @@ -543,6 +550,13 @@ Rectangle { fact: missionItem.turnaroundDist Layout.fillWidth: true } + QGCLabel { text: qsTr("Entry") } + FactComboBox { + fact: missionItem.gridEntryLocation + indexModel: false + Layout.fillWidth: true + } + QGCCheckBox { text: qsTr("Refly at 90 degree offset") -- 2.22.0