30 changed files with 300 additions and 238 deletions
@ -1,128 +0,0 @@
@@ -1,128 +0,0 @@
|
||||
/****************************************************************************
|
||||
* |
||||
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
|
||||
* |
||||
* QGroundControl is licensed according to the terms in the file |
||||
* COPYING.md in the root of the source code directory. |
||||
* |
||||
****************************************************************************/ |
||||
|
||||
#include "KML.h" |
||||
|
||||
#include <QDomDocument> |
||||
#include <QStringList> |
||||
|
||||
const QString Kml::_version("version=\"1.0\""); |
||||
const QString Kml::_encoding("encoding=\"UTF-8\""); |
||||
const QString Kml::_opengis("http://www.opengis.net/kml/2.2"); |
||||
const QString Kml::_qgckml("QGC KML"); |
||||
|
||||
Kml::Kml() |
||||
{ |
||||
//create header
|
||||
createHeader(); |
||||
//name
|
||||
createTextElement(_docEle, "name", _qgckml); |
||||
//open
|
||||
createTextElement(_docEle, "open", "1"); |
||||
//create style
|
||||
createStyles(); |
||||
} |
||||
|
||||
void Kml::points(const QStringList& points) |
||||
{ |
||||
//create placemark
|
||||
QDomElement placemark = _domDocument.createElement("Placemark"); |
||||
_docEle.appendChild(placemark); |
||||
createTextElement(placemark, "styleUrl", "yellowLineGreenPoly"); |
||||
createTextElement(placemark, "name", "Absolute"); |
||||
createTextElement(placemark, "visibility", "0"); |
||||
createTextElement(placemark, "description", "Transparent purple line"); |
||||
|
||||
QStringList latLonAlt = points[0].split(","); |
||||
QStringList lookAtList({latLonAlt[0], latLonAlt[1], "0" \
|
||||
, "-100", "45", "2500"}); |
||||
createLookAt(placemark, lookAtList); |
||||
|
||||
//Add linestring
|
||||
QDomElement lineString = _domDocument.createElement("LineString"); |
||||
placemark.appendChild(lineString); |
||||
|
||||
//extruder
|
||||
createTextElement(lineString, "extruder", "1"); |
||||
createTextElement(lineString, "tessellate", "1"); |
||||
createTextElement(lineString, "altitudeMode", "absolute"); |
||||
QString coordinates; |
||||
for(const auto& point : points) { |
||||
coordinates += point + "\n"; |
||||
} |
||||
createTextElement(lineString, "coordinates", coordinates); |
||||
} |
||||
|
||||
void Kml::save(QDomDocument& document) |
||||
{ |
||||
document = _domDocument; |
||||
} |
||||
|
||||
void Kml::createHeader() |
||||
{ |
||||
QDomProcessingInstruction header = _domDocument.createProcessingInstruction("xml", _version + " " + _encoding); |
||||
_domDocument.appendChild(header); |
||||
QDomElement kml = _domDocument.createElement("kml"); |
||||
kml.setAttribute("xmlns", _opengis); |
||||
_docEle = _domDocument.createElement("Document"); |
||||
kml.appendChild(_docEle); |
||||
_domDocument.appendChild(kml); |
||||
} |
||||
|
||||
void Kml::createStyles() |
||||
{ |
||||
QDomElement style = _domDocument.createElement("Style"); |
||||
style.setAttribute("id", "yellowLineGreenPoly"); |
||||
createStyleLine(style, "7f00ffff", "4", "7f00ff00"); |
||||
_docEle.appendChild(style); |
||||
} |
||||
|
||||
void Kml::createLookAt(QDomElement& placemark, const QStringList &lookAtList) |
||||
{ |
||||
QDomElement lookAt = _domDocument.createElement("LookAt"); |
||||
placemark.appendChild(lookAt); |
||||
createTextElement(lookAt, "longitude", lookAtList[0]); |
||||
createTextElement(lookAt, "latitude", lookAtList[1]); |
||||
createTextElement(lookAt, "altitude", lookAtList[2]); |
||||
createTextElement(lookAt, "heading", lookAtList[3]); |
||||
createTextElement(lookAt, "tilt", lookAtList[4]); |
||||
createTextElement(lookAt, "range", lookAtList[5]); |
||||
} |
||||
|
||||
void Kml::createTextElement(QDomElement& domEle, const QString& elementName, const QString& textElement) |
||||
{ |
||||
// <elementName>textElement</elementName>
|
||||
auto element = _domDocument.createElement(elementName); |
||||
element.appendChild(_domDocument.createTextNode(textElement)); |
||||
domEle.appendChild(element); |
||||
} |
||||
|
||||
void Kml::createStyleLine(QDomElement& domEle, const QString& lineColor, const QString& lineWidth, const QString& polyColor) |
||||
{ |
||||
/*
|
||||
<LineStyle> |
||||
<color>7f00ffff</color> |
||||
<width>4</width> |
||||
</LineStyle> |
||||
<PolyStyle> |
||||
<color>7f00ff00</color> |
||||
</PolyStyle> |
||||
*/ |
||||
auto lineStyle = _domDocument.createElement("LineStyle"); |
||||
auto polyStyle = _domDocument.createElement("PolyStyle"); |
||||
domEle.appendChild(lineStyle); |
||||
domEle.appendChild(polyStyle); |
||||
createTextElement(lineStyle, "color", lineColor); |
||||
createTextElement(lineStyle, "width", lineWidth); |
||||
createTextElement(polyStyle, "color", polyColor); |
||||
} |
||||
|
||||
Kml::~Kml() |
||||
{ |
||||
} |
@ -1,42 +0,0 @@
@@ -1,42 +0,0 @@
|
||||
/****************************************************************************
|
||||
* |
||||
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
|
||||
* |
||||
* QGroundControl is licensed according to the terms in the file |
||||
* COPYING.md in the root of the source code directory. |
||||
* |
||||
****************************************************************************/ |
||||
|
||||
#ifndef KML_H |
||||
#define KML_H |
||||
|
||||
#include <QDomDocument> |
||||
#include <QDomElement> |
||||
|
||||
class Kml |
||||
{ |
||||
|
||||
public: |
||||
Kml(); |
||||
~Kml(); |
||||
|
||||
void points(const QStringList& points); |
||||
void polygon(const QStringList& points); |
||||
void save(QDomDocument& document); |
||||
|
||||
private: |
||||
void createHeader(); |
||||
void createLookAt(QDomElement& placemark, const QStringList &lookAtList); |
||||
void createStyles(); |
||||
void createStyleLine(QDomElement& domEle, const QString& lineColor, const QString& lineWidth, const QString& polyColor); |
||||
void createTextElement(QDomElement& domEle, const QString& elementName, const QString& textElement); |
||||
|
||||
QDomDocument _domDocument; |
||||
QDomElement _docEle; |
||||
static const QString _encoding; |
||||
static const QString _opengis; |
||||
static const QString _qgckml; |
||||
static const QString _version; |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,175 @@
@@ -0,0 +1,175 @@
|
||||
/****************************************************************************
|
||||
* |
||||
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
|
||||
* |
||||
* QGroundControl is licensed according to the terms in the file |
||||
* COPYING.md in the root of the source code directory. |
||||
* |
||||
****************************************************************************/ |
||||
|
||||
#include "KMLPlanDomDocument.h" |
||||
#include "QGCPalette.h" |
||||
#include "QGCApplication.h" |
||||
#include "MissionCommandTree.h" |
||||
#include "MissionCommandUIInfo.h" |
||||
#include "FactMetaData.h" |
||||
|
||||
#include <QDomDocument> |
||||
#include <QStringList> |
||||
|
||||
const char* KMLPlanDomDocument::_missionLineStyleName = "MissionLineStyle"; |
||||
const char* KMLPlanDomDocument::_ballonStyleName = "BalloonStyle"; |
||||
|
||||
KMLPlanDomDocument::KMLPlanDomDocument() |
||||
{ |
||||
QDomProcessingInstruction header = createProcessingInstruction(QStringLiteral("xml"), QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"")); |
||||
appendChild(header); |
||||
|
||||
QDomElement kmlElement = createElement(QStringLiteral("kml")); |
||||
kmlElement.setAttribute(QStringLiteral("xmlns"), "http://www.opengis.net/kml/2.2"); |
||||
|
||||
_documentElement = createElement(QStringLiteral("Document")); |
||||
kmlElement.appendChild(_documentElement); |
||||
appendChild(kmlElement); |
||||
|
||||
_addTextElement(_documentElement, "name", QStringLiteral("%1 Plan KML").arg(qgcApp()->applicationName())); |
||||
_addTextElement(_documentElement, "open", "1"); |
||||
|
||||
_addStyles(); |
||||
} |
||||
|
||||
QString KMLPlanDomDocument::_kmlCoordString(const QGeoCoordinate& coord) |
||||
{ |
||||
return QStringLiteral("%1,%2,%3").arg(QString::number(coord.longitude(), 'f', 7)).arg(QString::number(coord.latitude(), 'f', 7)).arg(QString::number(coord.altitude(), 'f', 2)); |
||||
} |
||||
|
||||
void KMLPlanDomDocument::addMissionItems(Vehicle* vehicle, QList<MissionItem*> rgMissionItems) |
||||
{ |
||||
if (rgMissionItems.count() == 0) { |
||||
return; |
||||
} |
||||
|
||||
QDomElement itemFolderElement = createElement("Folder"); |
||||
_documentElement.appendChild(itemFolderElement); |
||||
|
||||
_addTextElement(itemFolderElement, "name", "Items"); |
||||
|
||||
QDomElement flightPathElement = createElement("Placemark"); |
||||
_documentElement.appendChild(flightPathElement); |
||||
|
||||
_addTextElement(flightPathElement, "styleUrl", QStringLiteral("#%1").arg(_missionLineStyleName)); |
||||
_addTextElement(flightPathElement, "name", "Flight Path"); |
||||
_addTextElement(flightPathElement, "visibility", "1"); |
||||
_addLookAt(flightPathElement, rgMissionItems[0]->coordinate()); |
||||
|
||||
// Build up the mission trajectory line coords
|
||||
QList<QGeoCoordinate> rgFlightCoords; |
||||
QGeoCoordinate homeCoord = rgMissionItems[0]->coordinate(); |
||||
for (const MissionItem* item : rgMissionItems) { |
||||
const MissionCommandUIInfo* uiInfo = qgcApp()->toolbox()->missionCommandTree()->getUIInfo(vehicle, item->command()); |
||||
if (uiInfo) { |
||||
double altAdjustment = item->frame() == MAV_FRAME_GLOBAL ? 0 : homeCoord.altitude(); // Used to convert to amsl
|
||||
if (uiInfo->isTakeoffCommand() && !vehicle->fixedWing()) { |
||||
// These takeoff items go straight up from home position to specified altitude
|
||||
QGeoCoordinate coord = homeCoord; |
||||
coord.setAltitude(item->param7() + altAdjustment); |
||||
rgFlightCoords += coord; |
||||
} |
||||
if (uiInfo->specifiesCoordinate()) { |
||||
QGeoCoordinate coord = item->coordinate(); |
||||
coord.setAltitude(coord.altitude() + altAdjustment); // convert to amsl
|
||||
|
||||
if (!uiInfo->isStandaloneCoordinate()) { |
||||
// Flight path goes through this item
|
||||
rgFlightCoords += coord; |
||||
} |
||||
|
||||
// Add a place mark for each WP
|
||||
|
||||
QDomElement wpPlacemarkElement = createElement("Placemark"); |
||||
_addTextElement(wpPlacemarkElement, "name", QStringLiteral("%1 %2").arg(QString::number(item->sequenceNumber())).arg(item->command() == MAV_CMD_NAV_WAYPOINT ? "" : uiInfo->friendlyName())); |
||||
_addTextElement(wpPlacemarkElement, "styleUrl", QStringLiteral("#%1").arg(_ballonStyleName)); |
||||
|
||||
QDomElement wpPointElement = createElement("Point"); |
||||
_addTextElement(wpPointElement, "altitudeMode", "absolute"); |
||||
_addTextElement(wpPointElement, "coordinates", _kmlCoordString(coord)); |
||||
_addTextElement(wpPointElement, "extrude", "1"); |
||||
|
||||
QDomElement descriptionElement = createElement("description"); |
||||
QString htmlString; |
||||
htmlString += QStringLiteral("Index: %1\n").arg(item->sequenceNumber()); |
||||
htmlString += uiInfo->friendlyName() + "\n"; |
||||
htmlString += QStringLiteral("Alt AMSL: %1 %2\n").arg(QString::number(FactMetaData::metersToAppSettingsDistanceUnits(coord.altitude()).toDouble(), 'f', 2)).arg(FactMetaData::appSettingsDistanceUnitsString()); |
||||
htmlString += QStringLiteral("Alt Rel: %1 %2\n").arg(QString::number(FactMetaData::metersToAppSettingsDistanceUnits(coord.altitude() - homeCoord.altitude()).toDouble(), 'f', 2)).arg(FactMetaData::appSettingsDistanceUnitsString()); |
||||
htmlString += QStringLiteral("Lat: %1\n").arg(QString::number(coord.latitude(), 'f', 7)); |
||||
htmlString += QStringLiteral("Lon: %1\n").arg(QString::number(coord.longitude(), 'f', 7)); |
||||
QDomCDATASection cdataSection = createCDATASection(htmlString); |
||||
descriptionElement.appendChild(cdataSection); |
||||
|
||||
wpPlacemarkElement.appendChild(descriptionElement); |
||||
wpPlacemarkElement.appendChild(wpPointElement); |
||||
itemFolderElement.appendChild(wpPlacemarkElement); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Create a LineString element from the coords
|
||||
|
||||
QDomElement lineStringElement = createElement("LineString"); |
||||
flightPathElement.appendChild(lineStringElement); |
||||
|
||||
_addTextElement(lineStringElement, "extruder", "1"); |
||||
_addTextElement(lineStringElement, "tessellate", "1"); |
||||
_addTextElement(lineStringElement, "altitudeMode", "absolute"); |
||||
|
||||
QString coordString; |
||||
for (const QGeoCoordinate& coord : rgFlightCoords) { |
||||
coordString += QStringLiteral("%1\n").arg(_kmlCoordString(coord)); |
||||
} |
||||
_addTextElement(lineStringElement, "coordinates", coordString); |
||||
} |
||||
|
||||
QString KMLPlanDomDocument::_kmlColorString (const QColor& color) |
||||
{ |
||||
return QStringLiteral("ff%1%2%3").arg(color.blue(), 2, 16, QChar('0')).arg(color.green(), 2, 16, QChar('0')).arg(color.red(), 2, 16, QChar('0')); |
||||
} |
||||
|
||||
void KMLPlanDomDocument::_addStyles(void) |
||||
{ |
||||
QGCPalette palette; |
||||
|
||||
QDomElement styleElement1 = createElement("Style"); |
||||
styleElement1.setAttribute("id", _missionLineStyleName); |
||||
QDomElement lineStyleElement = createElement("LineStyle"); |
||||
_addTextElement(lineStyleElement, "color", _kmlColorString(palette.mapMissionTrajectory())); |
||||
_addTextElement(lineStyleElement, "width", "4"); |
||||
styleElement1.appendChild(lineStyleElement); |
||||
|
||||
QDomElement styleElement2 = createElement("Style"); |
||||
styleElement2.setAttribute("id", _ballonStyleName); |
||||
QDomElement balloonStyleElement = createElement("BalloonStyle"); |
||||
_addTextElement(balloonStyleElement, "text", "$[description]"); |
||||
styleElement2.appendChild(balloonStyleElement); |
||||
|
||||
_documentElement.appendChild(styleElement1); |
||||
_documentElement.appendChild(styleElement2); |
||||
} |
||||
|
||||
void KMLPlanDomDocument::_addTextElement(QDomElement &element, const QString &name, const QString &value) |
||||
{ |
||||
QDomElement textElement = createElement(name); |
||||
textElement.appendChild(createTextNode(value)); |
||||
element.appendChild(textElement); |
||||
} |
||||
|
||||
void KMLPlanDomDocument::_addLookAt(QDomElement& element, const QGeoCoordinate& coord) |
||||
{ |
||||
QDomElement lookAtElement = createElement("LookAt"); |
||||
_addTextElement(lookAtElement, "latitude", QString::number(coord.latitude(), 'f', 7)); |
||||
_addTextElement(lookAtElement, "longitude", QString::number(coord.longitude(), 'f', 7)); |
||||
_addTextElement(lookAtElement, "altitude", QString::number(coord.longitude(), 'f', 2)); |
||||
_addTextElement(lookAtElement, "heading", "-100"); |
||||
_addTextElement(lookAtElement, "tilt", "45"); |
||||
_addTextElement(lookAtElement, "range", "2500"); |
||||
element.appendChild(lookAtElement); |
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
/****************************************************************************
|
||||
* |
||||
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
|
||||
* |
||||
* QGroundControl is licensed according to the terms in the file |
||||
* COPYING.md in the root of the source code directory. |
||||
* |
||||
****************************************************************************/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <QDomDocument> |
||||
#include <QDomElement> |
||||
#include <QGeoCoordinate> |
||||
|
||||
class MissionItem; |
||||
class Vehicle; |
||||
|
||||
/// Used to convert a Plan to a KML document
|
||||
class KMLPlanDomDocument : public QDomDocument |
||||
{ |
||||
|
||||
public: |
||||
KMLPlanDomDocument(); |
||||
|
||||
void addMissionItems(Vehicle* vehicle, QList<MissionItem*> rgMissionItems); |
||||
|
||||
private: |
||||
void _addStyles (void); |
||||
QString _kmlColorString (const QColor& color); |
||||
void _addTextElement (QDomElement& element, const QString& name, const QString& value); |
||||
QString _kmlCoordString (const QGeoCoordinate& coord); |
||||
void _addLookAt(QDomElement& element, const QGeoCoordinate& coord); |
||||
|
||||
QDomElement _documentElement; |
||||
|
||||
static const char* _missionLineStyleName; |
||||
static const char* _ballonStyleName; |
||||
}; |
Loading…
Reference in new issue