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
bbe6d219
Unverified
Commit
bbe6d219
authored
Nov 12, 2017
by
Don Gagne
Committed by
GitHub
Nov 12, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5837 from DonLakeFlyer/LoadKML
KML support for Polygons
parents
6e164c06
3c55e2b0
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
327 additions
and
10 deletions
+327
-10
UnitTest.qrc
UnitTest.qrc
+4
-0
QGCMapPolygon.cc
src/MissionManager/QGCMapPolygon.cc
+80
-0
QGCMapPolygon.h
src/MissionManager/QGCMapPolygon.h
+4
-0
QGCMapPolygonTest.cc
src/MissionManager/QGCMapPolygonTest.cc
+17
-0
QGCMapPolygonTest.h
src/MissionManager/QGCMapPolygonTest.h
+1
-0
QGCMapPolygonVisuals.qml
src/MissionManager/QGCMapPolygonVisuals.qml
+24
-4
BadCoordinatesNode.kml
src/MissionManager/UnitTest/BadCoordinatesNode.kml
+47
-0
BadXml.kml
src/MissionManager/UnitTest/BadXml.kml
+49
-0
GoodPolygon.kml
src/MissionManager/UnitTest/GoodPolygon.kml
+48
-0
MissingPolygonNode.kml
src/MissionManager/UnitTest/MissingPolygonNode.kml
+38
-0
FWLandingPatternMapVisual.qml
src/PlanView/FWLandingPatternMapVisual.qml
+2
-1
MissionItemMapVisual.qml
src/PlanView/MissionItemMapVisual.qml
+3
-2
PlanView.qml
src/PlanView/PlanView.qml
+1
-0
SimpleItemMapVisual.qml
src/PlanView/SimpleItemMapVisual.qml
+3
-1
StructureScanMapVisual.qml
src/PlanView/StructureScanMapVisual.qml
+4
-1
SurveyMapVisual.qml
src/PlanView/SurveyMapVisual.qml
+2
-1
No files found.
UnitTest.qrc
View file @
bbe6d219
...
...
@@ -9,5 +9,9 @@
<file alias="MavCmdInfoVTOL.json">src/MissionManager/UnitTest/MavCmdInfoVTOL.json</file>
<file alias="MissionPlanner.waypoints">src/MissionManager/UnitTest/MissionPlanner.waypoints</file>
<file alias="OldFileFormat.mission">src/MissionManager/UnitTest/OldFileFormat.mission</file>
<file alias="GoodPolygon.kml">src/MissionManager/UnitTest/GoodPolygon.kml</file>
<file alias="MissingPolygonNode.kml">src/MissionManager/UnitTest/MissingPolygonNode.kml</file>
<file alias="BadXml.kml">src/MissionManager/UnitTest/BadXml.kml</file>
<file alias="BadCoordinatesNode.kml">src/MissionManager/UnitTest/BadCoordinatesNode.kml</file>
</qresource>
</RCC>
src/MissionManager/QGCMapPolygon.cc
View file @
bbe6d219
...
...
@@ -11,11 +11,14 @@
#include "QGCGeo.h"
#include "JsonHelper.h"
#include "QGCQGeoCoordinate.h"
#include "QGCApplication.h"
#include <QGeoRectangle>
#include <QDebug>
#include <QJsonArray>
#include <QLineF>
#include <QFile>
#include <QDomDocument>
const
char
*
QGCMapPolygon
::
jsonPolygonKey
=
"polygon"
;
...
...
@@ -434,3 +437,80 @@ void QGCMapPolygon::offset(double distance)
appendVertex
(
rgNewPolygon
[
i
]);
}
}
bool
QGCMapPolygon
::
loadKMLFile
(
const
QString
&
kmlFile
)
{
QFile
file
(
kmlFile
);
if
(
!
file
.
exists
())
{
qgcApp
()
->
showMessage
(
tr
(
"File not found: %1"
).
arg
(
kmlFile
));
return
false
;
}
if
(
!
file
.
open
(
QIODevice
::
ReadOnly
))
{
qgcApp
()
->
showMessage
(
tr
(
"Unable to open file: %1 error: $%2"
).
arg
(
kmlFile
).
arg
(
file
.
errorString
()));
return
false
;
}
QDomDocument
doc
;
QString
errorMessage
;
int
errorLine
;
if
(
!
doc
.
setContent
(
&
file
,
&
errorMessage
,
&
errorLine
))
{
qgcApp
()
->
showMessage
(
tr
(
"Unable to parse KML file: %1 error: %2 line: %3"
).
arg
(
kmlFile
).
arg
(
errorMessage
).
arg
(
errorLine
));
return
false
;
}
QDomNodeList
rgNodes
=
doc
.
elementsByTagName
(
"Polygon"
);
if
(
rgNodes
.
count
()
==
0
)
{
qgcApp
()
->
showMessage
(
tr
(
"Unable to find Polygon node in KML"
));
return
false
;
}
QDomNode
coordinatesNode
=
rgNodes
.
item
(
0
).
namedItem
(
"outerBoundaryIs"
).
namedItem
(
"LinearRing"
).
namedItem
(
"coordinates"
);
if
(
coordinatesNode
.
isNull
())
{
qgcApp
()
->
showMessage
(
tr
(
"Internal error: Unable to find coordinates node in KML"
));
return
false
;
}
QString
coordinatesString
=
coordinatesNode
.
toElement
().
text
().
simplified
();
QStringList
rgCoordinateStrings
=
coordinatesString
.
split
(
" "
);
QList
<
QGeoCoordinate
>
rgCoords
;
for
(
int
i
=
0
;
i
<
rgCoordinateStrings
.
count
()
-
1
;
i
++
)
{
QString
coordinateString
=
rgCoordinateStrings
[
i
];
QStringList
rgValueStrings
=
coordinateString
.
split
(
","
);
QGeoCoordinate
coord
;
coord
.
setLongitude
(
rgValueStrings
[
0
].
toDouble
());
coord
.
setLatitude
(
rgValueStrings
[
1
].
toDouble
());
rgCoords
.
append
(
coord
);
}
// Determine winding, reverse if needed
double
sum
=
0
;
for
(
int
i
=
0
;
i
<
rgCoords
.
count
();
i
++
)
{
QGeoCoordinate
coord1
=
rgCoords
[
i
];
QGeoCoordinate
coord2
=
(
i
==
rgCoords
.
count
()
-
1
)
?
rgCoords
[
0
]
:
rgCoords
[
i
+
1
];
sum
+=
(
coord2
.
longitude
()
-
coord1
.
longitude
())
*
(
coord2
.
latitude
()
+
coord1
.
latitude
());
}
bool
reverse
=
sum
<
0.0
;
if
(
reverse
)
{
QList
<
QGeoCoordinate
>
rgReversed
;
for
(
int
i
=
0
;
i
<
rgCoords
.
count
();
i
++
)
{
rgReversed
.
prepend
(
rgCoords
[
i
]);
}
rgCoords
=
rgReversed
;
}
clear
();
for
(
int
i
=
0
;
i
<
rgCoords
.
count
();
i
++
)
{
appendVertex
(
rgCoords
[
i
]);
}
return
true
;
}
src/MissionManager/QGCMapPolygon.h
View file @
bbe6d219
...
...
@@ -55,6 +55,10 @@ public:
/// Offsets the current polygon edges by the specified distance in meters
Q_INVOKABLE
void
offset
(
double
distance
);
/// Loads a polygon from a KML file
/// @return true: success
Q_INVOKABLE
bool
loadKMLFile
(
const
QString
&
kmlFile
);
/// Returns the path in a list of QGeoCoordinate's format
QList
<
QGeoCoordinate
>
coordinateList
(
void
)
const
;
...
...
src/MissionManager/QGCMapPolygonTest.cc
View file @
bbe6d219
...
...
@@ -197,3 +197,20 @@ void QGCMapPolygonTest::_testVertexManipulation(void)
QCOMPARE
(
polyList
.
count
(),
0
);
QCOMPARE
(
_pathModel
->
count
(),
0
);
}
void
QGCMapPolygonTest
::
_testKMLLoad
(
void
)
{
QVERIFY
(
_mapPolygon
->
loadKMLFile
(
QStringLiteral
(
":/unittest/GoodPolygon.kml"
)));
setExpectedMessageBox
(
QMessageBox
::
Ok
);
QVERIFY
(
!
_mapPolygon
->
loadKMLFile
(
QStringLiteral
(
":/unittest/BadXml.kml"
)));
checkExpectedMessageBox
();
setExpectedMessageBox
(
QMessageBox
::
Ok
);
QVERIFY
(
!
_mapPolygon
->
loadKMLFile
(
QStringLiteral
(
":/unittest/MissingPolygonNode.kml"
)));
checkExpectedMessageBox
();
setExpectedMessageBox
(
QMessageBox
::
Ok
);
QVERIFY
(
!
_mapPolygon
->
loadKMLFile
(
QStringLiteral
(
":/unittest/BadCoordinatesNode.kml"
)));
checkExpectedMessageBox
();
}
src/MissionManager/QGCMapPolygonTest.h
View file @
bbe6d219
...
...
@@ -29,6 +29,7 @@ protected:
private
slots
:
void
_testDirty
(
void
);
void
_testVertexManipulation
(
void
);
void
_testKMLLoad
(
void
);
private:
enum
{
...
...
src/MissionManager/QGCMapPolygonVisuals.qml
View file @
bbe6d219
...
...
@@ -22,6 +22,7 @@ import QGroundControl.FlightMap 1.0
Item
{
id
:
_root
property
var
qgcView
///< QGCView for popping dialogs
property
var
mapControl
///< Map control to place item in
property
var
mapPolygon
///< QGCMapPolygon object
property
bool
interactive
:
mapPolygon
.
interactive
...
...
@@ -146,6 +147,10 @@ Item {
setCircleRadius
(
center
,
radius
)
}
function
loadKMLFile
()
{
mapPolygon
.
loadKMLFile
(
"
/Users/Don/Downloads/polygon.kml
"
)
}
onInteractiveChanged
:
{
if
(
interactive
)
{
addHandles
()
...
...
@@ -168,6 +173,21 @@ Item {
QGCPalette
{
id
:
qgcPal
}
QGCFileDialog
{
id
:
kmlLoadDialog
qgcView
:
_root
.
qgcView
folder
:
QGroundControl
.
settingsManager
.
appSettings
.
missionSavePath
title
:
qsTr
(
"
Select KML File
"
)
selectExisting
:
true
nameFilters
:
[
qsTr
(
"
KML files (*.kml)
"
)
]
onAcceptedForLoad
:
{
mapPolygon
.
loadKMLFile
(
file
)
close
()
}
}
Component
{
id
:
polygonComponent
...
...
@@ -394,7 +414,7 @@ Item {
MenuItem
{
text
:
qsTr
(
"
Load KML...
"
)
enabled
:
false
onTriggered
:
kmlLoadDialog
.
openForLoad
()
}
}
...
...
src/MissionManager/UnitTest/BadCoordinatesNode.kml
0 → 100755
View file @
bbe6d219
Incorrectly formed XML test file
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
<name>Polygon.kmz</name>
<Style id="s_ylw-pushpin_hl">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
</IconStyle>
</Style>
<Style id="s_ylw-pushpin">
<IconStyle>
<scale>1.1</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
</IconStyle>
</Style>
<StyleMap id="m_ylw-pushpin">
<Pair>
<key>normal</key>
<styleUrl>#s_ylw-pushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#s_ylw-pushpin_hl</styleUrl>
</Pair>
</StyleMap>
<Placemark>
<name>Untitled Polygon</name>
<styleUrl>#m_ylw-pushpin</styleUrl>
<Polygon>
<tessellate>1</tessellate>
<outerBoundaryIs>
<coordinates>
-122.1059149362712,47.65965281788451,0 -122.1044593196253,47.66002598220988,0 -122.1047336695092,47.66034166158975,0 -122.1061470943783,47.6599810708829,0 -122.1059149362712,47.65965281788451,0
</coordinates>
</outerBoundaryIs>
</Polygon>
</Placemark>
</Document>
</kml>
src/MissionManager/UnitTest/BadXml.kml
0 → 100755
View file @
bbe6d219
Incorrectly formed XML test file
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
<name>Polygon.kmz</name>
<Style id="s_ylw-pushpin_hl">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
</IconStyle>
</Style>
<Style id="s_ylw-pushpin">
<IconStyle>
<scale>1.1</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
</IconStyle>
</Style>
<StyleMap id="m_ylw-pushpin">
<Pair>
<key>normal</key>
<styleUrl>#s_ylw-pushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#s_ylw-pushpin_hl</styleUrl>
</Pair>
</StyleMap>
<Placemark>
<name>Untitled Polygon</name>
<styleUrl>#m_ylw-pushpin</styleUrl>
<Polygon>
<tessellate>1</tessellate>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-122.1059149362712,47.65965281788451,0 -122.1044593196253,47.66002598220988,0 -122.1047336695092,47.66034166158975,0 -122.1061470943783,47.6599810708829,0 -122.1059149362712,47.65965281788451,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
</Document>
</kml>
src/MissionManager/UnitTest/GoodPolygon.kml
0 → 100755
View file @
bbe6d219
<?xml version="1.0" encoding="UTF-8"?>
<kml
xmlns=
"http://www.opengis.net/kml/2.2"
xmlns:gx=
"http://www.google.com/kml/ext/2.2"
xmlns:kml=
"http://www.opengis.net/kml/2.2"
xmlns:atom=
"http://www.w3.org/2005/Atom"
>
<Document>
<name>
Polygon.kmz
</name>
<Style
id=
"s_ylw-pushpin_hl"
>
<IconStyle>
<scale>
1.3
</scale>
<Icon>
<href>
http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png
</href>
</Icon>
<hotSpot
x=
"20"
y=
"2"
xunits=
"pixels"
yunits=
"pixels"
/>
</IconStyle>
</Style>
<Style
id=
"s_ylw-pushpin"
>
<IconStyle>
<scale>
1.1
</scale>
<Icon>
<href>
http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png
</href>
</Icon>
<hotSpot
x=
"20"
y=
"2"
xunits=
"pixels"
yunits=
"pixels"
/>
</IconStyle>
</Style>
<StyleMap
id=
"m_ylw-pushpin"
>
<Pair>
<key>
normal
</key>
<styleUrl>
#s_ylw-pushpin
</styleUrl>
</Pair>
<Pair>
<key>
highlight
</key>
<styleUrl>
#s_ylw-pushpin_hl
</styleUrl>
</Pair>
</StyleMap>
<Placemark>
<name>
Untitled Polygon
</name>
<styleUrl>
#m_ylw-pushpin
</styleUrl>
<Polygon>
<tessellate>
1
</tessellate>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-122.1059149362712,47.65965281788451,0 -122.1044593196253,47.66002598220988,0 -122.1047336695092,47.66034166158975,0 -122.1061470943783,47.6599810708829,0 -122.1059149362712,47.65965281788451,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
</Document>
</kml>
src/MissionManager/UnitTest/MissingPolygonNode.kml
0 → 100755
View file @
bbe6d219
<?xml version="1.0" encoding="UTF-8"?>
<kml
xmlns=
"http://www.opengis.net/kml/2.2"
xmlns:gx=
"http://www.google.com/kml/ext/2.2"
xmlns:kml=
"http://www.opengis.net/kml/2.2"
xmlns:atom=
"http://www.w3.org/2005/Atom"
>
<Document>
<name>
Polygon.kmz
</name>
<Style
id=
"s_ylw-pushpin_hl"
>
<IconStyle>
<scale>
1.3
</scale>
<Icon>
<href>
http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png
</href>
</Icon>
<hotSpot
x=
"20"
y=
"2"
xunits=
"pixels"
yunits=
"pixels"
/>
</IconStyle>
</Style>
<Style
id=
"s_ylw-pushpin"
>
<IconStyle>
<scale>
1.1
</scale>
<Icon>
<href>
http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png
</href>
</Icon>
<hotSpot
x=
"20"
y=
"2"
xunits=
"pixels"
yunits=
"pixels"
/>
</IconStyle>
</Style>
<StyleMap
id=
"m_ylw-pushpin"
>
<Pair>
<key>
normal
</key>
<styleUrl>
#s_ylw-pushpin
</styleUrl>
</Pair>
<Pair>
<key>
highlight
</key>
<styleUrl>
#s_ylw-pushpin_hl
</styleUrl>
</Pair>
</StyleMap>
<Placemark>
<name>
Untitled Polygon
</name>
<styleUrl>
#m_ylw-pushpin
</styleUrl>
</Placemark>
</Document>
</kml>
src/PlanView/FWLandingPatternMapVisual.qml
View file @
bbe6d219
...
...
@@ -23,6 +23,7 @@ Item {
id
:
_root
property
var
map
///< Map control to place item in
property
var
qgcView
///< QGCView to use for popping dialogs
signal
clicked
(
int
sequenceNumber
)
...
...
src/PlanView/MissionItemMapVisual.qml
View file @
bbe6d219
...
...
@@ -22,6 +22,7 @@ Item {
id
:
_root
property
var
map
///< Map control to place item in
property
var
qgcView
///< QGCView to use for popping dialogs
signal
clicked
(
int
sequenceNumber
)
...
...
@@ -33,7 +34,7 @@ Item {
if
(
component
.
status
===
Component
.
Error
)
{
console
.
log
(
"
Error loading Qml:
"
,
object
.
mapVisualQML
,
component
.
errorString
())
}
_visualItem
=
component
.
createObject
(
map
,
{
"
map
"
:
_root
.
map
})
_visualItem
=
component
.
createObject
(
map
,
{
"
map
"
:
_root
.
map
,
"
qgcView
"
:
_root
.
qgcView
})
_visualItem
.
clicked
.
connect
(
_root
.
clicked
)
}
}
...
...
src/PlanView/PlanView.qml
View file @
bbe6d219
...
...
@@ -346,6 +346,7 @@ QGCView {
delegate
:
MissionItemMapVisual
{
map
:
editorMap
qgcView
:
_qgcView
onClicked
:
_missionController
.
setCurrentPlanViewIndex
(
sequenceNumber
,
false
)
visible
:
_editingLayer
==
_layerMission
}
...
...
src/PlanView/SimpleItemMapVisual.qml
View file @
bbe6d219
...
...
@@ -21,7 +21,9 @@ import QGroundControl.FlightMap 1.0
/// Simple Mission Item visuals
Item
{
id
:
_root
property
var
map
///< Map control to place item in
property
var
qgcView
///< QGCView to use for popping dialogs
property
var
_missionItem
:
object
property
var
_itemVisual
...
...
src/PlanView/StructureScanMapVisual.qml
View file @
bbe6d219
...
...
@@ -23,6 +23,7 @@ Item {
id
:
_root
property
var
map
///< Map control to place item in
property
var
qgcView
///< QGCView to use for popping dialogs
property
var
_missionItem
:
object
property
var
_structurePolygon
:
object
.
structurePolygon
...
...
@@ -85,6 +86,7 @@ Item {
}
QGCMapPolygonVisuals
{
qgcView
:
_root
.
qgcView
mapControl
:
map
mapPolygon
:
_structurePolygon
interactive
:
_missionItem
.
isCurrentItem
...
...
@@ -95,6 +97,7 @@ Item {
}
QGCMapPolygonVisuals
{
qgcView
:
_root
.
qgcView
mapControl
:
map
mapPolygon
:
_flightPolygon
interactive
:
false
...
...
src/PlanView/SurveyMapVisual.qml
View file @
bbe6d219
...
...
@@ -23,6 +23,7 @@ Item {
id
:
_root
property
var
map
///< Map control to place item in
property
var
qgcView
///< QGCView to use for popping dialogs
property
var
_missionItem
:
object
property
var
_mapPolygon
:
object
.
mapPolygon
...
...
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