File indexing completed on 2024-04-21 14:52:05

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2010 Dennis Nienhüser <nienhueser@kde.org>
0004 //
0005 
0006 #include <QCoreApplication>
0007 #include <QFile>
0008 #include <QFileInfo>
0009 #include <QTextStream>
0010 #include <QTime>
0011 #include <QDebug>
0012 
0013 #include "geodata/data/GeoDataLineString.h"
0014 #include "geodata/data/GeoDataLinearRing.h"
0015 #include "geodata/data/GeoDataDocument.h"
0016 #include "geodata/data/GeoDataPlacemark.h"
0017 #include "geodata/data/GeoDataMultiGeometry.h"
0018 #include "geodata/data/GeoDataStyle.h"
0019 #include "geodata/data/GeoDataStyleMap.h"
0020 #include "geodata/data/GeoDataLineStyle.h"
0021 #include "geodata/data/GeoDataData.h"
0022 #include "geodata/data/GeoDataExtendedData.h"
0023 #include "geodata/writer/GeoWriter.h"
0024 #include "geodata/handlers/kml/KmlElementDictionary.h"
0025 #include "MarbleColors.h"
0026 
0027 using namespace Marble;
0028 
0029 int usage()
0030 {
0031     qDebug() << "Usage: [options] poly2kml input.poly output.kml";
0032     qDebug() << "\tOptions store additional metadata in output.kml:";
0033     qDebug() << "\t--version aVersion";
0034     qDebug() << "\t--name aName";
0035     qDebug() << "\t--date aDate";
0036     qDebug() << "\t--payload aFilename";
0037     return 1;
0038 }
0039 
0040 QColor randomColor()
0041 {
0042     QVector<QColor> colors = QVector<QColor>() << Oxygen::aluminumGray4 << Oxygen::brickRed4;
0043     colors << Oxygen::hotOrange4 << Oxygen::forestGreen4 << Oxygen::hotOrange4;
0044     colors << Oxygen::seaBlue2 << Oxygen::skyBlue4 << Oxygen::sunYellow6;
0045     return colors.at( qrand() % colors.size() );
0046 }
0047 
0048 void parseBoundingBox( const QFileInfo &file, const QString &name,
0049                        const QString &version, const QString &date,
0050                        const QString &transport, const QString &payload,
0051                        GeoDataDocument* document )
0052 {
0053     GeoDataPlacemark* placemark = new GeoDataPlacemark;
0054     GeoDataMultiGeometry *geometry = new GeoDataMultiGeometry;
0055     QFile input( file.absoluteFilePath() );
0056     QString country = "Unknown";
0057     if ( input.open( QFile::ReadOnly ) ) {
0058         QTextStream stream( &input );
0059         country = stream.readLine();
0060         float lat( 0.0 ), lon( 0.0 );
0061         GeoDataLinearRing *box = new GeoDataLinearRing;
0062         while ( !stream.atEnd() ) {
0063             bool inside = true;
0064             QString line = stream.readLine().trimmed();
0065             QStringList entries = line.split( QLatin1Char( ' ' ), QString::SkipEmptyParts );
0066             if ( entries.size() == 1 ) {
0067                 if (entries.first() == QLatin1String("END") && inside) {
0068                     inside = false;
0069                     if (!box->isEmpty()) {
0070                         geometry->append(box);
0071                         box = new GeoDataLinearRing;
0072                     }
0073                 } else if (entries.first() == QLatin1String("END") && !inside) {
0074                     qDebug() << "END not expected here";
0075                 } else if ( entries.first().startsWith( QLatin1String( "!" ) ) ) {
0076                     qDebug() << "Warning: Negative polygons not supported, skipping";
0077                 } else {
0078                     //int number = entries.first().toInt();
0079                     inside = true;
0080                 }
0081             } else if ( entries.size() == 2 ) {
0082                 lon = entries.first().toDouble();
0083                 lat = entries.last().toDouble();
0084                 GeoDataCoordinates point( lon, lat, 0.0, GeoDataCoordinates::Degree );
0085                 *box << point;
0086             } else {
0087                 qDebug() << "Warning: Ignoring line in" << file.absoluteFilePath()
0088                          <<  "with" << entries.size() << "fields:" << line;
0089             }
0090         }
0091     }
0092 
0093     GeoDataStyle::Ptr style(new GeoDataStyle);
0094     GeoDataLineStyle lineStyle;
0095     QColor color = randomColor();
0096     color.setAlpha( 200 );
0097     lineStyle.setColor( color );
0098     lineStyle.setWidth( 4 );
0099     style->setLineStyle(lineStyle);
0100     style->setId("border");
0101 
0102     GeoDataStyleMap styleMap;
0103     styleMap.setId("map-border");
0104     styleMap.insert("normal", QLatin1Char('#') + style->id());
0105     document->addStyleMap(styleMap);
0106     document->addStyle(style);
0107 
0108     placemark->setStyleUrl(QLatin1Char('#') + styleMap.id());
0109 
0110     placemark->setName( name );
0111     if ( !version.isEmpty() ) {
0112         placemark->extendedData().addValue( GeoDataData( "version", version ) );
0113     }
0114     if ( !date.isEmpty() ) {
0115         placemark->extendedData().addValue( GeoDataData( "date", date ) );
0116     }
0117     if ( !transport.isEmpty() ) {
0118         placemark->extendedData().addValue( GeoDataData( "transport", transport ) );
0119     }
0120     if ( !payload.isEmpty() ) {
0121         placemark->extendedData().addValue( GeoDataData( "payload", payload ) );
0122     }
0123     placemark->setGeometry(geometry);
0124     document->append(placemark);
0125 }
0126 
0127 int save( GeoDataDocument* document, const QFileInfo &filename )
0128 {
0129     GeoWriter writer;
0130     writer.setDocumentType( kml::kmlTag_nameSpaceOgc22 );
0131 
0132     QFile file( filename.absoluteFilePath() );
0133     if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
0134     {
0135         qDebug() << "Cannot write to " << file.fileName();
0136         return usage();
0137     }
0138 
0139     if ( !writer.write( &file, document ) ) {
0140         qDebug() << "Can not write to " << file.fileName();
0141     }
0142     file.close();
0143     return 0;
0144 }
0145 
0146 int main( int argc, char* argv[] )
0147 {
0148     QCoreApplication app( argc, argv );
0149     if ( argc < 3 ) {
0150         usage();
0151         return 0;
0152     }
0153 
0154     QString inputFile = argv[argc-2];
0155     QString outputFile = argv[argc-1];
0156     QString name;
0157     QString version;
0158     QString date;
0159     QString transport;
0160     QString payload;
0161     for ( int i=1; i<argc-2; ++i ) {
0162         QString arg( argv[i] );
0163         if (arg == QLatin1String("--name")) {
0164             name = argv[++i];
0165         } else if (arg == QLatin1String("--version")) {
0166             version = argv[++i];
0167         } else if (arg == QLatin1String("--date")) {
0168             date = argv[++i];
0169         } else if (arg == QLatin1String("--transport")) {
0170             transport = argv[++i];
0171         } else if (arg == QLatin1String("--payload")) {
0172             payload = argv[++i];
0173         } else {
0174             usage();
0175             return 1;
0176         }
0177     }
0178 
0179     qsrand( QTime::currentTime().msec() );
0180     QFileInfo input( inputFile );
0181     if ( !input.exists() || !input.isFile() ) {
0182         qDebug() << "Invalid input file";
0183         return usage();
0184     }
0185 
0186     GeoDataDocument document;
0187     parseBoundingBox( input, name, version, date, transport, payload, &document );
0188     return save( &document, QFileInfo( outputFile ) );
0189 }