Commit be40a955 authored by Valentin Platzgummer's avatar Valentin Platzgummer

MeasurementItemEditor fixed

parent 3dfdeec9
......@@ -261,26 +261,20 @@
<file alias="QmlTest.qml">src/QmlControls/QmlTest.qml</file>
<file alias="RadioComponent.qml">src/AutoPilotPlugins/Common/RadioComponent.qml</file>
<file alias="SerialSettings.qml">src/ui/preferences/SerialSettings.qml</file>
<file alias="CircularGeneratorEditor.qml">src/WimaView/CircularGeneratorEditor.qml</file>
<file alias="QGroundControl/Controls/CircularGeneratorMapVisual.qml">src/WimaView/CircularGeneratorMapVisual.qml</file>
<file alias="CircularSurveyItemEditor.qml">src/WimaView/MeasurementItemEditor.qml</file>
<file alias="QGroundControl/Controls/CircularSurveyMapVisual.qml">src/WimaView/MeasurementItemMapVisual.qml</file>
<file alias="Wima/CoordinateIndicator.qml">src/WimaView/CoordinateIndicator.qml</file>
<file alias="Wima/CoordinateIndicatorDrag.qml">src/WimaView/CoordinateIndicatorDrag.qml</file>
<file alias="Wima/DragCoordinate.qml">src/WimaView/DragCoordinate.qml</file>
<file alias="LinearGeneratorEditor.qml">src/WimaView/LinearGeneratorEditor.qml</file>
<file alias="Wima/ProgressIndicator.qml">src/WimaView/ProgressIndicator.qml</file>
<file alias="Wima/qmldir">src/WimaView/Wima.qmldir</file>
<file alias="Wima/WimaAreaMapVisual.qml">src/WimaView/WimaAreaMapVisual.qml</file>
<file alias="Wima/WimaCorridorEditor.qml">src/WimaView/WimaCorridorEditor.qml</file>
<file alias="Wima/WimaItemEditor.qml">src/WimaView/WimaItemEditor.qml</file>
<file alias="Wima/WimaMapPolygonVisuals.qml">src/WimaView/WimaMapPolygonVisuals.qml</file>
<file alias="Wima/WimaMapVisual.qml">src/WimaView/WimaMapVisual.qml</file>
<file alias="Wima/WimaMeasurementAreaEditor.qml">src/WimaView/MeasurementAreaEditor.qml</file>
<file alias="Wima/WimaMeasurementAreaMapVisual.qml">src/WimaView/MeasurementAreaMapVisual.qml</file>
<file alias="Wima/WimaServiceAreaEditor.qml">src/WimaView/SafeAreaEditor.qml</file>
<file alias="Wima/WimaServiceAreaMapVisual.qml">src/WimaView/SafeAreaMapVisual.qml</file>
<file alias="Wima/WimaToolBar.qml">src/WimaView/WimaToolBar.qml</file>
<file alias="CircularGeneratorEditor.qml">src/MeasurementComplexItem/qml/CircularGeneratorEditor.qml</file>
<file alias="QGroundControl/Controls/CircularGeneratorMapVisual.qml">src/MeasurementComplexItem/qml/CircularGeneratorMapVisual.qml</file>
<file alias="MeasurementItemEditor.qml">src/MeasurementComplexItem/qml/MeasurementItemEditor.qml</file>
<file alias="QGroundControl/Controls/MeasurementItemMapVisual.qml">src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml</file>
<file alias="CoordinateIndicator.qml">src/MeasurementComplexItem/qml/CoordinateIndicator.qml</file>
<file alias="CoordinateIndicatorDrag.qml">src/MeasurementComplexItem/qml/CoordinateIndicatorDrag.qml</file>
<file alias="DragCoordinate.qml">src/MeasurementComplexItem/qml/DragCoordinate.qml</file>
<file alias="LinearGeneratorEditor.qml">src/MeasurementComplexItem/qml/LinearGeneratorEditor.qml</file>
<file alias="ProgressIndicator.qml">src/MeasurementComplexItem/qml/ProgressIndicator.qml</file>
<file alias="QGroundControl/Controls/GeoAreaVisualLoader.qml">src/MeasurementComplexItem/qml/GeoAreaVisualLoader.qml</file>
<file alias="MeasurementAreaEditor.qml">src/MeasurementComplexItem/qml/MeasurementAreaEditor.qml</file>
<file alias="MeasurementAreaMapVisual.qml">src/MeasurementComplexItem/qml/MeasurementAreaMapVisual.qml</file>
<file alias="SafeAreaEditor.qml">src/MeasurementComplexItem/qml/SafeAreaEditor.qml</file>
<file alias="SafeAreaMapVisual.qml">src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml</file>
<file alias="SetupParameterEditor.qml">src/VehicleSetup/SetupParameterEditor.qml</file>
<file alias="SetupView.qml">src/VehicleSetup/SetupView.qml</file>
<file alias="SimpleItemEditor.qml">src/PlanView/SimpleItemEditor.qml</file>
......@@ -295,6 +289,7 @@
<file alias="VibrationPage.qml">src/AnalyzeView/VibrationPage.qml</file>
<file alias="VirtualJoystick.qml">src/FlightDisplay/VirtualJoystick.qml</file>
<file alias="VTOLLandingPatternEditor.qml">src/PlanView/VTOLLandingPatternEditor.qml</file>
<file>src/MeasurementComplexItem/qml/GeoAreaEditorLoader.qml</file>
</qresource>
<qresource prefix="/FirstRunPromptDialogs">
<file alias="UnitsFirstRunPrompt.qml">src/FirstRunPromptDialogs/UnitsFirstRunPrompt.qml</file>
......@@ -352,9 +347,10 @@
<file alias="Video.SettingsGroup.json">src/Settings/Video.SettingsGroup.json</file>
<file alias="VTOLLandingPattern.FactMetaData.json">src/MissionManager/VTOLLandingPattern.FactMetaData.json</file>
<file alias="Wima.SettingsGroup.json">src/Settings/Wima.SettingsGroup.json</file>
<file>src/MeasurementComplexItem/json/CircularGenerator.SettingsGroup.json</file>
<file>src/MeasurementComplexItem/json/LinearGenerator.SettingsGroup.json</file>
<file>src/MeasurementComplexItem/json/MeasurementComplexItem.SettingsGroup.json</file>
<file alias="CircularGenerator.SettingsGroup.json">src/MeasurementComplexItem/json/CircularGenerator.SettingsGroup.json</file>
<file alias="LinearGenerator.SettingsGroup.json">src/MeasurementComplexItem/json/LinearGenerator.SettingsGroup.json</file>
<file alias="MeasurementComplexItem.SettingsGroup.json">src/MeasurementComplexItem/json/MeasurementComplexItem.SettingsGroup.json</file>
<file alias="MeasurementArea.SettingsGroup.json">src/MeasurementComplexItem/geometry/json/MeasurementArea.SettingsGroup.json</file>
</qresource>
<qresource prefix="/MockLink">
<file alias="APMArduSubMockLink.params">src/comm/APMArduSubMockLink.params</file>
......
......@@ -30,29 +30,11 @@ AreaData &AreaData::operator=(const AreaData &other) {
}
bool AreaData::insert(GeoArea *areaData) {
{
SafeArea *area = qobject_cast<SafeArea *>(areaData);
if (area != nullptr) {
if (Q_LIKELY(!this->_areaList.contains(area))) {
_areaList.append(area);
if (areaData != nullptr) {
if (Q_LIKELY(!this->_areaList.contains(areaData))) {
_areaList.append(areaData);
emit areaList();
return true;
} else {
return false;
}
}
}
{
MeasurementArea *area = qobject_cast<MeasurementArea *>(areaData);
if (area != nullptr) {
if (Q_LIKELY(!this->_areaList.contains(area))) {
_areaList.append(area);
emit areaList();
return true;
} else {
return false;
}
}
}
......@@ -111,7 +93,9 @@ bool AreaData::initialize(const QGeoCoordinate &bottomLeft,
auto *safeArea = getGeoArea<SafeArea *>(_areaList);
if (safeArea == nullptr) {
if (!insert(new SafeArea())) {
safeArea = new SafeArea(this);
if (!insert(safeArea)) {
safeArea->deleteLater();
qCCritical(AreaDataLog)
<< "initialize(): safeArea == nullptr, but insert() failed.";
return false;
......@@ -119,7 +103,9 @@ bool AreaData::initialize(const QGeoCoordinate &bottomLeft,
}
if (measurementArea == nullptr) {
if (!insert(new MeasurementArea())) {
measurementArea = new MeasurementArea(this);
if (!insert(measurementArea)) {
measurementArea->deleteLater();
qCCritical(AreaDataLog) << "initialize(): measurementArea == nullptr, "
"but insert() failed.";
return false;
......
......@@ -41,14 +41,15 @@ MeasurementComplexItem::MeasurementComplexItem(
const QString &kmlOrShpFile, QObject *parent)
: ComplexMissionItem(masterController, flyView, parent),
_masterController(masterController), _sequenceNumber(0),
_followTerrain(false),
_altitude(settingsGroup, _metaDataMap[altitudeName]), _state(STATE::IDLE),
_followTerrain(false), _state(STATE::IDLE),
_metaDataMap(FactMetaData::createMapFromJsonFile(
QStringLiteral(":/json/MeasurementComplexItem.SettingsGroup.json"),
this)),
_altitude(settingsGroup, _metaDataMap[altitudeName]),
_variant(settingsGroup, _metaDataMap[variantName]),
_areaData(new AreaData(this)), _editorData(new AreaData(this)),
_currentData(_areaData), _pWorker(new RoutingThread(this)) {
_pAreaData(new AreaData(this)), _pEditorData(new AreaData(this)),
_pCurrentData(_pAreaData), _pGenerator(nullptr),
_pWorker(new RoutingThread(this)) {
Q_UNUSED(kmlOrShpFile)
_editorQml = "qrc:/qml/MeasurementItemEditor.qml";
......@@ -61,7 +62,7 @@ MeasurementComplexItem::MeasurementComplexItem(
connect(this->_pWorker, &RoutingThread::result, this,
&MeasurementComplexItem::_storeRoutingData);
// Connect coordinate and exitCoordinate
// Connect coordinate and exitCoordinate.
connect(this, &MeasurementComplexItem::routeChanged,
[this] { emit this->coordinateChanged(this->coordinate()); });
connect(this, &MeasurementComplexItem::routeChanged,
......@@ -71,10 +72,14 @@ MeasurementComplexItem::MeasurementComplexItem(
this->exitCoordinateSameAsEntry());
});
// Connect complexDistance.
connect(this, &MeasurementComplexItem::routeChanged,
[this] { emit this->complexDistanceChanged(); });
// Register Generators.
auto lg = new routing::LinearGenerator(this->_areaData, this);
auto lg = new routing::LinearGenerator(this->_pAreaData, this);
registerGenerator(lg->name(), lg);
auto cg = new routing::CircularGenerator(this->_areaData, this);
auto cg = new routing::CircularGenerator(this->_pAreaData, this);
registerGenerator(cg->name(), cg);
qCritical() << "ToDo: _altitude connections missing.";
......@@ -86,10 +91,10 @@ MeasurementComplexItem::~MeasurementComplexItem() {}
void MeasurementComplexItem::reverseRoute() { _reverseRoute(); }
const AreaData *MeasurementComplexItem::areaData() const {
return this->_currentData;
return this->_pCurrentData;
}
AreaData *MeasurementComplexItem::areaData() { return this->_currentData; }
AreaData *MeasurementComplexItem::areaData() { return this->_pCurrentData; }
QVariantList MeasurementComplexItem::route() { return _route; }
......@@ -155,6 +160,24 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject,
return true;
}
double
MeasurementComplexItem::greatestDistanceTo(const QGeoCoordinate &other) const {
double d = -1 * std::numeric_limits<double>::infinity();
if (other.isValid()) {
if (this->_route.size() > 0) {
std::for_each(this->_route.cbegin(), this->_route.cend(),
[&d, &other](const QVariant &variant) {
auto vertex = variant.value<QGeoCoordinate>();
d = std::max(d, vertex.distanceTo(other));
});
}
} else {
qCDebug(MeasurementComplexItemLog)
<< "greatestDistanceTo(): invalid QGeoCoordinate: " << other;
}
return d;
}
bool MeasurementComplexItem::dirty() const { return _dirty; }
bool MeasurementComplexItem::isSimpleItem() const { return false; }
......@@ -202,6 +225,18 @@ double MeasurementComplexItem::maxAMSLAltitude() const {
return amslEntryAlt();
}
QString MeasurementComplexItem::commandDescription() const {
return QStringLiteral("Measurement");
}
QString MeasurementComplexItem::commandName() const {
return QStringLiteral("Measurement");
}
QString MeasurementComplexItem::abbreviation() const {
return QStringLiteral("M");
}
bool MeasurementComplexItem::specifiesCoordinate() const {
return _route.count() > 0;
}
......@@ -283,8 +318,12 @@ bool MeasurementComplexItem::_setGenerator(PtrGenerator newG) {
}
this->_pGenerator = newG;
connect(this->_pGenerator, &routing::GeneratorBase::generatorChanged, this,
&MeasurementComplexItem::_updateRoute);
if (this->_pGenerator != nullptr) {
connect(this->_pGenerator, &routing::GeneratorBase::generatorChanged,
this, &MeasurementComplexItem::_updateRoute);
}
emit generatorChanged();
if (!editing()) {
......@@ -321,14 +360,18 @@ bool MeasurementComplexItem::_calculating(MeasurementComplexItem::STATE state) {
return state == STATE::ROUTING;
}
bool MeasurementComplexItem::_editing(MeasurementComplexItem::STATE state) {
return state == STATE::EDITING;
}
bool MeasurementComplexItem::_ready(MeasurementComplexItem::STATE state) {
return state == STATE::IDLE;
}
void MeasurementComplexItem::_setAreaData(
MeasurementComplexItem::PtrAreaData data) {
if (_currentData != data) {
_currentData = data;
if (_pCurrentData != data) {
_pCurrentData = data;
emit areaDataChanged();
}
}
......@@ -340,10 +383,10 @@ bool MeasurementComplexItem::_updateRoute() {
this->_variantNames.clear();
emit variantNamesChanged();
if (this->_areaData->isValid()) {
if (this->_pAreaData->isValid()) {
// Prepare data.
auto origin = this->_areaData->origin();
auto origin = this->_pAreaData->origin();
origin.setAltitude(0);
if (!origin.isValid()) {
qCDebug(MeasurementComplexItemLog)
......@@ -353,7 +396,7 @@ bool MeasurementComplexItem::_updateRoute() {
// Convert safe area.
auto serviceArea =
getGeoArea<const SafeArea *>(*this->_areaData->areaList());
getGeoArea<const SafeArea *>(*this->_pAreaData->areaList());
auto geoSafeArea = serviceArea->coordinateList();
if (!(geoSafeArea.size() >= 3)) {
qCDebug(MeasurementComplexItemLog)
......@@ -378,7 +421,7 @@ bool MeasurementComplexItem::_updateRoute() {
snake::areaToEnu(origin, geoSafeArea, safeAreaENU);
// Create generator.
if (this->_pGenerator) {
if (this->_pGenerator != nullptr) {
routing::GeneratorBase::Generator g; // Transect generator.
if (this->_pGenerator->get(g)) {
// Start/Restart routing worker.
......@@ -491,6 +534,24 @@ void MeasurementComplexItem::setSequenceNumber(int sequenceNumber) {
QString MeasurementComplexItem::patternName() const { return name; }
double MeasurementComplexItem::complexDistance() const {
double d = 0;
if (this->_route.size() > 1) {
auto vertex = _route.first().value<QGeoCoordinate>();
std::for_each(this->_route.cbegin() + 1, this->_route.cend(),
[&vertex, &d](const QVariant &variant) {
auto otherVertex = variant.value<QGeoCoordinate>();
d += vertex.distanceTo(otherVertex);
vertex = otherVertex;
});
}
return d;
}
int MeasurementComplexItem::lastSequenceNumber() const {
return _sequenceNumber + std::max(0, this->_route.size() - 1);
}
bool MeasurementComplexItem::registerGenerator(const QString &name,
routing::GeneratorBase *g) {
if (name.isEmpty()) {
......@@ -602,20 +663,20 @@ int MeasurementComplexItem::generatorIndex() {
void MeasurementComplexItem::editingStart() {
if (!_editing(this->_state)) {
*_editorData = *_areaData;
_setAreaData(_editorData);
*_pEditorData = *_pAreaData;
_setAreaData(_pEditorData);
_setState(STATE::EDITING);
}
}
void MeasurementComplexItem::editingStop() {
if (_editing(this->_state)) {
if (_editorData->isValid()) {
*_areaData = *_editorData;
if (_pEditorData->isValid()) {
*_pAreaData = *_pEditorData;
}
_setAreaData(_areaData);
_setAreaData(_pAreaData);
_setState(STATE::IDLE);
if (_editorData->isValid() && *_editorData != *_areaData) {
if (_pEditorData->isValid() && *_pEditorData != *_pAreaData) {
_updateRoute();
}
}
......@@ -625,7 +686,7 @@ void MeasurementComplexItem::_storeRoutingData(
MeasurementComplexItem::PtrRoutingData pRoute) {
if (this->_state == STATE::ROUTING) {
// Store solutions.
auto ori = this->_areaData->origin();
auto ori = this->_pAreaData->origin();
ori.setAltitude(0);
const auto &transectsENU = pRoute->transects;
QVector<Variant> variantVector;
......@@ -742,4 +803,6 @@ bool MeasurementComplexItem::calculating() const {
bool MeasurementComplexItem::editing() const { return _editing(this->_state); }
bool MeasurementComplexItem::ready() const { return _ready(this->_state); }
bool MeasurementComplexItem::followTerrain() const { return _followTerrain; }
......@@ -45,8 +45,6 @@ public:
Q_PROPERTY(
routing::GeneratorBase *generator READ generator NOTIFY generatorChanged)
Q_PROPERTY(int generatorIndex READ generatorIndex NOTIFY generatorChanged)
Q_PROPERTY(bool editing READ editing NOTIFY editingChanged)
Q_PROPERTY(bool editing READ editing NOTIFY editingChanged)
Q_PROPERTY(AreaData *areaData READ areaData NOTIFY areaDataChanged)
Q_PROPERTY(QVariantList route READ route NOTIFY routeChanged)
......@@ -91,6 +89,9 @@ public:
virtual double amslExitAlt(void) const override final;
virtual double minAMSLAltitude(void) const override final;
virtual double maxAMSLAltitude(void) const override final;
virtual QString commandDescription(void) const override final;
virtual QString commandName(void) const override final;
virtual QString abbreviation(void) const override final;
// Generator
bool registerGenerator(const QString &name, routing::GeneratorBase *g);
......@@ -171,20 +172,20 @@ private:
PlanMasterController *_masterController;
int _sequenceNumber;
bool _followTerrain;
SettingsFact _altitude;
// State.
STATE _state;
// Facts
QMap<QString, FactMetaData *> _metaDataMap;
SettingsFact _altitude;
SettingsFact _variant;
QStringList _variantNames;
// Area data
PtrAreaData _areaData;
PtrAreaData _editorData;
PtrAreaData _currentData;
PtrAreaData _pAreaData;
PtrAreaData _pEditorData;
PtrAreaData _pCurrentData;
// Generators
QList<PtrGenerator> _generatorList;
......
......@@ -73,7 +73,7 @@ const char *MeasurementArea::MeasurementAreaName = "Measurement Area";
MeasurementArea::MeasurementArea(QObject *parent)
: GeoArea(parent),
_metaDataMap(FactMetaData::createMapFromJsonFile(
QStringLiteral(":/json/WimaMeasurementArea.SettingsGroup.json"),
QStringLiteral(":/json/MeasurementArea.SettingsGroup.json"),
this /* QObject parent */)),
_tileHeight(SettingsFact(settingsGroup, _metaDataMap[tileHeightName],
this /* QObject parent */)),
......
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "TileHeight",
......@@ -43,3 +47,4 @@
"defaultValue": 5
}
]
}
[
{
"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
}
]
......@@ -7,11 +7,13 @@ import QGroundControl.FactControls 1.0
import QGroundControl.ScreenTools 1.0
GridLayout {
id: grid
property var generator // CircularGenerator
property var availableWidth
property real _margin: ScreenTools.defaultFontPixelWidth / 2
width: availableWidth
columnSpacing: _margin
rowSpacing: _margin
columns: 2
......
......@@ -15,26 +15,27 @@ import QtPositioning 5.3
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl 1.0
/// Wima map visual
Item {
id: _root
property var map ///< Map control to place item in
property var qgcView ///< QGCView to use for popping dialogs
property var geoArea ///< GeoArea derived class
signal clicked(int sequenceNumber)
property var _visualItem
Component.onCompleted: {
if (object.mapVisualQML) {
var component = Qt.createComponent(object.mapVisualQML)
if (geoArea.mapVisualQML) {
var component = Qt.createComponent(geoArea.mapVisualQML)
if (component.status === Component.Error) {
console.log("Error loading Qml: ", object.mapVisualQML, component.errorString())
console.log("Error loading Qml: ", geoArea.mapVisualQML, component.errorString())
}
_visualItem = component.createObject(map, { "map": _root.map, "qgcView": _root.qgcView })
_visualItem = component.createObject(map, { "map": _root.map, "qgcView": _root.qgcView, "geoArea": _root.geoArea})
_visualItem.clicked.connect(_root.clicked)
}
}
......
......@@ -8,10 +8,11 @@ import QGroundControl.ScreenTools 1.0
GridLayout {
property var generator ///< LinearGenerator
property var generator // CircularGenerator
property var availableWidth
property real _margin: ScreenTools.defaultFontPixelWidth / 2
width: availableWidth
columnSpacing: _margin
rowSpacing: _margin
columns: 2
......
......@@ -18,93 +18,29 @@ import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightMap 1.0
/// Wima Global Measurement Area visuals
Item {
id: _root
property var map ///< Map control to place item in
property var qgcView ///< QGCView to use for popping dialogs
property var areaItem ///< GeoArea derived class
property var areaItem: object
property var _polygon: areaItem
property var opacity: 0.5
signal clicked(int sequenceNumber)
/// Add an initial 4 sided polygon if there is none
function _addInitialPolygon() {
// 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)
rect.x += (rect.width * 0.25) / 2
rect.y += (rect.height * 0.25) / 2
rect.width *= 0.75
rect.height *= 0.75
var centerCoord = map.toCoordinate(Qt.point(rect.x + (rect.width / 2), rect.y + (rect.height / 2)), false /* clipToViewPort */)
var topLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
var topRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y), false /* clipToViewPort */)
var bottomLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y + rect.height), false /* clipToViewPort */)
var bottomRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
// Adjust polygon to max size
var maxSize = 100
var halfWidthMeters = Math.min(topLeftCoord.distanceTo(topRightCoord), maxSize) / 2
var halfHeightMeters = Math.min(topLeftCoord.distanceTo(bottomLeftCoord), maxSize) / 2
topLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 0)
topRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0)
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180)
bottomRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180)
if (areaItem.showBorderPolygon.rawValue === true) {
if (areaItem.borderPolygon.count < 3) {
areaItem.borderPolygon.appendVertex(topLeftCoord)
areaItem.borderPolygon.appendVertex(topRightCoord)
areaItem.borderPolygon.appendVertex(bottomRightCoord)
areaItem.borderPolygon.appendVertex(bottomLeftCoord)
}
} else {
if (_polygon.count < 3) {
_polygon.appendVertex(topLeftCoord)
_polygon.appendVertex(topRightCoord)
_polygon.appendVertex(bottomRightCoord)
_polygon.appendVertex(bottomLeftCoord)
}
}
}
Component.onCompleted: {
_addInitialPolygon()
//_addInitialPolyline()
}
Component.onDestruction: {
}
// Polygon
WimaMapPolygonVisuals {
qgcView: _root.qgcView
// Area polygon
QGCMapPolygonVisuals {
id: mapPolygonVisuals
mapControl: map
mapPolygon: _polygon
mapPolygon: areaItem
interactive: true
borderWidth: 1
borderColor: "black"
interiorColor: "green"
interiorOpacity: 0.25
}
// Border Polygon
WimaMapPolygonVisuals {
qgcView: _root.qgcView
mapControl: map
mapPolygon: areaItem.borderPolygon
borderWidth: 1
borderColor: areaItem.borderPolygon.interactive ? "white" : "transparent"
interiorColor: "transparent"
interiorOpacity: 1
altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision
interiorOpacity: _root.opacity
}
// Add Snake tiles to the map
......@@ -131,6 +67,7 @@ Item {
}
}
}
function getColor(progress) {
if (progress === 0)
return "transparent"
......
This diff is collapsed.
......@@ -51,6 +51,8 @@ Item {
_addExitCoordinate()
_addTransectsComponent()
_addGeneratorVisuals()
var bbox = boundingBox()
_areaData.initialize(bbox[0], bbox[1])
}
Component.onDestruction: {
......@@ -70,7 +72,7 @@ Item {
id: visualTransectsComponent
MapPolyline {
property var transects: _missionItem.visualTransectPoints
property var transects: _missionItem.route
line.color: "white"
line.width: 2
path: transects.length > 0 ? transects : []
......@@ -120,13 +122,10 @@ Item {
Repeater {
model: _areaData.areaList
delegate: WimaMapVisual {
delegate: GeoAreaVisualLoader {
map: _root.map
qgcView: _root.qgcView
}
onItemAdded: {
//console.log("Item added")
geoArea: _areaData.areaList[index]
}
}
......@@ -205,4 +204,32 @@ Item {
_transectsComponent = undefined
}
}
function boundingBox() {
// 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)
rect.x += (rect.width * 0.25) / 2
rect.y += (rect.height * 0.25) / 2
rect.width *= 0.75
rect.height *= 0.75
var centerCoord = map.toCoordinate(Qt.point(rect.x + (rect.width / 2),
rect.y + (rect.height / 2)),
false /* clipToViewPort */)
var topRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y), false /* clipToViewPort */)
var bottomLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y + rect.height), false /* clipToViewPort */)
var topLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
var bottomRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
// Initial polygon has max width and height of 3000 meters
var halfWidthMeters = Math.min(topLeftCoord.distanceTo(topRightCoord), 3000) / 2
var halfHeightMeters = Math.min(topLeftCoord.distanceTo(bottomLeftCoord), 3000) / 2
topRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0)
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180)
return [ bottomLeftCoord, topRightCoord ]
}
}
......@@ -23,12 +23,14 @@ Item {
property var map ///< Map control to place item in
property var qgcView ///< QGCView to use for popping dialogs
property var areaItem ///< GeoArea derived class.
property var areaItem: object
property var _polygon: areaItem
property var _depot: undefined
property bool _showDepot: areaItem.interactive || areaItem.borderPolygon.interactive
signal clicked(int sequenceNumber)
on_ShowDepotChanged: {
if (_showDepot){
_addDepot()
......@@ -37,70 +39,7 @@ Item {
}
}
signal clicked(int sequenceNumber)
function _addDepot() {
if (!_depot){
_depot = depotPointComponent.createObject(_root)
map.addMapItem(_depot)
}
}
function _destroyDepot() {
if (_depot){
map.removeMapItem(_depot)
_depot.destroy()
_depot = undefined
}
}
/// Add an initial 4 sided polygon if there is none
function _addInitialPolygon() {
// 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)
rect.x += (rect.width * 0.25) / 2
rect.y += (rect.height * 0.25) / 2
rect.width *= 0.75
rect.height *= 0.75
var centerCoord = map.toCoordinate(Qt.point(rect.x + (rect.width / 2), rect.y + (rect.height / 2)), false /* clipToViewPort */)
var topLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
var topRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y), false /* clipToViewPort */)
var bottomLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y + rect.height), false /* clipToViewPort */)
var bottomRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
// Adjust polygon to max size
var maxSize = 100
var halfWidthMeters = Math.min(topLeftCoord.distanceTo(topRightCoord), maxSize) / 2
var halfHeightMeters = Math.min(topLeftCoord.distanceTo(bottomLeftCoord), maxSize) / 2
topLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 0)
topRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0)
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180)
bottomRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180)
if (areaItem.showBorderPolygon.rawValue === true) {
if (areaItem.borderPolygon.count < 3) {
areaItem.borderPolygon.appendVertex(topLeftCoord)
areaItem.borderPolygon.appendVertex(topRightCoord)
areaItem.borderPolygon.appendVertex(bottomRightCoord)
areaItem.borderPolygon.appendVertex(bottomLeftCoord)
}
} else {
if (_polygon.count < 3) {
_polygon.appendVertex(topLeftCoord)
_polygon.appendVertex(topRightCoord)
_polygon.appendVertex(bottomRightCoord)
_polygon.appendVertex(bottomLeftCoord)
}
}
}
Component.onCompleted: {
_addInitialPolygon()
if (_showDepot){
_addDepot()
}
......@@ -110,24 +49,17 @@ Item {
_destroyDepot()
}
WimaMapPolygonVisuals {
qgcView: _root.qgcView
// Area polygon
QGCMapPolygonVisuals {
id: mapPolygonVisuals
mapControl: map
mapPolygon: _polygon
mapPolygon: areaItem
interactive: true
borderWidth: 1
borderColor: "black"
interiorColor: "yellow"
interiorOpacity: 0.25
}
WimaMapPolygonVisuals {
qgcView: _root.qgcView
mapControl: map
mapPolygon: areaItem.borderPolygon
borderWidth: 1
borderColor: areaItem.borderPolygon.interactive ? "white" : "transparent"
interiorColor: "transparent"
interiorOpacity: 1
interiorColor: "blue"
altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision
interiorOpacity: _root.opacity
}
// Depot Point.
......@@ -164,4 +96,18 @@ Item {
}
}
function _addDepot() {
if (!_depot){
_depot = depotPointComponent.createObject(_root)
map.addMapItem(_depot)
}
}
function _destroyDepot() {
if (_depot){
map.removeMapItem(_depot)
_depot.destroy()
_depot = undefined
}
}
}
......@@ -15,7 +15,6 @@ import QtPositioning 5.3
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import Wima 1.0
/// Mission item map visual
Item {
......
......@@ -26,7 +26,9 @@ Rectangle {
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10.5
property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle
property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle ?
QGroundControl.multiVehicleManager.activeVehicle :
QGroundControl.multiVehicleManager.offlineEditingVehicle
property real _cameraMinTriggerInterval: _missionItem.cameraCalc.minTriggerInterval.rawValue
property bool _polygonDone: false
property string _doneAdjusting: qsTr("Done")
......
......@@ -110,3 +110,6 @@ VehicleRotationCal 1.0 VehicleRotationCal.qml
VehicleSummaryRow 1.0 VehicleSummaryRow.qml
QGCHoverButton 1.0 QGCHoverButton.qml
MAVLinkChart 1.0 MAVLinkChart.qml
MeasurementItemMapVisual 1.0 MeasurementItemMapVisual.qml
CircularGeneratorMapVisual 1.0 CircularGeneratorMapVisual.qml
GeoAreaVisualLoader 1.0 GeoAreaVisualLoader.qml
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.FlightMap 1.0
Rectangle {
id: _root
height: visible ? (editorColumn.height + (_margin * 2)) : 0
width: availableWidth
color: qgcPal.windowShadeDark
radius: _radius
// The following properties must be available up the hierarchy chain
//property real availableWidth ///< Width for control
//property var missionItem ///< Mission Item for editor
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property var _generator: missionItem.generator
property var _generatorEditor: undefined
QGCPalette { id: qgcPal; colorGroupEnabled: true }
Component.onCompleted: {
_addGeneratorEditor()
}
Component.onDestruction: {
_destroyGeneratorEditor()
}
on_GeneratorChanged: {
_destroyGeneratorEditor()
_addGeneratorEditor()
}
Column {
id: editorColumn
anchors.margins: _margin
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
SectionHeader {
id: generalHeader
text: qsTr("General")
}
GridLayout {
id: generalGrid
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
columns: 2
visible: generalHeader.checked
QGCLabel { text: qsTr("Altitude") }
FactTextField {
fact: missionItem.cameraCalc.distanceToSurface
Layout.fillWidth: true
}
QGCCheckBox {
id: relAlt
text: qsTr("Relative altitude")
checked: missionItem.cameraCalc.distanceToSurfaceRelative
enabled: missionItem.cameraCalc.isManualCamera && !missionItem.followTerrain
visible: QGroundControl.corePlugin.options.showMissionAbsoluteAltitude || (!missionItem.cameraCalc.distanceToSurfaceRelative && !missionItem.followTerrain)
onClicked: missionItem.cameraCalc.distanceToSurfaceRelative = checked
Layout.fillWidth: true
Layout.columnSpan: 2
Connections {
target: missionItem.cameraCalc
onDistanceToSurfaceRelativeChanged: relAlt.checked = missionItem.cameraCalc.distanceToSurfaceRelative
}
}
QGCLabel {
text: qsTr("Generator Type")
Layout.columnSpan: 2
}
QGCComboBox {
property var names: missionItem.generatorNameList
property int length: names.length
anchors.margins: ScreenTools.defaultFontPixelWidth
currentIndex: missionItem.generatorIndex
Layout.columnSpan: 2
model: missionItem.generatorNameList
onActivated: {
missionItem.switchToGenerator(index)
}
}
QGCLabel {
text: qsTr("Variant")
Layout.columnSpan: 2
}
GridLayout{
Layout.columnSpan: 2
columnSpacing: _margin
rowSpacing: _margin
columns: 6
Repeater{
id: variantRepeater
property var fact: missionItem.variant
property int variant: fact.value
property var names: missionItem.variantNames
property int len: missionItem.variantNames.length
model: len
delegate: QGCRadioButton {
checked: index === variantRepeater.variant
text: variantRepeater.names[index] ? variantRepeater.names[index]: ""
onCheckedChanged: {
if (checked){
missionItem.variant.value = index
}
checked = Qt.binding(function(){ return index === variantRepeater.variant})
}
}
}
}
}
// Generator Editor
SectionHeader {
id: transectsHeader
text: qsTr("Generator")
}
Column{
id:generatorEditorParent
visible: transectsHeader.checked
}
Column{
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
BusyIndicator{
id: indicator
anchors.horizontalCenter: parent.horizontalCenter
property bool calculating: missionItem.calculating
running: calculating
visible: calculating || timer.running
onCalculatingChanged: {
if(!calculating){
// defer hiding
timer.restart()
}
}
Timer{
id: timer
interval: 1000
repeat: false
running: false
}
}
}
} // Column
function _addGeneratorEditor(){
if (_generator.editorQml && !_generatorEditor) {
var component = Qt.createComponent(_generator.editorQml)
if (component.status === Component.Error) {
console.log("Error loading Qml: ",
_generator.editorQml, component.errorString())
} else {
_generatorEditor =
component.createObject(
generatorEditorParent, {
"generator": _root._generator,
})
}
}
}
function _destroyGeneratorEditor(){
if (_generatorEditor){
_generatorEditor.destroy()
_generatorEditor = undefined
}
}
} // Rectangle
WimaMapVisual 1.0 WimaMapVisual.qml
WimaMeasurementAreaMapVisual 1.0 WimaMeasurementAreaMapVisual.qml
WimaJoinedAreaMapVisual 1.0 WimaJoinedAreaMapVisual.qml
WimaMeasurementAreaEditor 1.0 WimaMeasurementAreaEditor.qml
WimaServiceAreaMapVisual 1.0 WimaServiceAreaMapVisual.qml
WimaAreaMapVisual 1.0 WimaAreaMapVisual.qml
WimaServiceAreaEditor 1.0 WimaServiceAreaEditor.qml
WimaCorridorMapVisual 1.0 WimaCorridorMapVisual.qml
WimaItemEditor 1.0 WimaItemEditor.qml
WimaMapPolygonVisuals 1.0 WimaMapPolygonVisuals.qml
WimaMapPolylineVisuals 1.0 WimaMapPolylineVisuals.qml
CircularSurveyMapVisual 1.0 CircularSurveyMapVisual.qml
DragCoordinate 1.0 DragCoordinate.qml
CoordinateIndicator 1.0 CoordinateIndicator.qml
CoordinateIndicatorDrag 1.0 CoordinateIndicatorDrag.qml
ProgressIndicator 1.0 ProgressIndicator.qml
WimaToolBar 1.0 WimaToolBar.qml
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.FlightMap 1.0
// Editor for Operating Area items
Rectangle {
id: _root
height: visible ? (editorColumn.height + (_margin * 2)) : 0
width: availableWidth
color: qgcPal.windowShadeDark
radius: _radius
// The following properties must be available up the hierarchy chain
//property real availableWidth ///< Width for control
//property var areaItem ///< Mission Item for editor
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10.5
//property var polyline: areaItem.polyline
//property bool polylineInteractive: polyline.interactive
property bool polygonInteractive: areaItem.interactive
property var polygon: areaItem
property bool initNecesarry: true
/*onPolylineInteractiveChanged: {
polyline.interactive = polylineInteractive;
}*/
onPolygonInteractiveChanged: {
polygon.interactive = polygonInteractive;
}
/*function editPolyline(){
if (polylineInteractive){
//polyline.interactive = false;
polylineInteractive = false;
//polygonInteractive = true;
}else{
//polyline.interactive = true;
polylineInteractive = true;
//polygonInteractive = false;
}
}*/
QGCPalette { id: qgcPal; colorGroupEnabled: true }
Column {
id: editorColumn
anchors.margins: _margin
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
SectionHeader {
id: scanHeader
text: qsTr("Settings")
}
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: scanHeader.checked
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
columns: 2
QGCLabel { text: qsTr("Offset") }
FactTextField {
fact: areaItem.borderPolygonOffset
Layout.fillWidth: true
}
/*QGCLabel {
text: qsTr("Bottom Layer Altitude")
}
FactTextField {
fact: areaItem.bottomLayerAltitude
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Number of Layers") }
FactTextField {
fact: areaItem.numberOfLayers
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Layer Distance") }
FactTextField {
fact: areaItem.layerDistance
Layout.fillWidth: true
}*/
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: 1
}
}
FactCheckBox {
text: qsTr("Border Polygon")
fact: areaItem.showBorderPolygon
//enabled: !missionItem.followTerrain
}
// Column - Scan
/*SectionHeader {
id: polylineHeader
text: qsTr("Gateway Poly Line")
}
QGCButton {
id: polylineEditor
anchors.topMargin: _margin / 2
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
text: polylineInteractive ? "Done" : "Edit"
onClicked: editPolyline()
}
QGCButton {
id: swapEndpoints
anchors.topMargin: _margin / 2
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
text: "Swap End-Points"
onClicked: polyline.swapEndPoints()
}*/
SectionHeader {
id: statsHeader
text: qsTr("Statistics")
}
Grid {
columns: 2
columnSpacing: ScreenTools.defaultFontPixelWidth
visible: statsHeader.checked
/*QGCLabel { text: qsTr("Layers") }
QGCLabel { text: areaItem.layers.valueString }*/
QGCLabel { text: qsTr("Area") }
QGCLabel { text: QGroundControl.squareMetersToAppSettingsAreaUnits(areaItem.area).toFixed(2) + " " + QGroundControl.appSettingsAreaUnitsString }
}
} // Column
} // Rectangle
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