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.
179 lines
5.6 KiB
179 lines
5.6 KiB
/**************************************************************************** |
|
* |
|
* (c) 2009-2016 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 "KMLFileHelper.h" |
|
|
|
#include <QFile> |
|
#include <QVariant> |
|
|
|
const char* KMLFileHelper::_errorPrefix = QT_TR_NOOP("KML file load failed. %1"); |
|
|
|
QDomDocument KMLFileHelper::loadFile(const QString& kmlFile, QString& errorString) |
|
{ |
|
QFile file(kmlFile); |
|
|
|
errorString.clear(); |
|
|
|
if (!file.exists()) { |
|
errorString = QString(_errorPrefix).arg(tr("File not found: %1").arg(kmlFile)); |
|
return QDomDocument(); |
|
} |
|
|
|
if (!file.open(QIODevice::ReadOnly)) { |
|
errorString = QString(_errorPrefix).arg(tr("Unable to open file: %1 error: $%2").arg(kmlFile).arg(file.errorString())); |
|
return QDomDocument(); |
|
} |
|
|
|
QDomDocument doc; |
|
QString errorMessage; |
|
int errorLine; |
|
if (!doc.setContent(&file, &errorMessage, &errorLine)) { |
|
errorString = QString(_errorPrefix).arg(tr("Unable to parse KML file: %1 error: %2 line: %3").arg(kmlFile).arg(errorMessage).arg(errorLine)); |
|
return QDomDocument(); |
|
} |
|
|
|
return doc; |
|
} |
|
|
|
QVariantList KMLFileHelper::determineFileContents(const QString& kmlFile) |
|
{ |
|
QString errorString; |
|
KMLFileContents fileContents = determineFileContents(kmlFile, errorString); |
|
|
|
QVariantList varList; |
|
varList.append(QVariant::fromValue(fileContents)); |
|
varList.append(QVariant::fromValue(errorString)); |
|
|
|
return varList; |
|
} |
|
|
|
KMLFileHelper::KMLFileContents KMLFileHelper::determineFileContents(const QString& kmlFile, QString& errorString) |
|
{ |
|
QDomDocument domDocument = KMLFileHelper::loadFile(kmlFile, errorString); |
|
if (!errorString.isEmpty()) { |
|
return Error; |
|
} |
|
|
|
QDomNodeList rgNodes = domDocument.elementsByTagName("Polygon"); |
|
if (rgNodes.count()) { |
|
return Polygon; |
|
} |
|
|
|
rgNodes = domDocument.elementsByTagName("LineString"); |
|
if (rgNodes.count()) { |
|
return Polyline; |
|
} |
|
|
|
errorString = QString(_errorPrefix).arg(tr("No supported type found in KML file.")); |
|
return Error; |
|
} |
|
|
|
bool KMLFileHelper::loadPolygonFromFile(const QString& kmlFile, QList<QGeoCoordinate>& vertices, QString& errorString) |
|
{ |
|
errorString.clear(); |
|
vertices.clear(); |
|
|
|
QDomDocument domDocument = KMLFileHelper::loadFile(kmlFile, errorString); |
|
if (!errorString.isEmpty()) { |
|
return false; |
|
} |
|
|
|
QDomNodeList rgNodes = domDocument.elementsByTagName("Polygon"); |
|
if (rgNodes.count() == 0) { |
|
errorString = QString(_errorPrefix).arg(tr("Unable to find Polygon node in KML")); |
|
return false; |
|
} |
|
|
|
QDomNode coordinatesNode = rgNodes.item(0).namedItem("outerBoundaryIs").namedItem("LinearRing").namedItem("coordinates"); |
|
if (coordinatesNode.isNull()) { |
|
errorString = QString(_errorPrefix).arg(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; |
|
} |
|
|
|
vertices = rgCoords; |
|
|
|
return true; |
|
} |
|
|
|
bool KMLFileHelper::loadPolylineFromFile(const QString& kmlFile, QList<QGeoCoordinate>& coords, QString& errorString) |
|
{ |
|
errorString.clear(); |
|
coords.clear(); |
|
|
|
QDomDocument domDocument = KMLFileHelper::loadFile(kmlFile, errorString); |
|
if (!errorString.isEmpty()) { |
|
return false; |
|
} |
|
|
|
QDomNodeList rgNodes = domDocument.elementsByTagName("LineString"); |
|
if (rgNodes.count() == 0) { |
|
errorString = QString(_errorPrefix).arg(tr("Unable to find LineString node in KML")); |
|
return false; |
|
} |
|
|
|
QDomNode coordinatesNode = rgNodes.item(0).namedItem("coordinates"); |
|
if (coordinatesNode.isNull()) { |
|
errorString = QString(_errorPrefix).arg(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); |
|
} |
|
|
|
coords = rgCoords; |
|
|
|
return true; |
|
}
|
|
|