You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.3 KiB
168 lines
5.3 KiB
7 years ago
|
/****************************************************************************
|
||
|
*
|
||
5 years ago
|
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
|
||
7 years ago
|
*
|
||
|
* QGroundControl is licensed according to the terms in the file
|
||
|
* COPYING.md in the root of the source code directory.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
5 years ago
|
#include "KMLHelper.h"
|
||
7 years ago
|
|
||
|
#include <QFile>
|
||
7 years ago
|
#include <QVariant>
|
||
7 years ago
|
|
||
5 years ago
|
const char* KMLHelper::_errorPrefix = QT_TR_NOOP("KML file load failed. %1");
|
||
7 years ago
|
|
||
5 years ago
|
QDomDocument KMLHelper::_loadFile(const QString& kmlFile, QString& errorString)
|
||
7 years ago
|
{
|
||
|
QFile file(kmlFile);
|
||
|
|
||
|
errorString.clear();
|
||
|
|
||
|
if (!file.exists()) {
|
||
7 years ago
|
errorString = QString(_errorPrefix).arg(tr("File not found: %1").arg(kmlFile));
|
||
7 years ago
|
return QDomDocument();
|
||
|
}
|
||
|
|
||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||
7 years ago
|
errorString = QString(_errorPrefix).arg(tr("Unable to open file: %1 error: $%2").arg(kmlFile).arg(file.errorString()));
|
||
7 years ago
|
return QDomDocument();
|
||
|
}
|
||
|
|
||
|
QDomDocument doc;
|
||
|
QString errorMessage;
|
||
|
int errorLine;
|
||
|
if (!doc.setContent(&file, &errorMessage, &errorLine)) {
|
||
7 years ago
|
errorString = QString(_errorPrefix).arg(tr("Unable to parse KML file: %1 error: %2 line: %3").arg(kmlFile).arg(errorMessage).arg(errorLine));
|
||
7 years ago
|
return QDomDocument();
|
||
|
}
|
||
|
|
||
|
return doc;
|
||
|
}
|
||
|
|
||
5 years ago
|
ShapeFileHelper::ShapeType KMLHelper::determineShapeType(const QString& kmlFile, QString& errorString)
|
||
7 years ago
|
{
|
||
5 years ago
|
QDomDocument domDocument = KMLHelper::_loadFile(kmlFile, errorString);
|
||
7 years ago
|
if (!errorString.isEmpty()) {
|
||
7 years ago
|
return ShapeFileHelper::Error;
|
||
7 years ago
|
}
|
||
|
|
||
|
QDomNodeList rgNodes = domDocument.elementsByTagName("Polygon");
|
||
|
if (rgNodes.count()) {
|
||
7 years ago
|
return ShapeFileHelper::Polygon;
|
||
7 years ago
|
}
|
||
|
|
||
|
rgNodes = domDocument.elementsByTagName("LineString");
|
||
|
if (rgNodes.count()) {
|
||
7 years ago
|
return ShapeFileHelper::Polyline;
|
||
7 years ago
|
}
|
||
|
|
||
7 years ago
|
errorString = QString(_errorPrefix).arg(tr("No supported type found in KML file."));
|
||
7 years ago
|
return ShapeFileHelper::Error;
|
||
7 years ago
|
}
|
||
|
|
||
5 years ago
|
bool KMLHelper::loadPolygonFromFile(const QString& kmlFile, QList<QGeoCoordinate>& vertices, QString& errorString)
|
||
7 years ago
|
{
|
||
|
errorString.clear();
|
||
|
vertices.clear();
|
||
|
|
||
5 years ago
|
QDomDocument domDocument = KMLHelper::_loadFile(kmlFile, errorString);
|
||
7 years ago
|
if (!errorString.isEmpty()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
QDomNodeList rgNodes = domDocument.elementsByTagName("Polygon");
|
||
|
if (rgNodes.count() == 0) {
|
||
7 years ago
|
errorString = QString(_errorPrefix).arg(tr("Unable to find Polygon node in KML"));
|
||
7 years ago
|
return false;
|
||
|
}
|
||
|
|
||
|
QDomNode coordinatesNode = rgNodes.item(0).namedItem("outerBoundaryIs").namedItem("LinearRing").namedItem("coordinates");
|
||
|
if (coordinatesNode.isNull()) {
|
||
7 years ago
|
errorString = QString(_errorPrefix).arg(tr("Internal error: Unable to find coordinates node in KML"));
|
||
7 years ago
|
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);
|
||
|
}
|
||
|
|
||
6 years ago
|
// Determine winding, reverse if needed. QGC wants clockwise winding
|
||
7 years ago
|
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;
|
||
|
}
|
||
|
|
||
|
vertices = rgCoords;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
5 years ago
|
bool KMLHelper::loadPolylineFromFile(const QString& kmlFile, QList<QGeoCoordinate>& coords, QString& errorString)
|
||
7 years ago
|
{
|
||
|
errorString.clear();
|
||
|
coords.clear();
|
||
|
|
||
5 years ago
|
QDomDocument domDocument = KMLHelper::_loadFile(kmlFile, errorString);
|
||
7 years ago
|
if (!errorString.isEmpty()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
QDomNodeList rgNodes = domDocument.elementsByTagName("LineString");
|
||
|
if (rgNodes.count() == 0) {
|
||
7 years ago
|
errorString = QString(_errorPrefix).arg(tr("Unable to find LineString node in KML"));
|
||
7 years ago
|
return false;
|
||
|
}
|
||
|
|
||
|
QDomNode coordinatesNode = rgNodes.item(0).namedItem("coordinates");
|
||
|
if (coordinatesNode.isNull()) {
|
||
7 years ago
|
errorString = QString(_errorPrefix).arg(tr("Internal error: Unable to find coordinates node in KML"));
|
||
7 years ago
|
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);
|
||
|
}
|
||
|
|
||
|
coords = rgCoords;
|
||
|
|
||
|
return true;
|
||
|
}
|