File indexing completed on 2024-06-02 03:51:04

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2015 Marius-Valeriu Stanciu <stanciumarius94@gmail.com>
0004 //
0005 
0006 // Marble
0007 #include "KmlOsmPlacemarkDataTagHandler.h"
0008 #include "KmlElementDictionary.h"
0009 #include "GeoDataExtendedData.h"
0010 #include "GeoDataGeometry.h"
0011 #include "GeoDataPlacemark.h"
0012 #include "GeoDataLinearRing.h"
0013 #include "GeoDataPolygon.h"
0014 #include "GeoDataData.h"
0015 #include "GeoParser.h"
0016 #include "GeoDataPoint.h"
0017 #include "osm/OsmPlacemarkData.h"
0018 
0019 #include <QVariant>
0020 
0021 namespace Marble
0022 {
0023 namespace kml
0024 {
0025 KML_DEFINE_TAG_HANDLER_MX( OsmPlacemarkData )
0026 
0027 GeoNode* KmlOsmPlacemarkDataTagHandler::parse( GeoParser& parser ) const
0028 {
0029     OsmPlacemarkData osmData = OsmPlacemarkData::fromParserAttributes( parser.attributes() );
0030     /* Case 1: This is the main OsmPlacemarkData of a placemark:
0031      * <Placemark>
0032      *      <ExtendedData>
0033      *          <mx:OsmPlacemarkData>
0034      * ...
0035      */
0036     if (parser.parentElement().is<GeoDataExtendedData>() && parser.parentElement(1).is<GeoDataPlacemark>()) {
0037         auto placemark = parser.parentElement(1).nodeAs<GeoDataPlacemark>();
0038         placemark->setOsmData(osmData);
0039         return &placemark->osmData();
0040     }
0041     /* Case 2: This is the OsmPlacemarkData of a Nd
0042      * <Placemark>
0043      *      <ExtendedData>
0044      *          <mx:OsmPlacemarkData>
0045      *              <mx:nd>
0046      *                  <mx:OsmPlacemarkData>
0047      * ...
0048      */
0049     else if ( parser.parentElement( 1 ).is<OsmPlacemarkData>() && parser.parentElement().is<GeoDataPoint>() ) {
0050         OsmPlacemarkData* placemarkOsmData = parser.parentElement( 1 ).nodeAs<OsmPlacemarkData>();
0051         GeoDataPoint *point = parser.parentElement().nodeAs<GeoDataPoint>();
0052         GeoDataCoordinates coordinates = point->coordinates();
0053         /* The GeoDataPoint object was only used as GeoNode wrapper for the GeoDataCoordinates
0054          * and it is no longer needed
0055          */
0056         delete point;
0057         placemarkOsmData->addNodeReference( coordinates, osmData );
0058         return &placemarkOsmData->nodeReference( coordinates );
0059     }
0060     /* Case 3: This is the OsmPlacemarkData of a polygon's member
0061      * <Placemark>
0062      *      <ExtendedData>
0063      *          <mx:OsmPlacemarkData>
0064      *              <mx:member>
0065      *                  <mx:OsmPlacemarkData>
0066      * ...
0067      */
0068     else if ( parser.parentElement( 1 ).is<OsmPlacemarkData>() && parser.parentElement().is<GeoDataLinearRing>()
0069               && parser.parentElement( 3 ).is<GeoDataPlacemark>() ) {
0070         OsmPlacemarkData *placemarkOsmData = parser.parentElement( 1 ).nodeAs<OsmPlacemarkData>();
0071         GeoDataPlacemark *placemark = parser.parentElement( 3 ).nodeAs<GeoDataPlacemark>();
0072         GeoDataLinearRing &ring = *parser.parentElement().nodeAs<GeoDataLinearRing>();
0073         GeoDataPolygon *polygon = geodata_cast<GeoDataPolygon>(placemark->geometry());
0074         if (!polygon) {
0075             return nullptr;
0076         }
0077 
0078         /* The QVector's indexOf function is perfect: returns the index of the ring
0079          * within the vector if the ring is an innerBoundary;
0080          * Else it returns -1, meaning it's an outerBoundary
0081          */
0082         int memberIndex = polygon->innerBoundaries().indexOf( ring );
0083 
0084         placemarkOsmData->addMemberReference( memberIndex, osmData );
0085         return &placemarkOsmData->memberReference( memberIndex );
0086     }
0087     return nullptr;
0088 }
0089 }
0090 }