diff --git a/src/plugins/runner/CMakeLists.txt b/src/plugins/runner/CMakeLists.txt --- a/src/plugins/runner/CMakeLists.txt +++ b/src/plugins/runner/CMakeLists.txt @@ -38,3 +38,11 @@ if( LIBSHP_FOUND ) add_subdirectory( shp ) endif( LIBSHP_FOUND ) + +macro_optional_find_package( GDAL 2.0.0 ) +marble_set_package_properties( GDAL PROPERTIES DESCRIPTION "Geospatial Data Abstration Library" ) +marble_set_package_properties( GDAL PROPERTIES URL "http://www.gdal.org/" ) +marble_set_package_properties( GDAL PROPERTIES TYPE OPTIONAL PURPOSE "reading datasets supported by the GDAL library" ) +if( GDAL_FOUND ) + add_subdirectory( gdal ) +endif( GDAL_FOUND ) diff --git a/src/plugins/runner/gdal/CMakeLists.txt b/src/plugins/runner/gdal/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/src/plugins/runner/gdal/CMakeLists.txt @@ -0,0 +1,16 @@ +PROJECT( GdalPlugin ) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${QT_INCLUDE_DIR} + ${GDAL_INCLUDE_DIR} +) + +set( gdal_SRCS GdalPlugin.cpp GdalRunner.cpp ) + +set( GdalPlugin_LIBS ${GDAL_LIBRARY} ) + +add_compile_options(-Wno-switch) + +marble_add_plugin( GdalPlugin ${gdal_SRCS} ) diff --git a/src/plugins/runner/gdal/GdalPlugin.h b/src/plugins/runner/gdal/GdalPlugin.h new file mode 100644 --- /dev/null +++ b/src/plugins/runner/gdal/GdalPlugin.h @@ -0,0 +1,47 @@ +// +// This file is part of the Marble Virtual Globe. +// +// This program is free software licensed under the GNU LGPL. You can +// find a copy of this license in LICENSE.txt in the top directory of +// the source code. +// +// Copyright 2016 Chris Hills + +#ifndef MARBLEGDALPLUGIN_H +#define MARBLEGDALPLUGIN_H + +#include "ParseRunnerPlugin.h" + +namespace Marble +{ + +class GdalPlugin : public ParseRunnerPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA( IID "org.kde.edu.marble.GdalPlugin" ) + Q_INTERFACES( Marble::ParseRunnerPlugin ) + +public: + explicit GdalPlugin( QObject *parent = 0 ); + + QString name() const; + + QString nameId() const; + + QString version() const; + + QString description() const; + + QString copyrightYears() const; + + QList pluginAuthors() const; + + QString fileFormatDescription() const; + + QStringList fileExtensions() const; + + virtual ParsingRunner* newRunner() const; +}; + +} +#endif // MARBLEGDALPLUGIN_H diff --git a/src/plugins/runner/gdal/GdalPlugin.cpp b/src/plugins/runner/gdal/GdalPlugin.cpp new file mode 100644 --- /dev/null +++ b/src/plugins/runner/gdal/GdalPlugin.cpp @@ -0,0 +1,85 @@ +// +// This file is part of the Marble Virtual Globe. +// +// This program is free software licensed under the GNU LGPL. You can +// find a copy of this license in LICENSE.txt in the top directory of +// the source code. +// +// Copyright 2016 Chris Hills + +#include "GdalPlugin.h" +#include "GdalRunner.h" + +#include + +namespace Marble +{ + +GdalPlugin::GdalPlugin( QObject *parent ) : + ParseRunnerPlugin( parent ) +{ + GDALAllRegister(); +} + +QString GdalPlugin::name() const +{ + return tr( "GDAL Import Plugin" ); +} + +QString GdalPlugin::nameId() const +{ + return "GDAL"; +} + +QString GdalPlugin::version() const +{ + return "1.0"; +} + +QString GdalPlugin::description() const +{ + return tr( "Create GeoDataDocument using GDAL" ); +} + +QString GdalPlugin::copyrightYears() const +{ + return "2016"; +} + +QList GdalPlugin::pluginAuthors() const +{ + return QList() + << PluginAuthor( "Chris Hills", "chaz@chaz6.com" ); +} + +QString GdalPlugin::fileFormatDescription() const +{ + return tr( "GDAL supported files" ); +} + +QStringList GdalPlugin::fileExtensions() const +{ + QStringList qslExtensions; + for ( int i=0; iGetDriverCount(); ++i ){ + GDALDriver* gDriver = GetGDALDriverManager()->GetDriver( i ); + if ( gDriver->GetMetadataItem( GDAL_DCAP_VECTOR, NULL ) ) { + QString extension( gDriver->GetMetadataItem( GDAL_DMD_EXTENSIONS, NULL ) ); + if ( extension.size() > 2 ) { + qslExtensions << extension.split(' '); + } + } + } + qslExtensions.sort(); + return qslExtensions; +} + +ParsingRunner* GdalPlugin::newRunner() const +{ + return new GdalRunner; +} + +} + +Q_EXPORT_PLUGIN2( GdalPlugin, Marble::GdalPlugin ) + +#include "moc_GdalPlugin.cpp" diff --git a/src/plugins/runner/gdal/GdalRunner.h b/src/plugins/runner/gdal/GdalRunner.h new file mode 100644 --- /dev/null +++ b/src/plugins/runner/gdal/GdalRunner.h @@ -0,0 +1,28 @@ +// +// This file is part of the Marble Virtual Globe. +// +// This program is free software licensed under the GNU LGPL. You can +// find a copy of this license in LICENSE.txt in the top directory of +// the source code. +// +// Copyright 2016 Chris Hills + +#ifndef MARBLEGDALRUNNER_H +#define MARBLEGDALRUNNER_H + +#include "ParsingRunner.h" + +namespace Marble +{ + +class GdalRunner : public ParsingRunner +{ + Q_OBJECT +public: + explicit GdalRunner(QObject *parent = 0); + ~GdalRunner(); + GeoDataDocument* parseFile( const QString &fileName, DocumentRole role, QString& error ); +}; + +} +#endif // MARBLEGDALRUNNER_H diff --git a/src/plugins/runner/gdal/GdalRunner.cpp b/src/plugins/runner/gdal/GdalRunner.cpp new file mode 100644 --- /dev/null +++ b/src/plugins/runner/gdal/GdalRunner.cpp @@ -0,0 +1,224 @@ +// +// This file is part of the Marble Virtual Globe. +// +// This program is free software licensed under the GNU LGPL. You can +// find a copy of this license in LICENSE.txt in the top directory of +// the source code. +// +// Copyright 2016 Chris Hills + +#include "GdalRunner.h" + +#include "GeoDataDocument.h" +#include "GeoDataPlacemark.h" +#include "GeoDataPolygon.h" +#include "GeoDataSchema.h" +#include "GeoDataSimpleField.h" +#include "GeoDataStyle.h" +#include "GeoDataPolyStyle.h" +#include "MarbleDebug.h" + +#include + +#include +#include + +namespace Marble +{ + +GdalRunner::GdalRunner(QObject *parent) : + ParsingRunner(parent) +{ +} + +GdalRunner::~GdalRunner() +{ +} + +GeoDataDocument *GdalRunner::parseFile( const QString &fileName, DocumentRole role, QString &error ) +{ + + GDALDataset *gDataset; + gDataset = static_cast( GDALOpenEx( fileName.toStdString().c_str(), GDAL_OF_VECTOR, NULL, NULL, NULL ) ); + + if ( gDataset == NULL ) { + error = QString("Failed to read %1").arg(fileName); + mDebug() << error; + return nullptr; + } + + if ( gDataset->GetLayerCount() < 1 ) { + mDebug() << "No layers found!"; + return nullptr; + } + + GeoDataDocument *document = new GeoDataDocument; + document->setDocumentRole( role ); + + OGRLayer *gLayer; + gLayer = gDataset->GetLayer(0); // TODO: support for multiple layers + + OGRFeature *gFeature; + gLayer->ResetReading(); + while( ( gFeature = gLayer->GetNextFeature() ) != NULL ) { + OGRGeometry *gGeometry; + gGeometry = gFeature->GetGeometryRef(); + if( gGeometry != NULL ) { + GeoDataPlacemark *placemark = 0; + placemark = new GeoDataPlacemark; + + switch( gGeometry->getGeometryType() ) { + case wkbPoint: { + OGRPoint *gPoint = static_cast( gGeometry ); + GeoDataPoint *point = new GeoDataPoint( gPoint->getX(), gPoint->getY(), 0, GeoDataCoordinates::Degree ); + document->append( placemark ); + placemark->setGeometry( point ); + mDebug() << "point " << placemark->name(); + break; + } + case wkbLineString: { + OGRLineString *gLineString = static_cast( gGeometry ); + GeoDataLineString *line = new GeoDataLineString; + OGRPoint p; + + for( int j=0; jgetNumPoints(); ++j ) { + gLineString->getPoint( j, &p ); + line->append( GeoDataCoordinates( + p.getX(), p.getY(), + 0, GeoDataCoordinates::Degree ) ); + } + + document->append( placemark ); + placemark->setGeometry( line ); + mDebug() << "arc " << placemark->name(); + break; + } + case wkbPolygon: { + OGRPolygon *gPolygon = static_cast( gGeometry ); + + GeoDataPolygon *polygon = new GeoDataPolygon; + + OGRLinearRing *gLinearRing = gPolygon->getExteriorRing(); + GeoDataLinearRing outerRing; + + for( int j=0; jgetNumPoints(); ++j ) { + OGRPoint gPoint; + gLinearRing->getPoint( j, &gPoint ); + outerRing.append( GeoDataCoordinates( + gPoint.getX(), gPoint.getY(), + 0, GeoDataCoordinates::Degree ) ); + } + polygon->setOuterBoundary( outerRing ); + + for( int j=0; jgetNumInteriorRings(); ++j ) { + GeoDataLinearRing ring; + gLinearRing = gPolygon->getInteriorRing( j ); + for( int k=0; kgetNumPoints(); ++k ) { + OGRPoint gPoint; + gLinearRing->getPoint( k, &gPoint ); + ring.append( GeoDataCoordinates( + gPoint.getX(), gPoint.getY(), + 0, GeoDataCoordinates::Degree ) ); + } + polygon->appendInnerBoundary( ring ); + } + + placemark->setGeometry( polygon ); + document->append( placemark ); + mDebug() << "polygon " << placemark->name(); + break; + } + case wkbMultiPoint: { + GeoDataMultiGeometry *multigeom = new GeoDataMultiGeometry; + + OGRMultiPoint *gMultipoint = static_cast( gGeometry ); + for (int j=0; j < gMultipoint->getNumGeometries(); ++j ){ + OGRPoint *gPoint = static_cast(gMultipoint->getGeometryRef( j ) ); + GeoDataPoint *point = new GeoDataPoint( gPoint->getX(), gPoint->getY(), 0, GeoDataCoordinates::Degree ); + multigeom->append( point ); + } + + placemark->setGeometry( multigeom ); + document->append( placemark ); + mDebug() << "multipoint " << placemark->name(); + break; + } + case wkbMultiLineString: { + GeoDataMultiGeometry *multigeom = new GeoDataMultiGeometry; + + OGRMultiLineString *gMultiLineString = static_cast( gGeometry ); + for (int j=0; j < gMultiLineString->getNumGeometries(); ++j ){ + OGRLineString *gLinestring = static_cast( gMultiLineString->getGeometryRef( j ) ); + GeoDataLineString *line = new GeoDataLineString; + + OGRPoint p; + for ( int k=0; kgetNumPoints(); ++k ) { + gLinestring->getPoint( k, &p ); + line->append( GeoDataCoordinates( + p.getX(), p.getY(), + 0, GeoDataCoordinates::Degree ) ); + } + + multigeom->append( line ); + } + placemark->setGeometry( multigeom ); + document->append( placemark ); + mDebug() << "multilinestring " << placemark->name(); + break; + } + case wkbMultiPolygon: { + GeoDataMultiGeometry *multigeom = new GeoDataMultiGeometry; + + OGRMultiPolygon *gMultiPolygon = static_cast( gGeometry ); + for ( int j=0; jgetNumGeometries(); ++j ){ + OGRPolygon *gPolygon = static_cast( gMultiPolygon->getGeometryRef( j ) ); + GeoDataPolygon *polygon = new GeoDataPolygon; + + OGRLinearRing *gLinearRing = gPolygon->getExteriorRing(); + GeoDataLinearRing outerRing; + for( int k=0; jgetNumPoints(); ++k ) { + OGRPoint gPoint; + gLinearRing->getPoint( k, &gPoint ); + outerRing.append( GeoDataCoordinates( + gPoint.getX(), gPoint.getY(), + 0, GeoDataCoordinates::Degree ) ); + } + polygon->setOuterBoundary( outerRing ); + + for( int k=0; jgetNumInteriorRings(); ++j ) { + GeoDataLinearRing ring; + gLinearRing = gPolygon->getInteriorRing( k ); + for( int l=0; kgetNumPoints(); ++l ) { + OGRPoint gPoint; + gLinearRing->getPoint( l, &gPoint ); + ring.append( GeoDataCoordinates( + gPoint.getX(), gPoint.getY(), + 0, GeoDataCoordinates::Degree ) ); + } + polygon->appendInnerBoundary( ring ); + } + multigeom->append( polygon ); + } + + placemark->setGeometry( multigeom ); + document->append( placemark ); + mDebug() << "polygon " << placemark->name(); + break; + } + } + } + } + + if ( document->size() ) { + document->setFileName( fileName ); + return document; + } else { + delete document; + return nullptr; + } + +} + +} + +#include "moc_GdalRunner.cpp"