Marble/Runners/DisplayGeoDataPlacemark: Difference between revisions

    From KDE TechBase
    No edit summary
    No edit summary
    (25 intermediate revisions by 6 users not shown)
    Line 1: Line 1:
    {{Template:I18n/Language Navigation Bar|Editing Projects/Marble/MarbleCPlusPlus}}
     
    {{TutorialBrowser|
    {{TutorialBrowser|


    Line 6: Line 6:
    name=Search|
    name=Search|


    pre=[[Projects/Marble/Runners/PaintingGeoDataLineString|Tutorial 10 - Using the GeoPainter in order to paint GeoDataLineString objects]]|
    pre=[[Projects/Marble/Runners/LoadingOSM|Tutorial 5 - Loading OSM files in MarbleWidget]]|


    next=
    next=[[Projects/Marble/Runners/VehicleTracking|Tutorial 7 - Vehicle Tracking]]|
    }}
    }}


    == KML Inspector ==
     
    Marble uses so-called runners to calculate routes, do reverse geocoding, parse files and search for placemarks (cities, addresses, points of interest, ...). This tutorial shows how to use the <tt>MarbleRunnerManager</tt> class to open a .kml (or .gpx, ...) file and display its structure in a tree view.
    In this tutorial we'll show how you can create a nice shiny '''placemark''' with an ''icon'' and associated '''geometries''' (such as ''LineStrings, LinearRings, Polygons or MultiGeometries''). We also cover basic '''styling''' of placemarks and geometries.
     
    [https://developers.google.com/kml/documentation/kmlreference#placemark GeoDataPlacemark] is a class which implements the features of [https://developers.google.com/kml/documentation/kmlreference#placemark KML's Placemark]. Basically, it represents an interest point (a simple point or a more complex geometry) on the map, with some information attached.  
     
    In order to add a GeoDataPlacemark to our widget, we will use the [https://developers.google.com/kml/documentation/kmlreference#document GeoDataDocument] class, which is a container for [https://developers.google.com/kml/documentation/kmlreference#feature features] (including placemarks) and [https://developers.google.com/kml/documentation/kmlreference#feature styles]. To make the Document visible, we need to add it to Marble's TreeModel, as shown in the first example below:
     


    <source lang="cpp-qt">
    <source lang="cpp-qt">
    #include <QtCore/QDebug>
    #include <QtCore/QFileInfo>
    #include <QtGui/QApplication>
    #include <QtGui/QApplication>
    #include <QtGui/QTreeView>
    #include <QtGui/QTreeView>
    #include <QtCore/QDataStream>
    #include <QtCore/QFile>
    #include <QtCore/QIODevice>


    #include <marble/MarbleWidget.h>
    #include <marble/MarbleWidget.h>
    #include <marble/GeoDataDocument.h>
    #include <marble/GeoDataPlacemark.h>
    #include <marble/GeoDataLineString.h>
    #include <marble/GeoDataTreeModel.h>
    #include <marble/MarbleModel.h>
    #include <marble/MarbleModel.h>
    #include <marble/MarbleRunnerManager.h>
    #include <marble/GeoDataTreeModel.h>


    #include <cstdio>
    using namespace Marble;
    using namespace Marble;


    int main(int argc, char** argv)
    {
        QApplication app(argc,argv);


        QFileInfo inputFile( app.arguments().last() );
    int main(int argc, char** argv) {
        if ( app.arguments().size() < 2 || !inputFile.exists() ) {
     
            qWarning() << "Usage: " << app.arguments().first() << "file.kml";
    QApplication app(argc,argv);
            return 1;
     
        }
    // Create a Marble QWidget without a parent
    MarbleWidget *mapWidget = new MarbleWidget();
       
    // Load the OpenStreetMap map
    mapWidget->setMapThemeId("earth/plain/plain.dgml");
     
    GeoDataPlacemark *place = new GeoDataPlacemark( "Bucharest" );
    place->setCoordinate( 25.97, 44.43, 0.0, GeoDataCoordinates::Degree );
    place->setPopulation( 1877155 );
    place->setCountryCode ( "Romania" );


        MarbleModel *model = new MarbleModel;
        MarbleRunnerManager* manager = new MarbleRunnerManager( model->pluginManager() );


        GeoDataDocument* document = manager->openFile( inputFile.absoluteFilePath() );
    GeoDataDocument *document = new GeoDataDocument;
        if ( document ) {
    document->append( place );
            GeoDataTreeModel* treeModel = new GeoDataTreeModel;
            treeModel->addDocument( document );
            QTreeView* treeView = new QTreeView;
            treeView->setModel( treeModel );
            treeView->show();
        } else {
            qDebug() << "Unable to open " << inputFile.absoluteFilePath();
        }


        return app.exec();
    // Add the document to MarbleWidget's tree model
    mapWidget->model()->treeModel()->addDocument( document );
    mapWidget->show();
     
    return app.exec();
    }
    }
    </source>
    </source>
    Line 61: Line 72:
    </source>
    </source>


    If things go fine, execute <tt>./my_marble some-file.kml</tt> and you get a tree view of its structure similar to this screenshot (showing the structure of a route calculated with Marble):
    If things go fine, execute <tt>./my_marble</tt> and you are going to see the placemark of our newly created Bucharest point.
     
    [[Image:PlacemarkTask_bis.png]]


    [[Image:Marble-kml-inspector.png]]
    The data we have set for our city (Population and Country) also appear, when clicking on the placemark.  


    {{tip|
    [[Image:PlacemarkTask2.png]]
    Here's a little checklist to tackle some problems that might arise when compiling the code above:


    * You need Qt and '''Marble development packages''' (or comparable git installations), version 1.3 (Marble library 0.13), shipped post KDE 4.8
    As we said earlier in this tutorial, it is possible to add more complex geometry to a placemark, meaning objects belonging to [https://developers.google.com/kml/documentation/kmlreference#geometry GeoDataGeometry] or to one of the classes which inherit it.  
    * If ''Qt headers'' are not installed in '''/usr/include/qt4''' on your system, change the path in the g++ call above accordingly.
     
    * Likewise, '''add -I /path/to/marble/headers''' if they're not to be found in /usr/include
    [https://developers.google.com/kml/documentation/kmlreference#style Styles] are another important property of placemarks. They are used in order to customize the appearance of the placemark on the map (e.g. by adding an icon). Geometries such as LineStrings, LinearRings or Polygons can be styled as well: You can change properties such as the pen color, the brush color and the line width.
    }}
     
    {{note|
    The next example shows how more complex geometry and styles can be added, by creating Bucharest's city boundary, and by adding an interest point (touristic objective) with a photo replacing the regular  placemark icon. (in order for the example to work properly you will need to download the [http://techbase.kde.org/File:Bucharest_small.jpg icon] and place it in the same folder as the source code)
    If you provide maps in your application please check the '''Terms of Use''' of the map material. The map material that is shipped with Marble is licensed ''in the spirit of Free Software''. This usually means at least that the authors should be credited and that the license is mentioned.
     
    E.g. for ''OpenStreetMap'' the license is [http://creativecommons.org/license/by-sa/2.0 CC-BY-SA]. Other map data shipped with Marble is either public domain or licensed in the spirit of the BSD license.
    <source lang="cpp-qt">
    }}
    #include <QtGui/QApplication>
    #include <QtGui/QTreeView>
     
    #include <marble/MarbleWidget.h>
    #include <marble/MarbleModel.h>
     
    #include <marble/GeoDataDocument.h>
    #include <marble/GeoDataCoordinates.h>
    #include <marble/GeoDataPlacemark.h>
    #include <marble/GeoDataLineString.h>
    #include <marble/GeoDataLinearRing.h>
    #include <marble/GeoDataTreeModel.h>
    #include <marble/GeoDataStyle.h>
    #include <marble/GeoDataIconStyle.h>
    #include <marble/GeoDataLineStyle.h>
    #include <marble/GeoDataPolyStyle.h>
     
    #include <cstdio>
    using namespace Marble;
     
    void addPoints( GeoDataLinearRing &linearRing ) {
     
    linearRing << GeoDataCoordinates(25.97226722704463, 44.43497647488007, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(26.04711276456992, 44.4420741223712, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(25.99712510557899, 44.48015825036597, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(26.11268978668501, 44.53902366720936, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(26.12777496065434, 44.48972441010599, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(26.17769825773425, 44.47685689461117, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(26.16489863910029, 44.45366647920105, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(26.23394105442375, 44.43247765101769, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(26.23388161223319, 44.40720014793351, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(26.18689640043445, 44.40683215952335, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(26.1462530009004, 44.36252655873379, 0, GeoDataCoordinates::Degree )
    << GeoDataCoordinates(25.97226722704463, 44.43497647488007, 0, GeoDataCoordinates::Degree );
     
    }
     
    void createStyleBucharest( GeoDataStyle &style ) {
    GeoDataLineStyle lineStyle( QColor( 255, 0, 0, 90 ) );
    lineStyle.setWidth ( 8 );
     
    GeoDataPolyStyle polyStyle( QColor( 255, 0, 0, 40 ) );
    polyStyle.setFill( true );
     
    style.setLineStyle( lineStyle );
    style.setPolyStyle( polyStyle );
    }
     
    void createStyleArch( GeoDataStyle &style ) {
    GeoDataIconStyle iconStyle;
    iconStyle.setIconPath( "bucharest_small.jpg" );
    style.setIconStyle( iconStyle );
    }
     
    int main(int argc, char** argv) {
     
    QApplication app(argc,argv);
     
    // Create a Marble QWidget without a parent
    MarbleWidget *mapWidget = new MarbleWidget();
       
    // Load the OpenStreetMap map
    mapWidget->setMapThemeId("earth/openstreetmap/openstreetmap.dgml");
     
    //Create the Linear Ring (polygon) representing Bucharest's boundaries and include it in a placemark
    GeoDataLinearRing *Bucharest = new GeoDataLinearRing;
    addPoints( *Bucharest );
     
    GeoDataPlacemark *placemarkBucharest = new GeoDataPlacemark;
    placemarkBucharest->setGeometry( Bucharest );
     
    //Create the placemark representing the Arch of Triumph
    GeoDataPlacemark *placemarkArch = new GeoDataPlacemark( "Arch of Triumph" );
    placemarkArch->setCoordinate( 26.0783, 44.4671, 0, GeoDataCoordinates::Degree );
     
     
    //Add styles (icons, colors, etc.) to the two placemarks
    GeoDataStyle *styleBucharest = new GeoDataStyle;
            GeoDataStyle *styleArch = new GeoDataStyle;
     
    createStyleBucharest( *styleBucharest );
    placemarkBucharest->setStyle( styleBucharest );
     
    createStyleArch ( *styleArch );
    placemarkArch->setStyle( styleArch );
     
     
    //Create the document and add the two placemarks (the point representing the Arch of Triumph and the polygon with Bucharest's boundaries)
    GeoDataDocument *document = new GeoDataDocument;
    document->append( placemarkBucharest );
    document->append( placemarkArch );
     
    // Add the document to MarbleWidget's tree model
    mapWidget->model()->treeModel()->addDocument( document );
     
            // Center the map on Bucharest and set the zoom
    mapWidget->centerOn( GeoDataCoordinates( 26.0783, 44.4671, 0, GeoDataCoordinates::Degree ) );
    mapWidget->zoomView( 2400 );
     
    mapWidget->show();
     
    return app.exec();
    }
    </source>
     
    This is the expected outcome after compiling, running and zooming into Bucharest:
     
    [[Image:Bucharest.png]]

    Revision as of 12:35, 11 October 2013

    Search
    Tutorial Series   Marble C++ Tutorial
    Previous   Tutorial 5 - Loading OSM files in MarbleWidget
    What's Next   Tutorial 7 - Vehicle Tracking
    Further Reading   n/a


    In this tutorial we'll show how you can create a nice shiny placemark with an icon and associated geometries (such as LineStrings, LinearRings, Polygons or MultiGeometries). We also cover basic styling of placemarks and geometries.

    GeoDataPlacemark is a class which implements the features of KML's Placemark. Basically, it represents an interest point (a simple point or a more complex geometry) on the map, with some information attached.

    In order to add a GeoDataPlacemark to our widget, we will use the GeoDataDocument class, which is a container for features (including placemarks) and styles. To make the Document visible, we need to add it to Marble's TreeModel, as shown in the first example below:


    #include <QtGui/QApplication>
    #include <QtGui/QTreeView>
    #include <QtCore/QDataStream>
    #include <QtCore/QFile>
    #include <QtCore/QIODevice>
    
    #include <marble/MarbleWidget.h>
    #include <marble/GeoDataDocument.h>
    #include <marble/GeoDataPlacemark.h>
    #include <marble/GeoDataLineString.h>
    #include <marble/GeoDataTreeModel.h>
    #include <marble/MarbleModel.h>
    
    #include <cstdio>
     
    using namespace Marble;
    
    
    int main(int argc, char** argv) {
    
    	QApplication app(argc,argv);
    		   
    	// Create a Marble QWidget without a parent
    	MarbleWidget *mapWidget = new MarbleWidget();
    				    
    	// Load the OpenStreetMap map
    	mapWidget->setMapThemeId("earth/plain/plain.dgml");		 
    
    	GeoDataPlacemark *place = new GeoDataPlacemark( "Bucharest" );
    	place->setCoordinate( 25.97, 44.43, 0.0, GeoDataCoordinates::Degree );
    	place->setPopulation( 1877155 );
    	place->setCountryCode ( "Romania" );
    
    
    	GeoDataDocument *document = new GeoDataDocument;
    	document->append( place );
    
    	// Add the document to MarbleWidget's tree model
    	mapWidget->model()->treeModel()->addDocument( document );
    	
    	mapWidget->show();
    								  
    	return app.exec();
    }
    

    Copy and paste the code above into a text editor. Then save it as my_marble.cpp and compile it by entering the following command on the command line:

     g++ -I /usr/include/qt4/ -o my_marble my_marble.cpp -lmarblewidget -lQtGui -lQtCore
    

    If things go fine, execute ./my_marble and you are going to see the placemark of our newly created Bucharest point.

    The data we have set for our city (Population and Country) also appear, when clicking on the placemark.

    As we said earlier in this tutorial, it is possible to add more complex geometry to a placemark, meaning objects belonging to GeoDataGeometry or to one of the classes which inherit it.

    Styles are another important property of placemarks. They are used in order to customize the appearance of the placemark on the map (e.g. by adding an icon). Geometries such as LineStrings, LinearRings or Polygons can be styled as well: You can change properties such as the pen color, the brush color and the line width.

    The next example shows how more complex geometry and styles can be added, by creating Bucharest's city boundary, and by adding an interest point (touristic objective) with a photo replacing the regular placemark icon. (in order for the example to work properly you will need to download the icon and place it in the same folder as the source code)

    #include <QtGui/QApplication>
    #include <QtGui/QTreeView>
    
    #include <marble/MarbleWidget.h>
    #include <marble/MarbleModel.h>
    
    #include <marble/GeoDataDocument.h>
    #include <marble/GeoDataCoordinates.h>
    #include <marble/GeoDataPlacemark.h>
    #include <marble/GeoDataLineString.h>
    #include <marble/GeoDataLinearRing.h>
    #include <marble/GeoDataTreeModel.h>
    #include <marble/GeoDataStyle.h>
    #include <marble/GeoDataIconStyle.h>
    #include <marble/GeoDataLineStyle.h>
    #include <marble/GeoDataPolyStyle.h>
    
    #include <cstdio>
     
    using namespace Marble;
    
    void addPoints( GeoDataLinearRing &linearRing ) {
    
    	linearRing << GeoDataCoordinates(25.97226722704463, 44.43497647488007, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(26.04711276456992, 44.4420741223712, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(25.99712510557899, 44.48015825036597, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(26.11268978668501, 44.53902366720936, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(26.12777496065434, 44.48972441010599, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(26.17769825773425, 44.47685689461117, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(26.16489863910029, 44.45366647920105, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(26.23394105442375, 44.43247765101769, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(26.23388161223319, 44.40720014793351, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(26.18689640043445, 44.40683215952335, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(26.1462530009004, 44.36252655873379, 0, GeoDataCoordinates::Degree )
    					<< GeoDataCoordinates(25.97226722704463, 44.43497647488007, 0, GeoDataCoordinates::Degree );
    
    }
    
    void createStyleBucharest( GeoDataStyle &style ) {
    	GeoDataLineStyle lineStyle( QColor( 255, 0, 0, 90 ) );
    	lineStyle.setWidth ( 8 );
    
    	GeoDataPolyStyle polyStyle( QColor( 255, 0, 0, 40 ) );
    	polyStyle.setFill( true );
    
    	style.setLineStyle( lineStyle );
    	style.setPolyStyle( polyStyle );
    }
    
    void createStyleArch( GeoDataStyle &style ) {
    	GeoDataIconStyle iconStyle;
    	iconStyle.setIconPath( "bucharest_small.jpg" );
    	style.setIconStyle( iconStyle );
    }
    
    int main(int argc, char** argv) {
    
    	QApplication app(argc,argv);
    		   
    	// Create a Marble QWidget without a parent
    	MarbleWidget *mapWidget = new MarbleWidget();
    				    
    	// Load the OpenStreetMap map
    	mapWidget->setMapThemeId("earth/openstreetmap/openstreetmap.dgml");		 
    
    	//Create the Linear Ring (polygon) representing Bucharest's boundaries and include it in a placemark
    	GeoDataLinearRing *Bucharest = new GeoDataLinearRing;
    	addPoints( *Bucharest );
    
    	GeoDataPlacemark *placemarkBucharest = new GeoDataPlacemark;
    	placemarkBucharest->setGeometry( Bucharest );
    
    	//Create the placemark representing the Arch of Triumph
    	GeoDataPlacemark *placemarkArch = new GeoDataPlacemark( "Arch of Triumph" );
    	placemarkArch->setCoordinate( 26.0783, 44.4671, 0, GeoDataCoordinates::Degree );
    
    
    	//Add styles (icons, colors, etc.) to the two placemarks
    	GeoDataStyle *styleBucharest = new GeoDataStyle;
            GeoDataStyle *styleArch = new GeoDataStyle;
    
    	createStyleBucharest( *styleBucharest );
    	placemarkBucharest->setStyle( styleBucharest );
    
    	createStyleArch ( *styleArch );
    	placemarkArch->setStyle( styleArch );
    
    
    	//Create the document and add the two placemarks (the point representing the Arch of Triumph and the polygon with Bucharest's boundaries)
    	GeoDataDocument *document = new GeoDataDocument;
    	document->append( placemarkBucharest );
    	document->append( placemarkArch );
    
    	// Add the document to MarbleWidget's tree model
    	mapWidget->model()->treeModel()->addDocument( document );
    
            // Center the map on Bucharest and set the zoom 
    	mapWidget->centerOn( GeoDataCoordinates( 26.0783, 44.4671, 0, GeoDataCoordinates::Degree ) );
    	mapWidget->zoomView( 2400 );
    
    	
    	mapWidget->show();
    								  
    	return app.exec();
    }
    

    This is the expected outcome after compiling, running and zooming into Bucharest: