7#include "KmlCoordinatesTagHandler.h"
9#include <QRegularExpression>
12#include "GeoDataLatLonQuad.h"
13#include "GeoDataLineString.h"
14#include "GeoDataLinearRing.h"
15#include "GeoDataModel.h"
16#include "GeoDataMultiGeometry.h"
17#include "GeoDataPlacemark.h"
18#include "GeoDataPoint.h"
19#include "GeoDataTrack.h"
21#include "KmlElementDictionary.h"
22#include "MarbleDebug.h"
23#include "MarbleGlobal.h"
29KML_DEFINE_TAG_HANDLER(coordinates)
31static const bool kmlStrictSpecs =
false;
35static GeoTagHandlerRegistrar s_handlercoordkmlTag_nameSpaceGx22(GeoParser::QualifiedName(QLatin1StringView(kmlTag_coord),
36 QLatin1StringView(kmlTag_nameSpaceGx22)),
37 new KmlcoordinatesTagHandler());
39GeoNode *KmlcoordinatesTagHandler::parse(GeoParser &parser)
const
41 Q_ASSERT(parser.isStartElement()
42 && (parser.isValidElement(QLatin1StringView(kmlTag_coordinates)) || parser.isValidElement(QLatin1StringView(kmlTag_coord))));
44 GeoStackItem parentItem = parser.parentElement();
46 if (parentItem.represents(kmlTag_Point) || parentItem.represents(kmlTag_LineString) || parentItem.represents(kmlTag_MultiGeometry)
47 || parentItem.represents(kmlTag_LinearRing) || parentItem.represents(kmlTag_LatLonQuad)) {
48 QStringList coordinatesLines;
50 QString text = parser.readElementText().trimmed();
52 if (!kmlStrictSpecs) {
54 for (
int i = 1; i < text.
size() - 1; ++i) {
55 if (text[i] == QLatin1Char(
',')) {
58 while (l > 0 && text[l].isSpace()) {
64 while (r < text.
size() && text[r].isSpace()) {
68 text.
remove(l + 1, r - l - 1).
insert(l + 1, QLatin1Char(
','));
75 int const size = text.
size();
76 for (
int i = 0; i < size; ++i) {
77 if (text[i].isSpace()) {
79 coordinatesLines.
append(text.
mid(index, i - index));
88 int coordinatesIndex = 0;
89 for (
const QString &line : coordinatesLines) {
90 const QStringList coordinates = line.trimmed().split(QLatin1Char(
','));
91 if (parentItem.represents(kmlTag_Point) && parentItem.is<GeoDataFeature>()) {
92 GeoDataCoordinates coord;
93 if (coordinates.
size() == 2) {
94 coord.
set(coordinates.
at(0).toDouble(), coordinates.
at(1).toDouble(), 0.0, GeoDataCoordinates::Degree);
95 }
else if (coordinates.
size() == 3) {
96 coord.
set(coordinates.
at(0).toDouble(), coordinates.
at(1).toDouble(), coordinates.
at(2).toDouble(), GeoDataCoordinates::Degree);
98 parentItem.nodeAs<GeoDataPlacemark>()->setCoordinate(coord);
100 GeoDataCoordinates coord;
101 if (coordinates.
size() == 2) {
102 coord.
set(DEG2RAD * coordinates.
at(0).toDouble(), DEG2RAD * coordinates.
at(1).toDouble());
103 }
else if (coordinates.
size() == 3) {
104 coord.
set(DEG2RAD * coordinates.
at(0).toDouble(), DEG2RAD * coordinates.
at(1).toDouble(), coordinates.
at(2).toDouble());
107 if (parentItem.represents(kmlTag_LineString)) {
108 parentItem.nodeAs<GeoDataLineString>()->append(coord);
109 }
else if (parentItem.represents(kmlTag_LinearRing)) {
110 parentItem.nodeAs<GeoDataLinearRing>()->append(coord);
111 }
else if (parentItem.represents(kmlTag_MultiGeometry)) {
112 auto point =
new GeoDataPoint(coord);
113 parentItem.nodeAs<GeoDataMultiGeometry>()->append(point);
114 }
else if (parentItem.represents(kmlTag_Model)) {
115 parentItem.nodeAs<GeoDataModel>()->setCoordinates(coord);
116 }
else if (parentItem.represents(kmlTag_Point)) {
118 parentItem.nodeAs<GeoDataPoint>()->setCoordinates(coord);
119 }
else if (parentItem.represents(kmlTag_LatLonQuad)) {
120 switch (coordinatesIndex) {
122 parentItem.nodeAs<GeoDataLatLonQuad>()->setBottomLeft(coord);
125 parentItem.nodeAs<GeoDataLatLonQuad>()->setBottomRight(coord);
128 parentItem.nodeAs<GeoDataLatLonQuad>()->setTopRight(coord);
131 parentItem.nodeAs<GeoDataLatLonQuad>()->setTopLeft(coord);
134 mDebug() <<
"Ignoring excessive coordinates in LatLonQuad (must not have more than 4 pairs)";
149 if (parentItem.represents(kmlTag_Track)) {
150 QString input = parser.readElementText().trimmed();
151 if (!kmlStrictSpecs) {
152 input.
replace(QRegularExpression(QStringLiteral(
"\\s*,\\s*")), QStringLiteral(
","));
154 const QStringList coordinates = input.
split(QLatin1Char(
' '));
156 GeoDataCoordinates coord;
157 if (coordinates.
size() == 2) {
158 coord.
set(DEG2RAD * coordinates.
at(0).toDouble(), DEG2RAD * coordinates.
at(1).toDouble());
159 }
else if (coordinates.
size() == 3) {
160 coord.
set(DEG2RAD * coordinates.
at(0).toDouble(), DEG2RAD * coordinates.
at(1).toDouble(), coordinates.
at(2).toDouble());
162 parentItem.nodeAs<GeoDataTrack>()->appendCoordinates(coord);
void set(qreal lon, qreal lat, qreal alt=0, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
(re)set the coordinates in a GeoDataCoordinates object
Binds a QML item to a specific geodetic location in screen coordinates.
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype size() const const
QString & insert(qsizetype position, QChar ch)
QString mid(qsizetype position, qsizetype n) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
qsizetype size() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const