Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
5f9f30c2
Commit
5f9f30c2
authored
Nov 27, 2020
by
Valentin Platzgummer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
generators fixed, _isIncomplete stuff added to MeasurementComplexItem
parent
8da5e19a
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
866 additions
and
849 deletions
+866
-849
AreaData.cc
src/MeasurementComplexItem/AreaData.cc
+2
-2
AreaData.h
src/MeasurementComplexItem/AreaData.h
+1
-1
CircularGenerator.cpp
src/MeasurementComplexItem/CircularGenerator.cpp
+40
-62
CircularGenerator.h
src/MeasurementComplexItem/CircularGenerator.h
+5
-5
GeneratorBase.cc
src/MeasurementComplexItem/GeneratorBase.cc
+2
-16
GeneratorBase.h
src/MeasurementComplexItem/GeneratorBase.h
+1
-1
LinearGenerator.cpp
src/MeasurementComplexItem/LinearGenerator.cpp
+32
-52
LinearGenerator.h
src/MeasurementComplexItem/LinearGenerator.h
+7
-5
MeasurementComplexItem.cc
src/MeasurementComplexItem/MeasurementComplexItem.cc
+48
-76
MeasurementComplexItem.h
src/MeasurementComplexItem/MeasurementComplexItem.h
+7
-7
GeoArea.cc
src/MeasurementComplexItem/geometry/GeoArea.cc
+31
-2
GeoArea.h
src/MeasurementComplexItem/geometry/GeoArea.h
+7
-0
MeasurementArea.cc
src/MeasurementComplexItem/geometry/MeasurementArea.cc
+27
-4
SafeArea.cc
src/MeasurementComplexItem/geometry/SafeArea.cc
+2
-2
SnakeTile.cpp
src/MeasurementComplexItem/nemo_interface/SnakeTile.cpp
+5
-3
SnakeTile.h
src/MeasurementComplexItem/nemo_interface/SnakeTile.h
+3
-0
CircularGeneratorMapVisual.qml
...MeasurementComplexItem/qml/CircularGeneratorMapVisual.qml
+34
-54
MeasurementItemMapVisual.qml
src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml
+111
-50
ParameterEditor.qml
src/MeasurementComplexItem/qml/ParameterEditor.qml
+20
-6
SafeAreaMapVisual.qml
src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml
+31
-41
QGCMapPolygon.cc
src/MissionManager/QGCMapPolygon.cc
+450
-460
No files found.
src/MeasurementComplexItem/AreaData.cc
View file @
5f9f30c2
...
...
@@ -39,7 +39,7 @@ bool AreaData::insert(GeoArea *areaData) {
if
(
areaData
!=
nullptr
)
{
if
(
Q_LIKELY
(
!
this
->
_areaList
.
contains
(
areaData
)))
{
_areaList
.
append
(
areaData
);
emit
areaList
();
emit
areaList
Changed
();
auto
*
measurementArea
=
qobject_cast
<
MeasurementArea
*>
(
areaData
);
if
(
measurementArea
!=
nullptr
)
{
...
...
@@ -88,7 +88,7 @@ QmlObjectListModel *AreaData::areaList() { return &_areaList; }
const
QmlObjectListModel
*
AreaData
::
areaList
()
const
{
return
&
_areaList
;
}
const
QGeoCoordinate
&
AreaData
::
origin
()
const
{
return
_origin
;
}
QGeoCoordinate
AreaData
::
origin
()
const
{
return
_origin
;
}
bool
AreaData
::
isCorrect
()
{
if
(
!
initialized
())
{
...
...
src/MeasurementComplexItem/AreaData.h
View file @
5f9f30c2
...
...
@@ -47,7 +47,7 @@ public:
//! \brief origin
//! \return Returns an origin near one of the areas.
//! \note Origin might change if the list of areas changes.
const
QGeoCoordinate
&
origin
()
const
;
QGeoCoordinate
origin
()
const
;
Q_INVOKABLE
bool
isCorrect
();
//!
...
...
src/MeasurementComplexItem/CircularGenerator.cpp
View file @
5f9f30c2
...
...
@@ -37,13 +37,21 @@ CircularGenerator::CircularGenerator(QObject *parent)
:
CircularGenerator
(
nullptr
,
parent
)
{}
CircularGenerator
::
CircularGenerator
(
GeneratorBase
::
Data
d
,
QObject
*
parent
)
:
GeneratorBase
(
d
,
parent
),
_connectionsEstablished
(
false
),
:
GeneratorBase
(
d
,
parent
),
_metaDataMap
(
FactMetaData
::
createMapFromJsonFile
(
QStringLiteral
(
":/json/CircularGenerator.SettingsGroup.json"
),
this
)),
_distance
(
settingsGroup
,
_metaDataMap
[
distanceName
]),
_deltaAlpha
(
settingsGroup
,
_metaDataMap
[
deltaAlphaName
]),
_minLength
(
settingsGroup
,
_metaDataMap
[
minLengthName
])
{
establishConnections
();
_minLength
(
settingsGroup
,
_metaDataMap
[
minLengthName
]),
_measurementArea
(
nullptr
)
{
connect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
deltaAlpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
,
&
CircularGenerator
::
referenceChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
}
QString
CircularGenerator
::
editorQml
()
{
...
...
@@ -199,77 +207,47 @@ void CircularGenerator::resetReference() {
}
}
void
CircularGenerator
::
establishConnections
()
{
if
(
this
->
_d
!=
nullptr
&&
!
this
->
_connectionsEstablished
)
{
auto
measurementArea
=
getGeoArea
<
const
MeasurementArea
*>
(
*
this
->
_d
->
areaList
());
auto
serviceArea
=
getGeoArea
<
const
SafeArea
*>
(
*
this
->
_d
->
areaList
());
if
(
measurementArea
!=
nullptr
&&
serviceArea
!=
nullptr
)
{
GeneratorBase
::
establishConnections
();
Fact
*
CircularGenerator
::
distance
()
{
return
&
_distance
;
}
connect
(
this
->
_d
,
&
AreaData
::
originChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
measurementArea
,
&
MeasurementArea
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
measurementArea
,
&
MeasurementArea
::
tilesChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
measurementArea
,
&
MeasurementArea
::
centerChanged
,
this
,
&
CircularGenerator
::
resetReferenceIfInvalid
);
connect
(
measurementArea
,
&
MeasurementArea
::
pathChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
serviceArea
,
&
SafeArea
::
depotChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
deltaAlpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
,
&
CircularGenerator
::
referenceChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
this
->
_connectionsEstablished
=
true
;
}
}
Fact
*
CircularGenerator
::
deltaAlpha
()
{
return
&
_deltaAlpha
;
}
Fact
*
CircularGenerator
::
minLength
()
{
return
&
_minLength
;
}
void
CircularGenerator
::
onAreaListChanged
()
{
auto
*
measurementArea
=
getGeoArea
<
MeasurementArea
*>
(
*
this
->
_d
->
areaList
());
setMeasurementArea
(
measurementArea
);
}
void
CircularGenerator
::
deleteConnections
()
{
if
(
this
->
_d
!=
nullptr
&&
this
->
_connectionsEstablished
)
{
auto
measurementArea
=
getGeoArea
<
const
MeasurementArea
*>
(
*
this
->
_d
->
areaList
());
auto
serviceArea
=
getGeoArea
<
const
SafeArea
*>
(
*
this
->
_d
->
areaList
());
if
(
measurementArea
!=
nullptr
&&
serviceArea
!=
nullptr
)
{
GeneratorBase
::
deleteConnections
();
void
CircularGenerator
::
setMeasurementArea
(
MeasurementArea
*
area
)
{
if
(
_measurementArea
!=
area
)
{
disconnect
(
this
->
_d
,
&
AreaData
::
originChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
measurementArea
,
&
MeasurementArea
::
progressChanged
,
this
,
if
(
_measurementArea
!=
nullptr
)
{
disconnect
(
_measurementArea
,
&
MeasurementArea
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
measurementArea
,
&
MeasurementArea
::
tilesChanged
,
this
,
disconnect
(
_
measurementArea
,
&
MeasurementArea
::
tilesChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
measurementArea
,
&
MeasurementArea
::
centerChanged
,
this
,
disconnect
(
_
measurementArea
,
&
MeasurementArea
::
centerChanged
,
this
,
&
CircularGenerator
::
resetReferenceIfInvalid
);
disconnect
(
measurementArea
,
&
MeasurementArea
::
pathChanged
,
this
,
disconnect
(
_
measurementArea
,
&
MeasurementArea
::
pathChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
serviceArea
,
&
SafeArea
::
depotChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
deltaAlpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
,
&
CircularGenerator
::
referenceChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
this
->
_connectionsEstablished
=
true
;
}
}
}
Fact
*
CircularGenerator
::
distance
()
{
return
&
_distance
;
}
_measurementArea
=
area
;
Fact
*
CircularGenerator
::
deltaAlpha
()
{
return
&
_deltaAlpha
;
}
if
(
_measurementArea
!=
nullptr
)
{
connect
(
_measurementArea
,
&
MeasurementArea
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
_measurementArea
,
&
MeasurementArea
::
tilesChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
_measurementArea
,
&
MeasurementArea
::
centerChanged
,
this
,
&
CircularGenerator
::
resetReferenceIfInvalid
);
connect
(
_measurementArea
,
&
MeasurementArea
::
pathChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
}
Fact
*
CircularGenerator
::
minLength
()
{
return
&
_minLength
;
}
emit
generatorChanged
();
}
}
bool
circularTransects
(
const
snake
::
FPoint
&
reference
,
const
snake
::
FPolygon
&
polygon
,
...
...
src/MeasurementComplexItem/CircularGenerator.h
View file @
5f9f30c2
...
...
@@ -4,6 +4,8 @@
#include "SettingsFact.h"
class
MeasurementArea
;
namespace
routing
{
class
CircularGenerator
:
public
GeneratorBase
{
...
...
@@ -48,18 +50,16 @@ public slots:
Q_INVOKABLE
void
resetReferenceIfInvalid
();
Q_INVOKABLE
void
resetReference
();
protected:
virtual
void
establishConnections
()
override
;
virtual
void
deleteConnections
()
override
;
private:
bool
_connectionsEstablished
;
void
onAreaListChanged
();
void
setMeasurementArea
(
MeasurementArea
*
area
);
QGeoCoordinate
_reference
;
QMap
<
QString
,
FactMetaData
*>
_metaDataMap
;
SettingsFact
_distance
;
SettingsFact
_deltaAlpha
;
SettingsFact
_minLength
;
MeasurementArea
*
_measurementArea
;
};
}
// namespace routing
src/MeasurementComplexItem/GeneratorBase.cc
View file @
5f9f30c2
...
...
@@ -8,8 +8,6 @@ GeneratorBase::GeneratorBase(QObject *parent)
GeneratorBase
::
GeneratorBase
(
GeneratorBase
::
Data
d
,
QObject
*
parent
)
:
QObject
(
parent
),
_d
(
d
)
{
establishConnections
();
connect
(
_d
,
&
AreaData
::
areaListChanged
,
this
,
&
GeneratorBase
::
_areaListChangedHandler
);
}
GeneratorBase
::~
GeneratorBase
()
{}
...
...
@@ -17,27 +15,15 @@ GeneratorBase::~GeneratorBase() {}
GeneratorBase
::
Data
GeneratorBase
::
data
()
const
{
return
_d
;
}
void
GeneratorBase
::
setData
(
Data
d
)
{
if
(
d
!=
nullptr
)
{
if
(
_d
!=
nullptr
)
{
disconnect
(
_d
,
&
AreaData
::
areaListChanged
,
this
,
&
GeneratorBase
::
_areaListChangedHandler
);
}
if
(
d
!=
_d
&&
d
!=
nullptr
)
{
deleteConnections
();
_d
=
d
;
establishConnections
();
connect
(
_d
,
&
AreaData
::
areaListChanged
,
this
,
&
GeneratorBase
::
_areaListChangedHandler
);
emit
dataChanged
();
}
}
void
GeneratorBase
::
establishConnections
()
{}
void
GeneratorBase
::
deleteConnections
()
{}
void
GeneratorBase
::
_areaListChangedHandler
()
{
deleteConnections
();
establishConnections
();
emit
generatorChanged
();
}
}
// namespace routing
src/MeasurementComplexItem/GeneratorBase.h
View file @
5f9f30c2
...
...
@@ -37,6 +37,7 @@ public:
signals:
void
generatorChanged
();
void
dataChanged
();
protected:
virtual
void
establishConnections
();
...
...
@@ -44,7 +45,6 @@ protected:
Data
_d
;
private:
void
_areaListChangedHandler
();
};
}
// namespace routing
src/MeasurementComplexItem/LinearGenerator.cpp
View file @
5f9f30c2
...
...
@@ -32,8 +32,16 @@ LinearGenerator::LinearGenerator(GeneratorBase::Data d, QObject *parent)
QStringLiteral
(
":/json/LinearGenerator.SettingsGroup.json"
),
this
)),
_distance
(
settingsGroup
,
_metaDataMap
[
distanceName
]),
_alpha
(
settingsGroup
,
_metaDataMap
[
alphaName
]),
_minLength
(
settingsGroup
,
_metaDataMap
[
minLengthName
])
{
establishConnections
();
_minLength
(
settingsGroup
,
_metaDataMap
[
minLengthName
]),
_measurementArea
(
nullptr
),
_safeArea
(
nullptr
)
{
connect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
alpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
_d
,
&
AreaData
::
areaListChanged
,
this
,
&
LinearGenerator
::
onAreaListChanged
);
}
QString
LinearGenerator
::
editorQml
()
{
...
...
@@ -147,63 +155,35 @@ Fact *LinearGenerator::alpha() { return &_alpha; }
Fact
*
LinearGenerator
::
minLength
()
{
return
&
_minLength
;
}
void
LinearGenerator
::
establishConnections
()
{
if
(
this
->
_d
!=
nullptr
&&
!
this
->
_connectionsEstablished
)
{
auto
measurementArea
=
getGeoArea
<
const
MeasurementArea
*>
(
*
this
->
_d
->
areaList
());
auto
serviceArea
=
getGeoArea
<
const
SafeArea
*>
(
*
this
->
_d
->
areaList
());
if
(
measurementArea
!=
nullptr
&&
serviceArea
!=
nullptr
)
{
GeneratorBase
::
establishConnections
();
connect
(
this
->
_d
,
&
AreaData
::
originChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
measurementArea
,
&
MeasurementArea
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
measurementArea
,
&
MeasurementArea
::
tilesChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
measurementArea
,
&
MeasurementArea
::
pathChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
serviceArea
,
&
SafeArea
::
depotChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
alpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
this
->
_connectionsEstablished
=
true
;
}
}
void
LinearGenerator
::
onAreaListChanged
()
{
auto
*
measurementArea
=
getGeoArea
<
MeasurementArea
*>
(
*
this
->
_d
->
areaList
());
setMeasurementArea
(
measurementArea
);
}
void
LinearGenerator
::
deleteConnections
()
{
if
(
this
->
_d
!=
nullptr
&&
this
->
_connectionsEstablished
)
{
auto
measurementArea
=
getGeoArea
<
const
MeasurementArea
*>
(
*
this
->
_d
->
areaList
());
auto
serviceArea
=
getGeoArea
<
const
SafeArea
*>
(
*
this
->
_d
->
areaList
());
if
(
measurementArea
!=
nullptr
&&
serviceArea
!=
nullptr
)
{
GeneratorBase
::
deleteConnections
();
void
LinearGenerator
::
setMeasurementArea
(
MeasurementArea
*
area
)
{
if
(
_measurementArea
!=
area
)
{
disconnect
(
this
->
_d
,
&
AreaData
::
originChanged
,
this
,
if
(
_measurementArea
!=
nullptr
)
{
disconnect
(
_measurementArea
,
&
MeasurementArea
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
measurementArea
,
&
MeasurementArea
::
progres
sChanged
,
this
,
disconnect
(
_measurementArea
,
&
MeasurementArea
::
tile
sChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
measurementArea
,
&
MeasurementArea
::
tiles
Changed
,
this
,
disconnect
(
_measurementArea
,
&
MeasurementArea
::
path
Changed
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
measurementArea
,
&
MeasurementArea
::
pathChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
serviceArea
,
&
SafeArea
::
depotChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
alpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
this
->
_connectionsEstablished
=
true
;
}
_measurementArea
=
area
;
if
(
_measurementArea
!=
nullptr
)
{
connect
(
_measurementArea
,
&
MeasurementArea
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
_measurementArea
,
&
MeasurementArea
::
tilesChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
_measurementArea
,
&
MeasurementArea
::
pathChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
}
emit
generatorChanged
();
}
}
...
...
src/MeasurementComplexItem/LinearGenerator.h
View file @
5f9f30c2
...
...
@@ -4,6 +4,9 @@
#include "SettingsFact.h"
class
MeasurementArea
;
class
SafeArea
;
namespace
routing
{
class
LinearGenerator
:
public
GeneratorBase
{
...
...
@@ -33,17 +36,16 @@ public:
static
const
char
*
alphaName
;
static
const
char
*
minLengthName
;
protected:
virtual
void
establishConnections
()
override
;
virtual
void
deleteConnections
()
override
;
private:
bool
_connectionsEstablished
;
void
onAreaListChanged
();
void
setMeasurementArea
(
MeasurementArea
*
area
);
QMap
<
QString
,
FactMetaData
*>
_metaDataMap
;
SettingsFact
_distance
;
SettingsFact
_alpha
;
SettingsFact
_minLength
;
MeasurementArea
*
_measurementArea
;
SafeArea
*
_safeArea
;
};
}
// namespace routing
src/MeasurementComplexItem/MeasurementComplexItem.cc
View file @
5f9f30c2
...
...
@@ -72,15 +72,32 @@ MeasurementComplexItem::MeasurementComplexItem(
this
->
exitCoordinateSameAsEntry
());
});
// Connect isIncomplete.
connect
(
this
,
&
MeasurementComplexItem
::
idleChanged
,
[
this
]
{
if
(
this
->
idle
())
{
if
(
this
->
route
().
size
()
>
0
&&
this
->
_isIncomplete
==
true
)
{
this
->
_isIncomplete
=
false
;
emit
this
->
isIncompleteChanged
();
}
}
else
{
if
(
this
->
_isIncomplete
==
false
)
{
this
->
_isIncomplete
=
true
;
emit
this
->
isIncompleteChanged
();
}
}
});
connect
(
this
,
&
MeasurementComplexItem
::
idleChanged
,
this
,
&
MeasurementComplexItem
::
readyForSaveStateChanged
);
// Connect complexDistance.
connect
(
this
,
&
MeasurementComplexItem
::
routeChanged
,
[
this
]
{
emit
this
->
complexDistanceChanged
();
});
// Register Generators.
auto
lg
=
new
routing
::
LinearGenerator
(
this
->
_pAreaData
,
this
);
register
Generator
(
lg
->
name
(),
lg
);
add
Generator
(
lg
->
name
(),
lg
);
auto
cg
=
new
routing
::
CircularGenerator
(
this
->
_pAreaData
,
this
);
register
Generator
(
cg
->
name
(),
cg
);
add
Generator
(
cg
->
name
(),
cg
);
qCritical
()
<<
"ToDo: _altitude connections missing."
;
qCritical
()
<<
"ToDo: add generator saveing."
;
...
...
@@ -192,7 +209,7 @@ void MeasurementComplexItem::save(QJsonArray &planItems) {
qWarning
()
<<
"MeasurementComplexItem::save(): area data save missing."
;
qWarning
()
<<
"MeasurementComplexItem::save(): mission item save missing."
;
if
(
ready
())
{
if
(
idle
())
{
QJsonObject
saveObject
;
saveObject
[
JsonHelper
::
jsonVersionKey
]
=
1
;
...
...
@@ -270,7 +287,7 @@ double MeasurementComplexItem::specifiedGimbalPitch() {
void
MeasurementComplexItem
::
appendMissionItems
(
QList
<
MissionItem
*>
&
items
,
QObject
*
missionItemParent
)
{
if
(
ready
())
{
if
(
idle
())
{
qCDebug
(
MeasurementComplexItemLog
)
<<
"appendMissionItems()"
;
int
seqNum
=
this
->
_sequenceNumber
;
...
...
@@ -350,8 +367,8 @@ void MeasurementComplexItem::_setState(MeasurementComplexItem::STATE state) {
emit
editingChanged
();
}
if
(
_
ready
(
oldState
)
!=
_ready
(
state
))
{
emit
ready
Changed
();
if
(
_
idle
(
oldState
)
!=
_idle
(
state
))
{
emit
idle
Changed
();
}
}
}
...
...
@@ -364,7 +381,7 @@ bool MeasurementComplexItem::_editing(MeasurementComplexItem::STATE state) {
return
state
==
STATE
::
EDITING
;
}
bool
MeasurementComplexItem
::
_
ready
(
MeasurementComplexItem
::
STATE
state
)
{
bool
MeasurementComplexItem
::
_
idle
(
MeasurementComplexItem
::
STATE
state
)
{
return
state
==
STATE
::
IDLE
;
}
...
...
@@ -380,6 +397,7 @@ void MeasurementComplexItem::_updateRoute() {
if
(
!
editing
())
{
// Reset data.
this
->
_route
.
clear
();
emit
routeChanged
();
this
->
_variantVector
.
clear
();
this
->
_variantNames
.
clear
();
emit
variantNamesChanged
();
...
...
@@ -443,14 +461,14 @@ void MeasurementComplexItem::_updateRoute() {
}
}
else
{
qCDebug
(
MeasurementComplexItemLog
)
<<
"_updateWorker():
plan
data invalid."
;
<<
"_updateWorker():
area
data invalid."
;
return
;
}
}
}
void
MeasurementComplexItem
::
_changeVariant
()
{
if
(
ready
())
{
if
(
idle
())
{
auto
variant
=
this
->
_variant
.
rawValue
().
toUInt
();
// Find old variant and run. Old run corresponts with empty list.
...
...
@@ -470,11 +488,11 @@ void MeasurementComplexItem::_changeVariant() {
if
(
old_variant
!=
std
::
numeric_limits
<
std
::
size_t
>::
max
())
{
// this->_route containes a route, swap it back to
// this->_solutionVector
auto
&
old
VariantCoordinates
=
this
->
_variantVector
[
old_variant
];
old
VariantCoordinates
.
swap
(
this
->
_route
);
auto
&
old
Route
=
this
->
_variantVector
[
old_variant
];
old
Route
.
swap
(
this
->
_route
);
}
auto
&
new
VariantCoordinates
=
this
->
_variantVector
[
variant
];
this
->
_route
.
swap
(
new
VariantCoordinates
);
auto
&
new
Route
=
this
->
_variantVector
[
variant
];
this
->
_route
.
swap
(
new
Route
);
emit
routeChanged
();
}
else
{
// error
qCDebug
(
MeasurementComplexItemLog
)
...
...
@@ -496,7 +514,7 @@ void MeasurementComplexItem::_changeVariant() {
}
void
MeasurementComplexItem
::
_reverseRoute
()
{
if
(
ready
())
{
if
(
idle
())
{
if
(
this
->
_route
.
size
()
>
0
)
{
auto
&
t
=
this
->
_route
;
std
::
reverse
(
t
.
begin
(),
t
.
end
());
...
...
@@ -507,7 +525,7 @@ void MeasurementComplexItem::_reverseRoute() {
ComplexMissionItem
::
ReadyForSaveState
MeasurementComplexItem
::
readyForSaveState
()
const
{
if
(
ready
())
{
if
(
idle
())
{
return
ReadyForSaveState
::
ReadyForSave
;
}
else
{
return
ReadyForSaveState
::
NotReadyForSaveData
;
...
...
@@ -557,8 +575,8 @@ int MeasurementComplexItem::lastSequenceNumber() const {
return
_sequenceNumber
+
std
::
max
(
0
,
this
->
_route
.
size
()
-
1
);
}
bool
MeasurementComplexItem
::
register
Generator
(
const
QString
&
name
,
routing
::
GeneratorBase
*
g
)
{
bool
MeasurementComplexItem
::
add
Generator
(
const
QString
&
name
,
routing
::
GeneratorBase
*
g
)
{
if
(
name
.
isEmpty
())
{
qCDebug
(
MeasurementComplexItemLog
)
<<
"registerGenerator(): empty name string."
;
...
...
@@ -587,7 +605,7 @@ bool MeasurementComplexItem::registerGenerator(const QString &name,
}
}
bool
MeasurementComplexItem
::
unregister
Generator
(
const
QString
&
name
)
{
bool
MeasurementComplexItem
::
remove
Generator
(
const
QString
&
name
)
{
auto
index
=
this
->
_generatorNameList
.
indexOf
(
name
);
if
(
index
>=
0
)
{
// Is this the current generator?
...
...
@@ -615,9 +633,9 @@ bool MeasurementComplexItem::unregisterGenerator(const QString &name) {
}
}
bool
MeasurementComplexItem
::
unregister
Generator
(
int
index
)
{
bool
MeasurementComplexItem
::
remove
Generator
(
int
index
)
{
if
(
index
>
0
&&
index
<
this
->
_generatorNameList
.
size
())
{
return
unregister
Generator
(
this
->
_generatorNameList
.
at
(
index
));
return
remove
Generator
(
this
->
_generatorNameList
.
at
(
index
));
}
else
{
qCDebug
(
MeasurementComplexItemLog
)
<<
"unregisterGenerator(): index ("
<<
index
...
...
@@ -701,7 +719,6 @@ void MeasurementComplexItem::_storeRoutingData(
// Store solutions.
auto
ori
=
this
->
_pAreaData
->
origin
();
ori
.
setAltitude
(
0
);
const
auto
&
transectsENU
=
pRoute
->
transects
;
QVector
<
Variant
>
variantVector
;
const
auto
nSolutions
=
pRoute
->
solutionVector
.
size
();
...
...
@@ -711,60 +728,13 @@ void MeasurementComplexItem::_storeRoutingData(
if
(
solution
.
size
()
>
0
)
{
const
auto
&
route
=
solution
.
at
(
0
);
const
auto
&
path
=
route
.
path
;
const
auto
&
info
=
route
.
info
;
if
(
info
.
size
()
>
1
)
{
// Find index of first waypoint.
std
::
size_t
idxFirst
=
0
;
const
auto
&
infoFirst
=
info
.
at
(
1
);
const
auto
&
firstTransect
=
transectsENU
[
infoFirst
.
index
];
if
(
firstTransect
.
size
()
>
0
)
{
const
auto
&
firstWaypoint
=
infoFirst
.
reversed
?
firstTransect
.
back
()
:
firstTransect
.
front
();
double
th
=
0.01
;
for
(
std
::
size_t
i
=
0
;
i
<
path
.
size
();
++
i
)
{
auto
dist
=
bg
::
distance
(
path
[
i
],
firstWaypoint
);
if
(
dist
<
th
)
{
idxFirst
=
i
;
break
;
}
}
// Find index of last waypoint.
std
::
size_t
idxLast
=
path
.
size
()
-
1
;
const
auto
&
infoLast
=
info
.
at
(
info
.
size
()
-
2
);
const
auto
&
lastTransect
=
transectsENU
[
infoLast
.
index
];
if
(
lastTransect
.
size
()
>
0
)
{
const
auto
&
lastWaypoint
=
infoLast
.
reversed
?
lastTransect
.
front
()
:
lastTransect
.
back
();
for
(
long
i
=
path
.
size
()
-
1
;
i
>=
0
;
--
i
)
{
auto
dist
=
bg
::
distance
(
path
[
i
],
lastWaypoint
);
if
(
dist
<
th
)
{
idxLast
=
i
;
break
;
}
}
// Convert to geo coordinates.
for
(
std
::
size_t
i
=
idxFirst
;
i
<=
idxLast
;
++
i
)
{
auto
&
vertex
=
path
[
i
];
QGeoCoordinate
c
;
snake
::
fromENU
(
ori
,
vertex
,
c
);
var
.
append
(
QVariant
::
fromValue
(
c
));
}
}
else
{
qCDebug
(
MeasurementComplexItemLog
)
<<
"_setTransects(): lastTransect.size() == 0"
;
}
}
else
{
qCDebug
(
MeasurementComplexItemLog
)
<<
"_setTransects(): firstTransect.size() == 0"
;
}
}
else
{
qCDebug
(
MeasurementComplexItemLog
)
<<
"_setTransects(): transectsInfo.size() <= 1"
;
// Convert to geo coordinates.
for
(
const
auto
&
vertex
:
path
)
{
QGeoCoordinate
c
;
snake
::
fromENU
(
ori
,
vertex
,
c
);
var
.
append
(
QVariant
::
fromValue
(
c
));
}
}
else
{
qCDebug
(
MeasurementComplexItemLog
)
...
...
@@ -789,12 +759,14 @@ void MeasurementComplexItem::_storeRoutingData(
}
emit
variantNamesChanged
();
// Set variant to 0.
disconnect
(
&
this
->
_variant
,
&
Fact
::
rawValueChanged
,
this
,
&
MeasurementComplexItem
::
_changeVariant
);
this
->
_variant
.
setCookedValue
(
QVariant
(
0
));
connect
(
&
this
->
_variant
,
&
Fact
::
rawValueChanged
,
this
,
&
MeasurementComplexItem
::
_changeVariant
);
// Select first variant as route.
this
->
_route
.
swap
(
this
->
_variantVector
.
first
());
emit
routeChanged
();
...
...
@@ -817,6 +789,6 @@ bool MeasurementComplexItem::calculating() const {
bool
MeasurementComplexItem
::
editing
()
const
{
return
_editing
(
this
->
_state
);
}
bool
MeasurementComplexItem
::
ready
()
const
{
return
_ready
(
this
->
_state
);
}
bool
MeasurementComplexItem
::
idle
()
const
{
return
_idle
(
this
->
_state
);
}
bool
MeasurementComplexItem
::
followTerrain
()
const
{
return
_followTerrain
;
}
src/MeasurementComplexItem/MeasurementComplexItem.h
View file @
5f9f30c2
...
...
@@ -41,7 +41,7 @@ public:
generatorNameListChanged
)
Q_PROPERTY
(
bool
calculating
READ
calculating
NOTIFY
calculatingChanged
)
Q_PROPERTY
(
bool
editing
READ
editing
NOTIFY
editingChanged
)
Q_PROPERTY
(
bool
ready
READ
ready
NOTIFY
ready
Changed
)
Q_PROPERTY
(
bool
idle
READ
idle
NOTIFY
idle
Changed
)
Q_PROPERTY
(
routing
::
GeneratorBase
*
generator
READ
generator
NOTIFY
generatorChanged
)
Q_PROPERTY
(
int
generatorIndex
READ
generatorIndex
NOTIFY
generatorChanged
)
...
...
@@ -94,9 +94,9 @@ public:
virtual
QString
abbreviation
(
void
)
const
override
final
;
// Generator
bool
register
Generator
(
const
QString
&
name
,
routing
::
GeneratorBase
*
g
);
bool
unregister
Generator
(
const
QString
&
name
);
bool
unregister
Generator
(
int
index
);
bool
add
Generator
(
const
QString
&
name
,
routing
::
GeneratorBase
*
g
);
bool
remove
Generator
(
const
QString
&
name
);
bool
remove
Generator
(
int
index
);
Q_INVOKABLE
bool
switchToGenerator
(
const
QString
&
name
);
Q_INVOKABLE
bool
switchToGenerator
(
int
index
);
QStringList
generatorNameList
();
...
...
@@ -137,7 +137,7 @@ public:
bool
calculating
()
const
;
bool
editing
()
const
;
bool
ready
()
const
;
bool
idle
()
const
;
bool
followTerrain
()
const
;
static
const
char
*
settingsGroup
;
...
...
@@ -154,7 +154,7 @@ signals:
void
calculatingChanged
();
void
editingChanged
();
void
ready
Changed
();
void
idle
Changed
();
void
areaDataChanged
();
void
routeChanged
();
...
...
@@ -173,7 +173,7 @@ private:
void
_setAreaData
(
PtrAreaData
data
);
static
bool
_calculating
(
STATE
state
);
static
bool
_editing
(
STATE
state
);
static
bool
_
ready
(
STATE
state
);
static
bool
_
idle
(
STATE
state
);
// Hirarcical stuff.
PlanMasterController
*
_masterController
;
...
...
src/MeasurementComplexItem/geometry/GeoArea.cc
View file @
5f9f30c2
...
...
@@ -17,13 +17,16 @@ const char *GeoArea::settingsGroup = "GeoArea";
GeoArea
::
GeoArea
(
QObject
*
parent
)
:
QGCMapPolygon
(
parent
)
{
init
();
}
GeoArea
::
GeoArea
(
const
GeoArea
&
other
,
QObject
*
parent
)
:
QGCMapPolygon
(
other
,
parent
)
,
_errorString
(
other
.
_errorString
)
{
:
QGCMapPolygon
(
other
,
parent
)
{
init
();
_errorString
=
other
.
_errorString
;
}
GeoArea
&
GeoArea
::
operator
=
(
const
GeoArea
&
other
)
{
QGCMapPolygon
::
operator
=
(
other
);
_errorString
=
other
.
_errorString
;
return
*
this
;
}
...
...
@@ -63,7 +66,33 @@ bool GeoArea::isCorrect() {
QString
GeoArea
::
errorString
()
const
{
return
this
->
_errorString
;
}
void
GeoArea
::
init
()
{
this
->
setObjectName
(
wimaAreaName
);
}
bool
GeoArea
::
covers
(
const
QGeoCoordinate
&
c
)
{
if
(
GeoArea
::
isCorrect
())
{
auto
origin
=
this
->
pathModel
().
value
<
QGCQGeoCoordinate
*>
(
0
)
->
coordinate
();
snake
::
FPolygon
polygonENU
;
snake
::
areaToEnu
(
origin
,
this
->
pathModel
(),
polygonENU
);
snake
::
FPoint
cENU
;
snake
::
toENU
(
origin
,
c
,
cENU
);
return
bg
::
covered_by
(
cENU
,
polygonENU
);
}
else
{
return
false
;
}
}
void
GeoArea
::
init
()
{
this
->
setObjectName
(
wimaAreaName
);
// connect(this, &GeoArea::pathChanged, [this] {
// if (this->objectName() != "Tile") {
// qDebug() << this->objectName() << " path: " << this->path() << "\n";
// }
// });
// connect(this, &GeoArea::centerChanged, [this] {
// if (this->objectName() != "Tile") {
// qDebug() << this->objectName() << " center: " << this->center() <<
// "\n";
// }
// });
}
void
GeoArea
::
setErrorString
(
const
QString
&
str
)
{
this
->
_errorString
=
str
;
...
...
src/MeasurementComplexItem/geometry/GeoArea.h
View file @
5f9f30c2
...
...
@@ -27,6 +27,13 @@ public:
Q_INVOKABLE
virtual
bool
isCorrect
();
Q_INVOKABLE
QString
errorString
()
const
;
//!
//! \brief covers Checks if GeoArea covers c.
//! \param c
//! \return Returns true if c is inside, or on the border of GeoArea.
//!
Q_INVOKABLE
bool
covers
(
const
QGeoCoordinate
&
c
);
// static Members
static
const
char
*
wimaAreaName
;
static
const
char
*
areaTypeName
;
...
...
src/MeasurementComplexItem/geometry/MeasurementArea.cc
View file @
5f9f30c2
...
...
@@ -23,7 +23,7 @@ TileData &TileData::operator=(const TileData &other) {
const
auto
*
obj
=
other
.
tiles
[
i
];
const
auto
*
tile
=
qobject_cast
<
const
SnakeTile
*>
(
obj
);
if
(
tile
!=
nullptr
)
{
this
->
tiles
.
append
(
new
SnakeTile
(
*
tile
,
this
));
this
->
tiles
.
append
(
tile
->
clone
(
this
));
}
else
{
qCWarning
(
MeasurementAreaLog
)
<<
"TileData::operator=: nullptr"
;
}
...
...
@@ -103,18 +103,41 @@ MeasurementArea::MeasurementArea(const MeasurementArea &other, QObject *parent)
_showTiles
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
showTilesName
],
this
/* QObject parent */
)),
_state
(
STATE
::
IDLE
)
{
init
();
disableUpdate
();
_tileHeight
=
other
.
_tileHeight
;
_tileWidth
=
other
.
_tileWidth
;
_minTileAreaPercent
=
other
.
_minTileAreaPercent
;
_showTiles
=
other
.
_showTiles
;
_progress
=
other
.
_progress
;
_tileData
=
other
.
_tileData
;
init
();
if
(
other
.
ready
())
{
_progress
=
other
.
_progress
;
_tileData
=
other
.
_tileData
;
enableUpdate
();
}
else
{
enableUpdate
();
doUpdate
();
}
}
MeasurementArea
&
MeasurementArea
::
operator
=
(
const
MeasurementArea
&
other
)
{
GeoArea
::
operator
=
(
other
);
disableUpdate
();
_tileHeight
=
other
.
_tileHeight
;
_tileWidth
=
other
.
_tileWidth
;
_minTileAreaPercent
=
other
.
_minTileAreaPercent
;
_showTiles
=
other
.
_showTiles
;
if
(
other
.
ready
())
{
_progress
=
other
.
_progress
;
_tileData
=
other
.
_tileData
;
enableUpdate
();
}
else
{
enableUpdate
();
doUpdate
();
}
return
*
this
;
}
...
...
src/MeasurementComplexItem/geometry/SafeArea.cc
View file @
5f9f30c2
...
...
@@ -73,7 +73,7 @@ void SafeArea::putDepotInside() {
bool
SafeArea
::
setDepot
(
const
QGeoCoordinate
&
newDepot
)
{
if
(
_depot
.
latitude
()
!=
newDepot
.
latitude
()
||
_depot
.
longitude
()
!=
newDepot
.
longitude
())
{
if
(
this
->
co
ntainsCoordinate
(
newDepot
))
{
if
(
this
->
co
vers
(
newDepot
))
{
_depot
=
newDepot
;
_depot
.
setAltitude
(
0
);
emit
depotChanged
();
...
...
@@ -125,7 +125,7 @@ bool SafeArea::loadFromJson(const QJsonObject &json, QString &errorString) {
bool
SafeArea
::
isCorrect
()
{
if
(
GeoArea
::
isCorrect
())
{
if
(
this
->
_depot
.
isValid
())
{
if
(
this
->
co
ntainsCoordinate
(
this
->
_depot
))
{
if
(
this
->
co
vers
(
this
->
_depot
))
{
return
true
;
}
else
{
setErrorString
(
tr
(
"Depot outside Safe Area"
));
...
...
src/MeasurementComplexItem/nemo_interface/SnakeTile.cpp
View file @
5f9f30c2
#include "SnakeTile.h"
SnakeTile
::
SnakeTile
(
QObject
*
parent
)
:
GeoArea
(
parent
)
{}
SnakeTile
::
SnakeTile
(
QObject
*
parent
)
:
GeoArea
(
parent
)
{
init
();
}
SnakeTile
::
SnakeTile
(
const
SnakeTile
&
other
,
QObject
*
parent
)
:
GeoArea
(
parent
)
{
*
this
=
other
;
:
GeoArea
(
other
,
parent
)
{
init
()
;
}
SnakeTile
::~
SnakeTile
()
{}
...
...
@@ -18,3 +18,5 @@ SnakeTile *SnakeTile::clone(QObject *parent) const {
}
void
SnakeTile
::
push_back
(
const
QGeoCoordinate
&
c
)
{
this
->
appendVertex
(
c
);
}
void
SnakeTile
::
init
()
{
this
->
setObjectName
(
"Tile"
);
}
src/MeasurementComplexItem/nemo_interface/SnakeTile.h
View file @
5f9f30c2
...
...
@@ -16,4 +16,7 @@ public:
virtual
SnakeTile
*
clone
(
QObject
*
parent
)
const
;
void
push_back
(
const
QGeoCoordinate
&
c
);
private:
void
init
();
};
src/MeasurementComplexItem/qml/CircularGeneratorMapVisual.qml
View file @
5f9f30c2
import
QtQuick
2.0
import
QGroundControl
1.0
import
QtLocation
5.11
Item
{
id
:
_root
...
...
@@ -11,74 +12,53 @@ Item {
property
var
generator
property
bool
checked
:
false
property
var
_referenceComponent
:
undefined
signal
clicked
()
onVisibleChanged
:
{
if
(
visible
){
_addRefPoint
()
}
else
{
_destroyRefPoint
()
}
}
Component.onCompleted
:
{
if
(
visible
){
_addRefPoint
()
}
}
Item
{
id
:
refPointItem
Component
.
onDestruction
:
{
_destroyRefPoint
()
}
property
var
reference
:
generator
.
reference
function
_addRefPoint
()
{
if
(
!
_referenceComponent
){
_referenceComponent
=
refPointComponent
.
createObject
(
_root
)
map
.
addMapItem
(
_referenceComponent
)
onReferenceChanged
:
{
if
(
mapItem
.
coordinate
!==
reference
){
mapItem
.
coordinate
=
reference
}
}
}
function
_destroyRefPoint
(){
if
(
_referenceComponent
){
map
.
removeMapItem
(
_referenceComponent
)
_referenceComponent
.
destroy
()
_referenceComponent
=
undefined
}
}
MapQuickItem
{
id
:
mapItem
// Ref. point (Base Station)
Component
{
id
:
refPointComponent
DragCoordinate
{
id
:
dragCoordinate
coordinate
:
_root
.
generator
.
reference
anchorPoint.x
:
sourceItem
.
anchorPointX
anchorPoint.y
:
sourceItem
.
anchorPointY
visible
:
refPointItem
.
visible
z
:
QGroundControl
.
zOrderMapItems
property
var
ref
:
_root
.
generator
.
reference
sourceItem
:
MissionItemIndexLabel
{
checked
:
true
label
:
qsTr
(
"
Reference
"
)
highlightSelected
:
true
onClicked
:
_root
.
clicked
(
0
)
visible
:
mapItem
.
visible
z
:
mapItem
.
z
}
}
map
:
_root
.
map
z
:
QGroundControl
.
zOrderMapItems
checked
:
_root
.
checked
coordinate
:
ref
ItemDragger
{
anchor
:
mapItem
z
:
QGroundControl
.
zOrderMapItems
+
1
draggable
:
true
onDragReleased
:
{
syncAndBind
()
}
Component.onCompleted
:
{
syncAndBind
()
}
onClicked
:
{
_root
.
clicked
()
onDragStop
:{
_root
.
generator
.
reference
=
mapItem
.
coordinate
}
}
function
syncAndBind
(){
if
(
coordinate
.
latitude
!==
ref
.
latitude
||
coordinate
.
longitude
!==
ref
.
longitude
){
_root
.
generator
.
reference
=
coordinate
}
coordinate
=
Qt
.
binding
(
function
(){
return
_root
.
generator
.
reference
})
}
Component.onCompleted
:
{
_root
.
map
.
addMapItem
(
mapItem
)
}
}
}
src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml
View file @
5f9f30c2
...
...
@@ -28,10 +28,12 @@ Item {
property
bool
_editing
:
_missionItem
.
editing
property
var
_generator
:
_missionItem
.
generator
property
var
_transectsComponent
:
undefined
property
var
_entryCoordinate
:
undefined
property
var
_exitCoordinate
:
undefined
property
var
_generatorVisuals
:
undefined
property
var
_routeObject
:
undefined
property
var
_entryCoordinateObject
:
undefined
property
var
_exitCoordinateObject
:
undefined
property
var
_generatorObject
:
undefined
property
var
_entryArrowObject
:
undefined
property
var
_exitArrowObject
:
undefined
property
bool
_isCurrentItem
:
_missionItem
.
isCurrentItem
...
...
@@ -53,19 +55,23 @@ Item {
Component.onCompleted
:
{
console
.
assert
(
map
!=
undefined
,
"
please set the map property
"
)
_addEntryCoordinate
()
_addExitCoordinate
()
_addTransectsComponent
()
_addGeneratorVisuals
()
var
bbox
=
boundingBox
()
_missionItem
.
areaData
.
initialize
(
bbox
[
0
],
bbox
[
1
])
// _addEntryCoordinate()
// _addExitCoordinate()
_addTransects
()
_addGeneratorVisuals
()
_addEntryArrow
()
_addExitArrow
()
}
Component.onDestruction
:
{
_destroyEntryCoordinate
()
_destroyExitCoordinate
()
_destroyTransects
Component
()
//
_destroyEntryCoordinate()
//
_destroyExitCoordinate()
_destroyTransects
()
_destroyGeneratorVisuals
()
_destroyEntryArrow
()
_destroyExitArrow
()
}
on_GeneratorChanged
:
{
...
...
@@ -78,11 +84,10 @@ Item {
id
:
visualTransectsComponent
MapPolyline
{
visible
:
!
_missionItem
.
editing
line.color
:
"
white
"
line.width
:
2
path
:
_missionItem
.
route
onPathChanged
:
console
.
log
(
"
path:
"
+
path
)
}
}
...
...
@@ -126,6 +131,37 @@ Item {
}
}
// Entry arrow
Component
{
id
:
entryArrowComponent
MapLineArrow
{
property
int
length
:
_missionItem
.
route
.
length
property
var
route
:
_missionItem
.
route
fromCoord
:
length
>
1
?
route
[
0
]
:
QtPositioning
.
coordinate
()
toCoord
:
length
>
1
?
route
[
1
]
:
QtPositioning
.
coordinate
()
arrowPosition
:
2
visible
:
length
>
1
&&
!
_missionItem
.
editing
opacity
:
_root
.
opacity
}
}
// Exit arrow
Component
{
id
:
exitArrowComponent
MapLineArrow
{
property
int
length
:
_missionItem
.
route
.
length
property
var
route
:
_missionItem
.
route
fromCoord
:
length
>
3
?
route
[
length
-
2
]
:
QtPositioning
.
coordinate
()
toCoord
:
length
>
3
?
route
[
length
-
1
]
:
QtPositioning
.
coordinate
()
arrowPosition
:
2
visible
:
length
>
3
&&
!
_missionItem
.
editing
opacity
:
_root
.
opacity
}
}
// GeoAreas
Repeater
{
...
...
@@ -138,76 +174,101 @@ Item {
// Generator visuals
function
_addGeneratorVisuals
(){
if
(
_generator
.
mapVisualQml
&&
!
_generator
Visuals
)
{
if
(
_generator
.
mapVisualQml
&&
!
_generator
Object
)
{
var
component
=
Qt
.
createComponent
(
_generator
.
mapVisualQml
)
if
(
component
.
status
===
Component
.
Error
)
{
console
.
log
(
"
Error loading Qml:
"
,
_generator
.
mapVisualQml
,
component
.
errorString
())
}
else
{
_generatorVisuals
=
component
.
createObject
(
_root
,
{
"
map
"
:
_root
.
map
,
"
generator
"
:
_root
.
_generator
,
"
checked
"
:
Qt
.
binding
(
function
(){
return
_root
.
_isCurrentItem
})
})
_generatorVisuals
.
clicked
.
connect
(
_generatorObject
=
component
.
createObject
(
_root
,
{
"
map
"
:
_root
.
map
,
"
generator
"
:
_root
.
_generator
,
"
checked
"
:
Qt
.
binding
(
function
(){
return
_root
.
_isCurrentItem
})
})
_generatorObject
.
clicked
.
connect
(
function
(){
_root
.
clicked
(
_missionItem
.
sequenceNumber
)})
}
}
}
function
_destroyGeneratorVisuals
(){
if
(
_generator
Visuals
){
_generator
Visuals
.
destroy
()
_generator
Visuals
=
undefined
if
(
_generator
Object
){
_generator
Object
.
destroy
()
_generator
Object
=
undefined
}
}
function
_addTransects
Component
(){
if
(
!
_
transectsComponen
t
){
_
transectsComponent
=
visualTransectsComponent
.
createObject
(
_root
)
map
.
addMapItem
(
_
transectsComponen
t
)
function
_addTransects
(){
if
(
!
_
routeObjec
t
){
_
routeObject
=
visualTransectsComponent
.
createObject
(
_root
)
map
.
addMapItem
(
_
routeObjec
t
)
}
}
function
_addExitCoordinate
(){
if
(
!
_exitCoordinate
){
_exitCoordinate
=
exitPointComponent
.
createObject
(
_root
)
map
.
addMapItem
(
_exitCoordinate
)
if
(
!
_exitCoordinate
Object
){
_exitCoordinate
Object
=
exitPointComponent
.
createObject
(
_root
)
map
.
addMapItem
(
_exitCoordinate
Object
)
}
}
function
_addEntryCoordinate
(){
if
(
!
_entryCoordinate
){
_entryCoordinate
=
entryPointComponent
.
createObject
(
_root
)
map
.
addMapItem
(
_entryCoordinate
)
if
(
!
_entryCoordinateObject
){
_entryCoordinateObject
=
entryPointComponent
.
createObject
(
_root
)
map
.
addMapItem
(
_entryCoordinateObject
)
}
}
function
_addEntryArrow
(){
if
(
!
_entryArrowObject
){
_entryArrowObject
=
entryArrowComponent
.
createObject
(
_root
)
map
.
addMapItem
(
_entryArrowObject
)
}
}
function
_addExitArrow
(){
if
(
!
_exitArrowObject
){
_exitArrowObject
=
exitArrowComponent
.
createObject
(
_root
)
map
.
addMapItem
(
_exitArrowObject
)
}
}
function
_destroyEntryCoordinate
(){
if
(
_entryCoordinate
){
map
.
removeMapItem
(
_entryCoordinate
)
_entryCoordinate
.
destroy
()
_entryCoordinate
=
undefined
if
(
_entryCoordinate
Object
){
map
.
removeMapItem
(
_entryCoordinate
Object
)
_entryCoordinate
Object
.
destroy
()
_entryCoordinate
Object
=
undefined
}
}
function
_destroyExitCoordinate
(){
if
(
_exitCoordinate
){
map
.
removeMapItem
(
_exitCoordinate
)
_exitCoordinate
.
destroy
()
_exitCoordinate
=
undefined
if
(
_exitCoordinateObject
){
map
.
removeMapItem
(
_exitCoordinateObject
)
_exitCoordinateObject
.
destroy
()
_exitCoordinateObject
=
undefined
}
}
function
_destroyTransects
(){
if
(
_routeObject
){
map
.
removeMapItem
(
_routeObject
)
_routeObject
.
destroy
()
_routeObject
=
undefined
}
}
function
_destroyEntryArrow
(){
if
(
_entryArrowObject
){
map
.
removeMapItem
(
_entryArrowObject
)
_entryArrowObject
.
destroy
()
_entryArrowObject
=
undefined
}
}
function
_destroy
TransectsComponent
(){
if
(
_
transectsComponen
t
){
map
.
removeMapItem
(
_
transectsComponen
t
)
_
transectsComponen
t
.
destroy
()
_
transectsComponen
t
=
undefined
function
_destroy
ExitArrow
(){
if
(
_
exitArrowObjec
t
){
map
.
removeMapItem
(
_
exitArrowObjec
t
)
_
exitArrowObjec
t
.
destroy
()
_
exitArrowObjec
t
=
undefined
}
}
...
...
src/MeasurementComplexItem/qml/ParameterEditor.qml
View file @
5f9f30c2
...
...
@@ -68,29 +68,36 @@ ColumnLayout {
}
GridLayout
{
Layout.columnSpan
:
2
Layout.fillWidth
:
true
Layout.maximumWidth
:
parent
.
width
columnSpacing
:
_margin
rowSpacing
:
_margin
columns
:
6
ExclusiveGroup
{
id
:
variantGroup
}
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
===
variant
Repeater
.
variant
checked
:
index
===
variant
text
:
variantRepeater
.
names
[
index
]
?
variantRepeater
.
names
[
index
]:
""
property
int
variant
:
missionItem
.
variant
.
value
onVariantChanged
:
{
if
(
variant
===
index
){
checked
=
true
}
}
onCheckedChanged
:
{
if
(
checked
){
if
(
checked
&&
variant
!==
index
){
missionItem
.
variant
.
value
=
index
}
checked
=
Qt
.
binding
(
function
(){
return
index
===
variantRepeater
.
variant
})
}
}
}
// variant repeater
...
...
@@ -135,6 +142,13 @@ ColumnLayout {
visible
:
generatorHeader
.
checked
}
QGCButton
{
text
:
qsTr
(
"
Reverse
"
)
onClicked
:
missionItem
.
reverseRoute
()
Layout.columnSpan
:
2
Layout.fillWidth
:
true
}
// bussy indicator
ColumnLayout
{
Layout.fillWidth
:
true
...
...
src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml
View file @
5f9f30c2
...
...
@@ -46,57 +46,47 @@ Item {
interiorOpacity
:
0.3
}
Loader
{
id
:
depotLoader
sourceComponent
:
depotComponent
}
// Depot Point.
Component
{
id
:
depotComponent
Item
{
id
:
depotMapItem
Item
{
id
:
depotMapItem
MapQuickItem
{
id
:
mapItem
MapQuickItem
{
id
:
mapItem
coordinate
:
_root
.
geoArea
.
depot
anchorPoint.x
:
sourceItem
.
anchorPointX
anchorPoint.y
:
sourceItem
.
anchorPointY
visible
:
tru
e
z
:
QGroundControl
.
zOrderMapItems
coordinate
:
_root
.
geoArea
.
depot
anchorPoint.x
:
sourceItem
.
anchorPointX
anchorPoint.y
:
sourceItem
.
anchorPointY
visible
:
depotMapItem
.
visibl
e
z
:
QGroundControl
.
zOrderMapItems
Component.onCompleted
:
{
coordinate
=
Qt
.
binding
(
function
(){
return
_root
.
geoArea
.
depot
})
}
Component.onCompleted
:
{
coordinate
=
Qt
.
binding
(
function
(){
return
_root
.
geoArea
.
depot
})
}
sourceItem
:
MissionItemIndexLabel
{
checked
:
true
label
:
qsTr
(
"
Depot
"
)
highlightSelected
:
true
onClicked
:
_root
.
clicked
(
0
)
visible
:
mapItem
.
visible
z
:
mapItem
.
z
}
sourceItem
:
MissionItemIndexLabel
{
checked
:
true
label
:
qsTr
(
"
Depot
"
)
highlightSelected
:
true
onClicked
:
_root
.
clicked
(
0
)
visible
:
mapItem
.
visible
z
:
mapItem
.
z
}
}
ItemDragger
{
anchor
:
mapItem
z
:
QGroundControl
.
zOrderMapItems
+
1
draggable
:
_root
.
geoArea
.
interactive
ItemDragger
{
anchor
:
mapItem
z
:
QGroundControl
.
zOrderMapItems
+
1
draggable
:
_root
.
geoArea
.
interactive
onDragStop
:{
_root
.
geoArea
.
depot
=
mapItem
.
coordinate
mapItem
.
coordinate
=
Qt
.
binding
(
function
(){
return
_root
.
geoArea
.
depot
})
}
onDragStop
:{
_root
.
geoArea
.
depot
=
mapItem
.
coordinate
mapItem
.
coordinate
=
Qt
.
binding
(
function
(){
return
_root
.
geoArea
.
depot
})
}
}
Component.onCompleted
:
{
_root
.
map
.
addMapItem
(
mapItem
)
}
Component.onCompleted
:
{
_root
.
map
.
addMapItem
(
mapItem
)
}
}
}
src/MissionManager/QGCMapPolygon.cc
View file @
5f9f30c2
...
...
@@ -8,576 +8,560 @@
****************************************************************************/
#include "QGCMapPolygon.h"
#include "QGCGeo.h"
#include "JsonHelper.h"
#include "QGCQGeoCoordinate.h"
#include "QGCApplication.h"
#include "
ShapeFileHelper
.h"
#include "
QGCGeo
.h"
#include "QGCLoggingCategory.h"
#include "QGCQGeoCoordinate.h"
#include "ShapeFileHelper.h"
#include <QGeoRectangle>
#include <QDebug>
#include <QDomDocument>
#include <QFile>
#include <QGeoRectangle>
#include <QJsonArray>
#include <QLineF>
#include <QFile>
#include <QDomDocument>
const
char
*
QGCMapPolygon
::
jsonPolygonKey
=
"polygon"
;
const
char
*
QGCMapPolygon
::
jsonPolygonKey
=
"polygon"
;
QGCMapPolygon
::
QGCMapPolygon
(
QObject
*
parent
)
:
QObject
(
parent
)
,
_dirty
(
false
)
,
_centerDrag
(
false
)
,
_ignoreCenterUpdates
(
false
)
,
_interactive
(
false
)
,
_resetActive
(
false
)
{
_init
();
QGCMapPolygon
::
QGCMapPolygon
(
QObject
*
parent
)
:
QObject
(
parent
),
_dirty
(
false
),
_centerDrag
(
false
),
_ignoreCenterUpdates
(
false
),
_interactive
(
false
),
_resetActive
(
false
)
{
_init
();
}
QGCMapPolygon
::
QGCMapPolygon
(
const
QGCMapPolygon
&
other
,
QObject
*
parent
)
:
QObject
(
parent
)
,
_dirty
(
false
)
,
_centerDrag
(
false
)
,
_ignoreCenterUpdates
(
false
)
,
_interactive
(
false
)
,
_resetActive
(
false
)
{
*
this
=
other
;
_init
();
QGCMapPolygon
::
QGCMapPolygon
(
const
QGCMapPolygon
&
other
,
QObject
*
parent
)
:
QObject
(
parent
),
_dirty
(
false
),
_centerDrag
(
false
),
_ignoreCenterUpdates
(
false
),
_interactive
(
false
),
_resetActive
(
false
)
{
_init
();
*
this
=
other
;
}
void
QGCMapPolygon
::
_init
(
void
)
{
connect
(
&
_polygonModel
,
&
QmlObjectListModel
::
dirtyChanged
,
this
,
&
QGCMapPolygon
::
_polygonModelDirtyChanged
);
connect
(
&
_polygonModel
,
&
QmlObjectListModel
::
countChanged
,
this
,
&
QGCMapPolygon
::
_polygonModelCountChanged
);
void
QGCMapPolygon
::
_init
(
void
)
{
connect
(
&
_polygonModel
,
&
QmlObjectListModel
::
dirtyChanged
,
this
,
&
QGCMapPolygon
::
_polygonModelDirtyChanged
);
connect
(
&
_polygonModel
,
&
QmlObjectListModel
::
countChanged
,
this
,
&
QGCMapPolygon
::
_polygonModelCountChanged
);
connect
(
this
,
&
QGCMapPolygon
::
pathChanged
,
this
,
&
QGCMapPolygon
::
_updateCenter
);
connect
(
this
,
&
QGCMapPolygon
::
countChanged
,
this
,
&
QGCMapPolygon
::
isValidChanged
);
connect
(
this
,
&
QGCMapPolygon
::
countChanged
,
this
,
&
QGCMapPolygon
::
isEmptyChanged
);
connect
(
this
,
&
QGCMapPolygon
::
pathChanged
,
this
,
&
QGCMapPolygon
::
_updateCenter
);
connect
(
this
,
&
QGCMapPolygon
::
countChanged
,
this
,
&
QGCMapPolygon
::
isValidChanged
);
connect
(
this
,
&
QGCMapPolygon
::
countChanged
,
this
,
&
QGCMapPolygon
::
isEmptyChanged
);
}
const
QGCMapPolygon
&
QGCMapPolygon
::
operator
=
(
const
QGCMapPolygon
&
other
)
{
clear
();
const
QGCMapPolygon
&
QGCMapPolygon
::
operator
=
(
const
QGCMapPolygon
&
other
)
{
clear
();
QVariantList
vertices
=
other
.
path
();
QList
<
QGeoCoordinate
>
rgCoord
;
for
(
const
QVariant
&
vertexVar
:
vertices
)
{
rgCoord
.
append
(
vertexVar
.
value
<
QGeoCoordinate
>
());
}
appendVertices
(
rgCoord
);
QVariantList
vertices
=
other
.
path
();
QList
<
QGeoCoordinate
>
rgCoord
;
for
(
const
QVariant
&
vertexVar
:
vertices
)
{
rgCoord
.
append
(
vertexVar
.
value
<
QGeoCoordinate
>
());
}
appendVertices
(
rgCoord
);
setDirty
(
true
);
setDirty
(
true
);
return
*
this
;
return
*
this
;
}
void
QGCMapPolygon
::
clear
(
void
)
{
// Bug workaround, see below
while
(
_polygonPath
.
count
()
>
1
)
{
_polygonPath
.
takeLast
();
}
emit
pathChanged
();
void
QGCMapPolygon
::
clear
(
void
)
{
// Bug workaround, see below
while
(
_polygonPath
.
count
()
>
1
)
{
_polygonPath
.
takeLast
();
}
emit
pathChanged
();
// Although this code should remove the polygon from the map it doesn't. There appears
// to be a bug in QGCMapPolygon 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
();
// Although this code should remove the polygon from the map it doesn't. There
// appears to be a bug in QGCMapPolygon 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
();
_polygonModel
.
clearAndDeleteContents
();
_polygonModel
.
clearAndDeleteContents
();
emit
cleared
();
emit
cleared
();
setDirty
(
true
);
setDirty
(
true
);
}
void
QGCMapPolygon
::
adjustVertex
(
int
vertexIndex
,
const
QGeoCoordinate
coordinate
)
{
_polygonPath
[
vertexIndex
]
=
QVariant
::
fromValue
(
coordinate
);
_polygonModel
.
value
<
QGCQGeoCoordinate
*>
(
vertexIndex
)
->
setCoordinate
(
coordinate
);
if
(
!
_centerDrag
)
{
// When dragging center we don't signal path changed until all vertices are updated
emit
pathChanged
();
}
setDirty
(
true
);
void
QGCMapPolygon
::
adjustVertex
(
int
vertexIndex
,
const
QGeoCoordinate
coordinate
)
{
_polygonPath
[
vertexIndex
]
=
QVariant
::
fromValue
(
coordinate
);
_polygonModel
.
value
<
QGCQGeoCoordinate
*>
(
vertexIndex
)
->
setCoordinate
(
coordinate
);
if
(
!
_centerDrag
)
{
// When dragging center we don't signal path changed until all vertices are
// updated
emit
pathChanged
();
}
setDirty
(
true
);
}
void
QGCMapPolygon
::
setDirty
(
bool
dirty
)
{
if
(
_dirty
!=
dirty
)
{
_dirty
=
dirty
;
if
(
!
dirty
)
{
_polygonModel
.
setDirty
(
false
);
}
emit
dirtyChanged
(
dirty
);
void
QGCMapPolygon
::
setDirty
(
bool
dirty
)
{
if
(
_dirty
!=
dirty
)
{
_dirty
=
dirty
;
if
(
!
dirty
)
{
_polygonModel
.
setDirty
(
false
);
}
emit
dirtyChanged
(
dirty
);
}
}
QGeoCoordinate
QGCMapPolygon
::
_coordFromPointF
(
const
QPointF
&
point
)
const
{
QGeoCoordinate
coord
;
QGeoCoordinate
QGCMapPolygon
::
_coordFromPointF
(
const
QPointF
&
point
)
const
{
QGeoCoordinate
coord
;
if
(
_polygonPath
.
count
()
>
0
)
{
QGeoCoordinate
tangentOrigin
=
_polygonPath
[
0
].
value
<
QGeoCoordinate
>
();
convertNedToGeo
(
-
point
.
y
(),
point
.
x
(),
0
,
tangentOrigin
,
&
coord
);
}
if
(
_polygonPath
.
count
()
>
0
)
{
QGeoCoordinate
tangentOrigin
=
_polygonPath
[
0
].
value
<
QGeoCoordinate
>
();
convertNedToGeo
(
-
point
.
y
(),
point
.
x
(),
0
,
tangentOrigin
,
&
coord
);
}
return
coord
;
return
coord
;
}
QPointF
QGCMapPolygon
::
_pointFFromCoord
(
const
QGeoCoordinate
&
coordinate
)
const
{
if
(
_polygonPath
.
count
()
>
0
)
{
double
y
,
x
,
down
;
QGeoCoordinate
tangentOrigin
=
_polygonPath
[
0
].
value
<
QGeoCoordinate
>
();
QPointF
QGCMapPolygon
::
_pointFFromCoord
(
const
QGeoCoordinate
&
coordinate
)
const
{
if
(
_polygonPath
.
count
()
>
0
)
{
double
y
,
x
,
down
;
QGeoCoordinate
tangentOrigin
=
_polygonPath
[
0
].
value
<
QGeoCoordinate
>
();
convertGeoToNed
(
coordinate
,
tangentOrigin
,
&
y
,
&
x
,
&
down
);
return
QPointF
(
x
,
-
y
);
}
convertGeoToNed
(
coordinate
,
tangentOrigin
,
&
y
,
&
x
,
&
down
);
return
QPointF
(
x
,
-
y
);
}
return
QPointF
();
return
QPointF
();
}
QPolygonF
QGCMapPolygon
::
_toPolygonF
(
void
)
const
{
QPolygonF
polygon
;
QPolygonF
QGCMapPolygon
::
_toPolygonF
(
void
)
const
{
QPolygonF
polygon
;
if
(
_polygonPath
.
count
()
>
2
)
{
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
polygon
.
append
(
_pointFFromCoord
(
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
()));
}
if
(
_polygonPath
.
count
()
>
2
)
{
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
polygon
.
append
(
_pointFFromCoord
(
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
()));
}
}
return
polygon
;
return
polygon
;
}
bool
QGCMapPolygon
::
containsCoordinate
(
const
QGeoCoordinate
&
coordinate
)
const
{
if
(
_polygonPath
.
count
()
>
2
)
{
return
_toPolygonF
().
containsPoint
(
_pointFFromCoord
(
coordinate
),
Qt
::
OddEvenFill
);
}
else
{
return
false
;
}
bool
QGCMapPolygon
::
containsCoordinate
(
const
QGeoCoordinate
&
coordinate
)
const
{
if
(
_polygonPath
.
count
()
>
2
)
{
return
_toPolygonF
().
containsPoint
(
_pointFFromCoord
(
coordinate
),
Qt
::
OddEvenFill
);
}
else
{
return
false
;
}
}
void
QGCMapPolygon
::
setPath
(
const
QList
<
QGeoCoordinate
>&
path
)
{
_polygonPath
.
clear
();
_polygonModel
.
clearAndDeleteContents
();
for
(
const
QGeoCoordinate
&
coord
:
path
)
{
_polygonPath
.
append
(
QVariant
::
fromValue
(
coord
));
_polygonModel
.
append
(
new
QGCQGeoCoordinate
(
coord
,
this
));
}
void
QGCMapPolygon
::
setPath
(
const
QList
<
QGeoCoordinate
>
&
path
)
{
_polygonPath
.
clear
();
_polygonModel
.
clearAndDeleteContents
();
for
(
const
QGeoCoordinate
&
coord
:
path
)
{
_polygonPath
.
append
(
QVariant
::
fromValue
(
coord
));
_polygonModel
.
append
(
new
QGCQGeoCoordinate
(
coord
,
this
));
}
setDirty
(
true
);
emit
pathChanged
();
setDirty
(
true
);
emit
pathChanged
();
}
void
QGCMapPolygon
::
setPath
(
const
QVariantList
&
path
)
{
_polygonPath
=
path
;
void
QGCMapPolygon
::
setPath
(
const
QVariantList
&
path
)
{
_polygonPath
=
path
;
_polygonModel
.
clearAndDeleteContents
();
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
_polygonModel
.
append
(
new
QGCQGeoCoordinate
(
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
(),
this
));
}
_polygonModel
.
clearAndDeleteContents
();
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
_polygonModel
.
append
(
new
QGCQGeoCoordinate
(
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
(),
this
));
}
setDirty
(
true
);
emit
pathChanged
();
setDirty
(
true
);
emit
pathChanged
();
}
void
QGCMapPolygon
::
saveToJson
(
QJsonObject
&
json
)
{
QJsonValue
jsonValue
;
void
QGCMapPolygon
::
saveToJson
(
QJsonObject
&
json
)
{
QJsonValue
jsonValue
;
JsonHelper
::
saveGeoCoordinateArray
(
_polygonPath
,
false
/* writeAltitude*/
,
jsonValue
);
json
.
insert
(
jsonPolygonKey
,
jsonValue
);
setDirty
(
false
);
JsonHelper
::
saveGeoCoordinateArray
(
_polygonPath
,
false
/* writeAltitude*/
,
jsonValue
);
json
.
insert
(
jsonPolygonKey
,
jsonValue
);
setDirty
(
false
);
}
bool
QGCMapPolygon
::
loadFromJson
(
const
QJsonObject
&
json
,
bool
required
,
QString
&
errorString
)
{
errorString
.
clear
();
clear
();
bool
QGCMapPolygon
::
loadFromJson
(
const
QJsonObject
&
json
,
bool
required
,
QString
&
errorString
)
{
errorString
.
clear
();
clear
();
if
(
required
)
{
if
(
!
JsonHelper
::
validateRequiredKeys
(
json
,
QStringList
(
jsonPolygonKey
),
errorString
))
{
return
false
;
}
}
else
if
(
!
json
.
contains
(
jsonPolygonKey
))
{
return
true
;
if
(
required
)
{
if
(
!
JsonHelper
::
validateRequiredKeys
(
json
,
QStringList
(
jsonPolygonKey
),
errorString
))
{
return
false
;
}
}
else
if
(
!
json
.
contains
(
jsonPolygonKey
))
{
return
true
;
}
if
(
!
JsonHelper
::
loadGeoCoordinateArray
(
json
[
jsonPolygonKey
],
false
/* altitudeRequired */
,
_polygonPath
,
errorString
))
{
return
false
;
}
if
(
!
JsonHelper
::
loadGeoCoordinateArray
(
json
[
jsonPolygonKey
],
false
/* altitudeRequired */
,
_polygonPath
,
errorString
))
{
return
false
;
}
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
_polygonModel
.
append
(
new
QGCQGeoCoordinate
(
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
(),
this
));
}
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
_polygonModel
.
append
(
new
QGCQGeoCoordinate
(
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
(),
this
));
}
setDirty
(
false
);
emit
pathChanged
();
setDirty
(
false
);
emit
pathChanged
();
return
true
;
return
true
;
}
QList
<
QGeoCoordinate
>
QGCMapPolygon
::
coordinateList
(
void
)
const
{
QList
<
QGeoCoordinate
>
coords
;
QList
<
QGeoCoordinate
>
QGCMapPolygon
::
coordinateList
(
void
)
const
{
QList
<
QGeoCoordinate
>
coords
;
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
coords
.
append
(
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
());
}
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
coords
.
append
(
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
());
}
return
coords
;
return
coords
;
}
void
QGCMapPolygon
::
splitPolygonSegment
(
int
vertexIndex
)
{
int
nextIndex
=
vertexIndex
+
1
;
if
(
nextIndex
>
_polygonPath
.
length
()
-
1
)
{
nextIndex
=
0
;
}
void
QGCMapPolygon
::
splitPolygonSegment
(
int
vertexIndex
)
{
int
nextIndex
=
vertexIndex
+
1
;
if
(
nextIndex
>
_polygonPath
.
length
()
-
1
)
{
nextIndex
=
0
;
}
QGeoCoordinate
firstVertex
=
_polygonPath
[
vertexIndex
].
value
<
QGeoCoordinate
>
();
QGeoCoordinate
nextVertex
=
_polygonPath
[
nextIndex
].
value
<
QGeoCoordinate
>
();
QGeoCoordinate
firstVertex
=
_polygonPath
[
vertexIndex
].
value
<
QGeoCoordinate
>
();
QGeoCoordinate
nextVertex
=
_polygonPath
[
nextIndex
].
value
<
QGeoCoordinate
>
();
double
distance
=
firstVertex
.
distanceTo
(
nextVertex
);
double
azimuth
=
firstVertex
.
azimuthTo
(
nextVertex
);
QGeoCoordinate
newVertex
=
firstVertex
.
atDistanceAndAzimuth
(
distance
/
2
,
azimuth
);
double
distance
=
firstVertex
.
distanceTo
(
nextVertex
);
double
azimuth
=
firstVertex
.
azimuthTo
(
nextVertex
);
QGeoCoordinate
newVertex
=
firstVertex
.
atDistanceAndAzimuth
(
distance
/
2
,
azimuth
);
if
(
nextIndex
==
0
)
{
appendVertex
(
newVertex
);
}
else
{
_polygonModel
.
insert
(
nextIndex
,
new
QGCQGeoCoordinate
(
newVertex
,
this
));
_polygonPath
.
insert
(
nextIndex
,
QVariant
::
fromValue
(
newVertex
));
emit
pathChanged
();
}
if
(
nextIndex
==
0
)
{
appendVertex
(
newVertex
);
}
else
{
_polygonModel
.
insert
(
nextIndex
,
new
QGCQGeoCoordinate
(
newVertex
,
this
));
_polygonPath
.
insert
(
nextIndex
,
QVariant
::
fromValue
(
newVertex
));
emit
pathChanged
();
}
}
void
QGCMapPolygon
::
appendVertex
(
const
QGeoCoordinate
&
coordinate
)
{
_polygonPath
.
append
(
QVariant
::
fromValue
(
coordinate
));
_polygonModel
.
append
(
new
QGCQGeoCoordinate
(
coordinate
,
this
));
emit
pathChanged
();
void
QGCMapPolygon
::
appendVertex
(
const
QGeoCoordinate
&
coordinate
)
{
_polygonPath
.
append
(
QVariant
::
fromValue
(
coordinate
));
_polygonModel
.
append
(
new
QGCQGeoCoordinate
(
coordinate
,
this
));
emit
pathChanged
();
}
void
QGCMapPolygon
::
appendVertices
(
const
QList
<
QGeoCoordinate
>&
coordinates
)
{
QList
<
QObject
*>
objects
;
void
QGCMapPolygon
::
appendVertices
(
const
QList
<
QGeoCoordinate
>
&
coordinates
)
{
QList
<
QObject
*>
objects
;
_beginResetIfNotActive
();
for
(
const
QGeoCoordinate
&
coordinate
:
coordinates
)
{
objects
.
append
(
new
QGCQGeoCoordinate
(
coordinate
,
this
));
_polygonPath
.
append
(
QVariant
::
fromValue
(
coordinate
));
}
_polygonModel
.
append
(
objects
);
_endResetIfNotActive
();
_beginResetIfNotActive
();
for
(
const
QGeoCoordinate
&
coordinate
:
coordinates
)
{
objects
.
append
(
new
QGCQGeoCoordinate
(
coordinate
,
this
));
_polygonPath
.
append
(
QVariant
::
fromValue
(
coordinate
));
}
_polygonModel
.
append
(
objects
);
_endResetIfNotActive
();
emit
pathChanged
();
emit
pathChanged
();
}
void
QGCMapPolygon
::
appendVertices
(
const
QVariantList
&
varCoords
)
{
QList
<
QGeoCoordinate
>
rgCoords
;
for
(
const
QVariant
&
varCoord
:
varCoords
)
{
rgCoords
.
append
(
varCoord
.
value
<
QGeoCoordinate
>
());
}
appendVertices
(
rgCoords
);
void
QGCMapPolygon
::
appendVertices
(
const
QVariantList
&
varCoords
)
{
QList
<
QGeoCoordinate
>
rgCoords
;
for
(
const
QVariant
&
varCoord
:
varCoords
)
{
rgCoords
.
append
(
varCoord
.
value
<
QGeoCoordinate
>
());
}
appendVertices
(
rgCoords
);
}
void
QGCMapPolygon
::
_polygonModelDirtyChanged
(
bool
dirty
)
{
if
(
dirty
)
{
setDirty
(
true
);
}
void
QGCMapPolygon
::
_polygonModelDirtyChanged
(
bool
dirty
)
{
if
(
dirty
)
{
setDirty
(
true
);
}
}
void
QGCMapPolygon
::
removeVertex
(
int
vertexIndex
)
{
if
(
vertexIndex
<
0
&&
vertexIndex
>
_polygonPath
.
length
()
-
1
)
{
qWarning
()
<<
"Call to removePolygonCoordinate with bad vertexIndex:count"
<<
vertexIndex
<<
_polygonPath
.
length
();
return
;
}
void
QGCMapPolygon
::
removeVertex
(
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
;
}
if
(
_polygonPath
.
length
()
<=
3
)
{
// Don't allow the user to trash the polygon
return
;
}
QObject
*
coordObj
=
_polygonModel
.
removeAt
(
vertexIndex
);
coordObj
->
deleteLater
();
if
(
vertexIndex
==
_selectedVertexIndex
)
{
selectVertex
(
-
1
);
}
else
if
(
vertexIndex
<
_selectedVertexIndex
)
{
selectVertex
(
_selectedVertexIndex
-
1
);
}
// else do nothing - keep current selected vertex
QObject
*
coordObj
=
_polygonModel
.
removeAt
(
vertexIndex
);
coordObj
->
deleteLater
();
if
(
vertexIndex
==
_selectedVertexIndex
)
{
selectVertex
(
-
1
);
}
else
if
(
vertexIndex
<
_selectedVertexIndex
)
{
selectVertex
(
_selectedVertexIndex
-
1
);
}
// else do nothing - keep current selected vertex
_polygonPath
.
removeAt
(
vertexIndex
);
emit
pathChanged
();
_polygonPath
.
removeAt
(
vertexIndex
);
emit
pathChanged
();
}
void
QGCMapPolygon
::
_polygonModelCountChanged
(
int
count
)
{
emit
countChanged
(
count
);
}
void
QGCMapPolygon
::
_updateCenter
(
void
)
{
if
(
!
_ignoreCenterUpdates
)
{
QGeoCoordinate
center
;
if
(
_polygonPath
.
count
()
>
2
)
{
QPointF
centroid
(
0
,
0
);
QPolygonF
polygonF
=
_toPolygonF
();
for
(
int
i
=
0
;
i
<
polygonF
.
count
();
i
++
)
{
centroid
+=
polygonF
[
i
];
}
center
=
_coordFromPointF
(
QPointF
(
centroid
.
x
()
/
polygonF
.
count
(),
centroid
.
y
()
/
polygonF
.
count
()));
}
if
(
_center
!=
center
)
{
_center
=
center
;
emit
centerChanged
(
center
);
}
}
void
QGCMapPolygon
::
_polygonModelCountChanged
(
int
count
)
{
emit
countChanged
(
count
);
}
void
QGCMapPolygon
::
setCenter
(
QGeoCoordinate
newCenter
)
{
if
(
newCenter
!=
_center
)
{
_ignoreCenterUpdates
=
true
;
void
QGCMapPolygon
::
_updateCenter
(
void
)
{
if
(
!
_ignoreCenterUpdates
)
{
QGeoCoordinate
center
;
// Adjust polygon vertices to new center
double
distance
=
_center
.
distanceTo
(
newCenter
);
double
azimuth
=
_center
.
azimuthTo
(
newCenter
);
if
(
_polygonPath
.
count
()
>
2
)
{
QPointF
centroid
(
0
,
0
);
QPolygonF
polygonF
=
_toPolygonF
();
for
(
int
i
=
0
;
i
<
polygonF
.
count
();
i
++
)
{
centroid
+=
polygonF
[
i
];
}
center
=
_coordFromPointF
(
QPointF
(
centroid
.
x
()
/
polygonF
.
count
(),
centroid
.
y
()
/
polygonF
.
count
()));
}
if
(
_center
!=
center
)
{
_center
=
center
;
emit
centerChanged
(
center
);
}
}
}
for
(
int
i
=
0
;
i
<
count
();
i
++
)
{
QGeoCoordinate
oldVertex
=
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
();
QGeoCoordinate
newVertex
=
oldVertex
.
atDistanceAndAzimuth
(
distance
,
azimuth
);
adjustVertex
(
i
,
newVertex
);
}
void
QGCMapPolygon
::
setCenter
(
QGeoCoordinate
newCenter
)
{
if
(
newCenter
!=
_center
)
{
_ignoreCenterUpdates
=
true
;
if
(
_centerDrag
)
{
// When center dragging, signals from adjustVertext are not sent. So we need to signal here when all adjusting is complete.
emit
pathChanged
();
}
// Adjust polygon vertices to new center
double
distance
=
_center
.
distanceTo
(
newCenter
);
double
azimuth
=
_center
.
azimuthTo
(
newCenter
);
_ignoreCenterUpdates
=
false
;
for
(
int
i
=
0
;
i
<
count
();
i
++
)
{
QGeoCoordinate
oldVertex
=
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
();
QGeoCoordinate
newVertex
=
oldVertex
.
atDistanceAndAzimuth
(
distance
,
azimuth
);
adjustVertex
(
i
,
newVertex
);
}
_center
=
newCenter
;
emit
centerChanged
(
newCenter
);
if
(
_centerDrag
)
{
// When center dragging, signals from adjustVertext are not sent. So we
// need to signal here when all adjusting is complete.
emit
pathChanged
();
}
_ignoreCenterUpdates
=
false
;
_center
=
newCenter
;
emit
centerChanged
(
newCenter
);
}
}
void
QGCMapPolygon
::
setCenterDrag
(
bool
centerDrag
)
{
if
(
centerDrag
!=
_centerDrag
)
{
_centerDrag
=
centerDrag
;
emit
centerDragChanged
(
centerDrag
);
}
void
QGCMapPolygon
::
setCenterDrag
(
bool
centerDrag
)
{
if
(
centerDrag
!=
_centerDrag
)
{
_centerDrag
=
centerDrag
;
emit
centerDragChanged
(
centerDrag
);
}
}
void
QGCMapPolygon
::
setInteractive
(
bool
interactive
)
{
if
(
_interactive
!=
interactive
)
{
_interactive
=
interactive
;
emit
interactiveChanged
(
interactive
);
}
void
QGCMapPolygon
::
setInteractive
(
bool
interactive
)
{
if
(
_interactive
!=
interactive
)
{
_interactive
=
interactive
;
emit
interactiveChanged
(
interactive
);
}
}
QGeoCoordinate
QGCMapPolygon
::
vertexCoordinate
(
int
vertex
)
const
{
if
(
vertex
>=
0
&&
vertex
<
_polygonPath
.
count
())
{
return
_polygonPath
[
vertex
].
value
<
QGeoCoordinate
>
();
}
else
{
qWarning
()
<<
"QGCMapPolygon::vertexCoordinate bad vertex requested:count"
<<
vertex
<<
_polygonPath
.
count
();
return
QGeoCoordinate
();
}
QGeoCoordinate
QGCMapPolygon
::
vertexCoordinate
(
int
vertex
)
const
{
if
(
vertex
>=
0
&&
vertex
<
_polygonPath
.
count
())
{
return
_polygonPath
[
vertex
].
value
<
QGeoCoordinate
>
();
}
else
{
qWarning
()
<<
"QGCMapPolygon::vertexCoordinate bad vertex requested:count"
<<
vertex
<<
_polygonPath
.
count
();
return
QGeoCoordinate
();
}
}
QList
<
QPointF
>
QGCMapPolygon
::
nedPolygon
(
void
)
const
{
QList
<
QPointF
>
nedPolygon
;
if
(
count
()
>
0
)
{
QGeoCoordinate
tangentOrigin
=
vertexCoordinate
(
0
);
for
(
int
i
=
0
;
i
<
_polygonModel
.
count
();
i
++
)
{
double
y
,
x
,
down
;
QGeoCoordinate
vertex
=
vertexCoordinate
(
i
);
if
(
i
==
0
)
{
// This avoids a nan calculation that comes out of convertGeoToNed
x
=
y
=
0
;
}
else
{
convertGeoToNed
(
vertex
,
tangentOrigin
,
&
y
,
&
x
,
&
down
);
}
nedPolygon
+=
QPointF
(
x
,
y
);
}
QList
<
QPointF
>
QGCMapPolygon
::
nedPolygon
(
void
)
const
{
QList
<
QPointF
>
nedPolygon
;
if
(
count
()
>
0
)
{
QGeoCoordinate
tangentOrigin
=
vertexCoordinate
(
0
);
for
(
int
i
=
0
;
i
<
_polygonModel
.
count
();
i
++
)
{
double
y
,
x
,
down
;
QGeoCoordinate
vertex
=
vertexCoordinate
(
i
);
if
(
i
==
0
)
{
// This avoids a nan calculation that comes out of convertGeoToNed
x
=
y
=
0
;
}
else
{
convertGeoToNed
(
vertex
,
tangentOrigin
,
&
y
,
&
x
,
&
down
);
}
nedPolygon
+=
QPointF
(
x
,
y
);
}
}
return
nedPolygon
;
return
nedPolygon
;
}
void
QGCMapPolygon
::
offset
(
double
distance
)
{
QList
<
QGeoCoordinate
>
rgNewPolygon
;
void
QGCMapPolygon
::
offset
(
double
distance
)
{
QList
<
QGeoCoordinate
>
rgNewPolygon
;
// I'm sure there is some beautiful famous algorithm to do this, but here is a
// brute force method
// I'm sure there is some beautiful famous algorithm to do this, but here is a brute force method
if
(
count
()
>
2
)
{
// Convert the polygon to NED
QList
<
QPointF
>
rgNedVertices
=
nedPolygon
();
if
(
count
()
>
2
)
{
// Convert the polygon to NED
QList
<
QPointF
>
rgNedVertices
=
nedPolygon
();
// Walk the edges, offsetting by the specified distance
QList
<
QLineF
>
rgOffsetEdges
;
for
(
int
i
=
0
;
i
<
rgNedVertices
.
count
();
i
++
)
{
int
lastIndex
=
i
==
rgNedVertices
.
count
()
-
1
?
0
:
i
+
1
;
QLineF
offsetEdge
;
QLineF
originalEdge
(
rgNedVertices
[
i
],
rgNedVertices
[
lastIndex
]);
// Walk the edges, offsetting by the specified distance
QList
<
QLineF
>
rgOffsetEdges
;
for
(
int
i
=
0
;
i
<
rgNedVertices
.
count
();
i
++
)
{
int
lastIndex
=
i
==
rgNedVertices
.
count
()
-
1
?
0
:
i
+
1
;
QLineF
offsetEdge
;
QLineF
originalEdge
(
rgNedVertices
[
i
],
rgNedVertices
[
lastIndex
]);
QLineF
workerLine
=
originalEdge
;
workerLine
.
setLength
(
distance
);
workerLine
.
setAngle
(
workerLine
.
angle
()
-
90.0
);
offsetEdge
.
setP1
(
workerLine
.
p2
());
QLineF
workerLine
=
originalEdge
;
workerLine
.
setLength
(
distance
);
workerLine
.
setAngle
(
workerLine
.
angle
()
-
90.0
);
offsetEdge
.
setP1
(
workerLine
.
p2
());
workerLine
.
setPoints
(
originalEdge
.
p2
(),
originalEdge
.
p1
())
;
workerLine
.
setLength
(
distance
);
workerLine
.
setAngle
(
workerLine
.
angle
()
+
90.0
);
offsetEdge
.
setP2
(
workerLine
.
p2
());
workerLine
.
setPoints
(
originalEdge
.
p2
(),
originalEdge
.
p1
());
workerLine
.
setLength
(
distance
);
workerLine
.
setAngle
(
workerLine
.
angle
()
+
90.0
);
offsetEdge
.
setP2
(
workerLine
.
p2
());
rgOffsetEdges
.
append
(
offsetEdge
);
}
rgOffsetEdges
.
append
(
offsetEdge
);
}
// Intersect the offset edges to generate new vertices
QPointF
newVertex
;
QGeoCoordinate
tangentOrigin
=
vertexCoordinate
(
0
);
for
(
int
i
=
0
;
i
<
rgOffsetEdges
.
count
();
i
++
)
{
int
prevIndex
=
i
==
0
?
rgOffsetEdges
.
count
()
-
1
:
i
-
1
;
// Intersect the offset edges to generate new vertices
QPointF
newVertex
;
QGeoCoordinate
tangentOrigin
=
vertexCoordinate
(
0
);
for
(
int
i
=
0
;
i
<
rgOffsetEdges
.
count
();
i
++
)
{
int
prevIndex
=
i
==
0
?
rgOffsetEdges
.
count
()
-
1
:
i
-
1
;
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
auto
intersect
=
rgOffsetEdges
[
prevIndex
].
intersect
(
rgOffsetEdges
[
i
],
&
newVertex
);
auto
intersect
=
rgOffsetEdges
[
prevIndex
].
intersect
(
rgOffsetEdges
[
i
],
&
newVertex
);
#else
auto
intersect
=
rgOffsetEdges
[
prevIndex
].
intersects
(
rgOffsetEdges
[
i
],
&
newVertex
);
auto
intersect
=
rgOffsetEdges
[
prevIndex
].
intersects
(
rgOffsetEdges
[
i
],
&
newVertex
);
#endif
if
(
intersect
==
QLineF
::
NoIntersection
)
{
// FIXME: Better error handling?
qWarning
(
"Intersection failed"
);
return
;
}
QGeoCoordinate
coord
;
convertNedToGeo
(
newVertex
.
y
(),
newVertex
.
x
(),
0
,
tangentOrigin
,
&
coord
);
rgNewPolygon
.
append
(
coord
);
}
if
(
intersect
==
QLineF
::
NoIntersection
)
{
// FIXME: Better error handling?
qWarning
(
"Intersection failed"
);
return
;
}
QGeoCoordinate
coord
;
convertNedToGeo
(
newVertex
.
y
(),
newVertex
.
x
(),
0
,
tangentOrigin
,
&
coord
);
rgNewPolygon
.
append
(
coord
);
}
}
// Update internals
_beginResetIfNotActive
();
clear
();
appendVertices
(
rgNewPolygon
);
_endResetIfNotActive
();
// Update internals
_beginResetIfNotActive
();
clear
();
appendVertices
(
rgNewPolygon
);
_endResetIfNotActive
();
}
bool
QGCMapPolygon
::
loadKMLOrSHPFile
(
const
QString
&
file
)
{
QString
errorString
;
QList
<
QGeoCoordinate
>
rgCoords
;
if
(
!
ShapeFileHelper
::
loadPolygonFromFile
(
file
,
rgCoords
,
errorString
))
{
qgcApp
()
->
showAppMessage
(
errorString
);
return
false
;
}
bool
QGCMapPolygon
::
loadKMLOrSHPFile
(
const
QString
&
file
)
{
QString
errorString
;
QList
<
QGeoCoordinate
>
rgCoords
;
if
(
!
ShapeFileHelper
::
loadPolygonFromFile
(
file
,
rgCoords
,
errorString
))
{
qgcApp
()
->
showAppMessage
(
errorString
);
return
false
;
}
_beginResetIfNotActive
();
clear
();
appendVertices
(
rgCoords
);
_endResetIfNotActive
();
_beginResetIfNotActive
();
clear
();
appendVertices
(
rgCoords
);
_endResetIfNotActive
();
return
true
;
return
true
;
}
double
QGCMapPolygon
::
area
(
void
)
const
{
// https://www.mathopenref.com/coordpolygonarea2.html
double
QGCMapPolygon
::
area
(
void
)
const
{
// https://www.mathopenref.com/coordpolygonarea2.html
if
(
_polygonPath
.
count
()
<
3
)
{
return
0
;
}
if
(
_polygonPath
.
count
()
<
3
)
{
return
0
;
}
double
coveredArea
=
0.0
;
QList
<
QPointF
>
nedVertices
=
nedPolygon
();
for
(
int
i
=
0
;
i
<
nedVertices
.
count
();
i
++
)
{
if
(
i
!=
0
)
{
coveredArea
+=
nedVertices
[
i
-
1
].
x
()
*
nedVertices
[
i
].
y
()
-
nedVertices
[
i
].
x
()
*
nedVertices
[
i
-
1
].
y
();
}
else
{
coveredArea
+=
nedVertices
.
last
().
x
()
*
nedVertices
[
i
].
y
()
-
nedVertices
[
i
].
x
()
*
nedVertices
.
last
().
y
();
}
double
coveredArea
=
0.0
;
QList
<
QPointF
>
nedVertices
=
nedPolygon
();
for
(
int
i
=
0
;
i
<
nedVertices
.
count
();
i
++
)
{
if
(
i
!=
0
)
{
coveredArea
+=
nedVertices
[
i
-
1
].
x
()
*
nedVertices
[
i
].
y
()
-
nedVertices
[
i
].
x
()
*
nedVertices
[
i
-
1
].
y
();
}
else
{
coveredArea
+=
nedVertices
.
last
().
x
()
*
nedVertices
[
i
].
y
()
-
nedVertices
[
i
].
x
()
*
nedVertices
.
last
().
y
();
}
return
0.5
*
fabs
(
coveredArea
);
}
return
0.5
*
fabs
(
coveredArea
);
}
void
QGCMapPolygon
::
verifyClockwiseWinding
(
void
)
{
if
(
_polygonPath
.
count
()
<=
2
)
{
return
;
}
void
QGCMapPolygon
::
verifyClockwiseWinding
(
void
)
{
if
(
_polygonPath
.
count
()
<=
2
)
{
return
;
}
double
sum
=
0
;
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
QGeoCoordinate
coord1
=
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
();
QGeoCoordinate
coord2
=
(
i
==
_polygonPath
.
count
()
-
1
)
?
_polygonPath
[
0
].
value
<
QGeoCoordinate
>
()
:
_polygonPath
[
i
+
1
].
value
<
QGeoCoordinate
>
();
double
sum
=
0
;
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
QGeoCoordinate
coord1
=
_polygonPath
[
i
].
value
<
QGeoCoordinate
>
();
QGeoCoordinate
coord2
=
(
i
==
_polygonPath
.
count
()
-
1
)
?
_polygonPath
[
0
].
value
<
QGeoCoordinate
>
()
:
_polygonPath
[
i
+
1
].
value
<
QGeoCoordinate
>
();
sum
+=
(
coord2
.
longitude
()
-
coord1
.
longitude
())
*
(
coord2
.
latitude
()
+
coord1
.
latitude
());
}
sum
+=
(
coord2
.
longitude
()
-
coord1
.
longitude
())
*
(
coord2
.
latitude
()
+
coord1
.
latitude
());
}
if
(
sum
<
0.0
)
{
// Winding is counter-clockwise and needs reversal
if
(
sum
<
0.0
)
{
// Winding is counter-clockwise and needs reversal
QList
<
QGeoCoordinate
>
rgReversed
;
for
(
const
QVariant
&
varCoord
:
_polygonPath
)
{
rgReversed
.
prepend
(
varCoord
.
value
<
QGeoCoordinate
>
());
}
_beginResetIfNotActive
();
clear
();
appendVertices
(
rgReversed
);
_endResetIfNotActive
();
QList
<
QGeoCoordinate
>
rgReversed
;
for
(
const
QVariant
&
varCoord
:
_polygonPath
)
{
rgReversed
.
prepend
(
varCoord
.
value
<
QGeoCoordinate
>
());
}
_beginResetIfNotActive
();
clear
();
appendVertices
(
rgReversed
);
_endResetIfNotActive
();
}
}
void
QGCMapPolygon
::
beginReset
(
void
)
{
_resetActive
=
true
;
_polygonModel
.
beginReset
();
void
QGCMapPolygon
::
beginReset
(
void
)
{
_resetActive
=
true
;
_polygonModel
.
beginReset
();
}
void
QGCMapPolygon
::
endReset
(
void
)
{
_resetActive
=
false
;
_polygonModel
.
endReset
();
emit
pathChanged
();
emit
centerChanged
(
_center
);
void
QGCMapPolygon
::
endReset
(
void
)
{
_resetActive
=
false
;
_polygonModel
.
endReset
();
emit
pathChanged
();
emit
centerChanged
(
_center
);
}
void
QGCMapPolygon
::
_beginResetIfNotActive
(
void
)
{
if
(
!
_resetActive
)
{
beginReset
();
}
void
QGCMapPolygon
::
_beginResetIfNotActive
(
void
)
{
if
(
!
_resetActive
)
{
beginReset
();
}
}
void
QGCMapPolygon
::
_endResetIfNotActive
(
void
)
{
if
(
!
_resetActive
)
{
endReset
();
}
void
QGCMapPolygon
::
_endResetIfNotActive
(
void
)
{
if
(
!
_resetActive
)
{
endReset
();
}
}
QDomElement
QGCMapPolygon
::
kmlPolygonElement
(
KMLDomDocument
&
domDocument
)
{
QDomElement
QGCMapPolygon
::
kmlPolygonElement
(
KMLDomDocument
&
domDocument
)
{
#if 0
<Polygon id="ID">
<!-- specific to Polygon -->
...
...
@@ -599,55 +583,61 @@ QDomElement QGCMapPolygon::kmlPolygonElement(KMLDomDocument& domDocument)
</Polygon>
#endif
QDomElement
polygonElement
=
domDocument
.
createElement
(
"Polygon"
);
QDomElement
polygonElement
=
domDocument
.
createElement
(
"Polygon"
);
domDocument
.
addTextElement
(
polygonElement
,
"altitudeMode"
,
"clampToGround"
);
domDocument
.
addTextElement
(
polygonElement
,
"altitudeMode"
,
"clampToGround"
);
QDomElement
outerBoundaryIsElement
=
domDocument
.
createElement
(
"outerBoundaryIs"
);
QDomElement
linearRingElement
=
domDocument
.
createElement
(
"LinearRing"
);
QDomElement
outerBoundaryIsElement
=
domDocument
.
createElement
(
"outerBoundaryIs"
);
QDomElement
linearRingElement
=
domDocument
.
createElement
(
"LinearRing"
);
outerBoundaryIsElement
.
appendChild
(
linearRingElement
);
polygonElement
.
appendChild
(
outerBoundaryIsElement
);
outerBoundaryIsElement
.
appendChild
(
linearRingElement
);
polygonElement
.
appendChild
(
outerBoundaryIsElement
);
QString
coordString
;
for
(
const
QVariant
&
varCoord
:
_polygonPath
)
{
coordString
+=
QStringLiteral
(
"%1
\n
"
).
arg
(
domDocument
.
kmlCoordString
(
varCoord
.
value
<
QGeoCoordinate
>
()));
}
coordString
+=
QStringLiteral
(
"%1
\n
"
).
arg
(
domDocument
.
kmlCoordString
(
_polygonPath
.
first
().
value
<
QGeoCoordinate
>
()));
domDocument
.
addTextElement
(
linearRingElement
,
"coordinates"
,
coordString
);
QString
coordString
;
for
(
const
QVariant
&
varCoord
:
_polygonPath
)
{
coordString
+=
QStringLiteral
(
"%1
\n
"
).
arg
(
domDocument
.
kmlCoordString
(
varCoord
.
value
<
QGeoCoordinate
>
()));
}
coordString
+=
QStringLiteral
(
"%1
\n
"
).
arg
(
domDocument
.
kmlCoordString
(
_polygonPath
.
first
().
value
<
QGeoCoordinate
>
()));
domDocument
.
addTextElement
(
linearRingElement
,
"coordinates"
,
coordString
);
return
polygonElement
;
return
polygonElement
;
}
void
QGCMapPolygon
::
setTraceMode
(
bool
traceMode
)
{
if
(
traceMode
!=
_traceMode
)
{
_traceMode
=
traceMode
;
emit
traceModeChanged
(
traceMode
);
}
void
QGCMapPolygon
::
setTraceMode
(
bool
traceMode
)
{
if
(
traceMode
!=
_traceMode
)
{
_traceMode
=
traceMode
;
emit
traceModeChanged
(
traceMode
);
}
}
void
QGCMapPolygon
::
setShowAltColor
(
bool
showAltColor
){
if
(
showAltColor
!=
_showAltColor
)
{
_showAltColor
=
showAltColor
;
emit
showAltColorChanged
(
showAltColor
);
}
void
QGCMapPolygon
::
setShowAltColor
(
bool
showAltColor
)
{
if
(
showAltColor
!=
_showAltColor
)
{
_showAltColor
=
showAltColor
;
emit
showAltColorChanged
(
showAltColor
);
}
}
void
QGCMapPolygon
::
selectVertex
(
int
index
)
{
if
(
index
==
_selectedVertexIndex
)
return
;
// do nothing
void
QGCMapPolygon
::
selectVertex
(
int
index
)
{
if
(
index
==
_selectedVertexIndex
)
return
;
// do nothing
if
(
-
1
<=
index
&&
index
<
count
())
{
_selectedVertexIndex
=
index
;
}
else
{
if
(
!
qgcApp
()
->
runningUnitTests
())
{
qCWarning
(
ParameterManagerLog
)
<<
QString
(
"QGCMapPolygon: Selected vertex index (%1) is out of bounds! "
"Polygon vertices indexes range is [%2..%3]."
).
arg
(
index
).
arg
(
0
).
arg
(
count
()
-
1
);
}
_selectedVertexIndex
=
-
1
;
// deselect vertex
if
(
-
1
<=
index
&&
index
<
count
())
{
_selectedVertexIndex
=
index
;
}
else
{
if
(
!
qgcApp
()
->
runningUnitTests
())
{
qCWarning
(
ParameterManagerLog
)
<<
QString
(
"QGCMapPolygon: Selected vertex index (%1) is out of bounds! "
"Polygon vertices indexes range is [%2..%3]."
)
.
arg
(
index
)
.
arg
(
0
)
.
arg
(
count
()
-
1
);
}
_selectedVertexIndex
=
-
1
;
// deselect vertex
}
emit
selectedVertexChanged
(
_selectedVertexIndex
);
emit
selectedVertexChanged
(
_selectedVertexIndex
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment